refactor: LaunchController

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
This commit is contained in:
Octol1ttle 2026-01-28 00:59:03 +05:00
parent ba325a6012
commit a9f3be9f45
No known key found for this signature in database
GPG key ID: B77C34313AEE1FFF
13 changed files with 192 additions and 230 deletions

View file

@ -333,7 +333,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_worldToJoin = parser.value("world"); m_worldToJoin = parser.value("world");
m_profileToUse = parser.value("profile"); m_profileToUse = parser.value("profile");
if (parser.isSet("offline")) { if (parser.isSet("offline")) {
m_offline = true; m_launchOffline = true;
m_offlineName = parser.value("offline"); m_offlineName = parser.value("offline");
} }
m_liveCheck = parser.isSet("alive"); m_liveCheck = parser.isSet("alive");
@ -350,7 +350,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
} }
// error if --launch is missing with --server or --profile // error if --launch is missing with --server or --profile
if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_offline) && if ((!m_serverToJoin.isEmpty() || !m_worldToJoin.isEmpty() || !m_profileToUse.isEmpty() || m_launchOffline) &&
m_instanceIdToLaunch.isEmpty()) { m_instanceIdToLaunch.isEmpty()) {
std::cerr << "--server, --profile and --offline can only be used in combination with --launch!" << std::endl; std::cerr << "--server, --profile and --offline can only be used in combination with --launch!" << std::endl;
m_status = Application::Failed; m_status = Application::Failed;
@ -478,7 +478,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
if (!m_profileToUse.isEmpty()) { if (!m_profileToUse.isEmpty()) {
launch.args["profile"] = m_profileToUse; launch.args["profile"] = m_profileToUse;
} }
if (m_offline) { if (m_launchOffline) {
launch.args["offline_enabled"] = "true"; launch.args["offline_enabled"] = "true";
launch.args["offline_name"] = m_offlineName; launch.args["offline_name"] = m_offlineName;
} }
@ -1348,7 +1348,7 @@ void Application::performMainStartupAction()
qDebug() << " Launching with account" << m_profileToUse; qDebug() << " Launching with account" << m_profileToUse;
} }
launch(inst, !m_offline, false, targetToJoin, accountToUse, m_offlineName); launch(inst, m_launchOffline ? LaunchMode::Offline : LaunchMode::Normal, targetToJoin, accountToUse, m_offlineName);
return; return;
} }
} }
@ -1471,7 +1471,7 @@ void Application::messageReceived(const QByteArray& message)
} }
} }
launch(instance, !offline, false, serverObject, accountObject, offlineName); launch(instance, offline ? LaunchMode::Offline : LaunchMode::Normal, serverObject, accountObject, offlineName);
} else { } else {
qWarning() << "Received invalid message" << message; qWarning() << "Received invalid message" << message;
} }
@ -1507,8 +1507,7 @@ bool Application::openJsonEditor(const QString& filename)
} }
bool Application::launch(BaseInstance* instance, bool Application::launch(BaseInstance* instance,
bool online, LaunchMode mode,
bool demo,
MinecraftTarget::Ptr targetToJoin, MinecraftTarget::Ptr targetToJoin,
MinecraftAccountPtr accountToUse, MinecraftAccountPtr accountToUse,
const QString& offlineName) const QString& offlineName)
@ -1527,8 +1526,7 @@ bool Application::launch(BaseInstance* instance,
auto& controller = extras.controller; auto& controller = extras.controller;
controller.reset(new LaunchController()); controller.reset(new LaunchController());
controller->setInstance(instance); controller->setInstance(instance);
controller->setOnline(online); controller->setLaunchMode(mode);
controller->setDemo(demo);
controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get()); controller->setProfiler(profilers().value(instance->settings()->get("Profiler").toString(), nullptr).get());
controller->setTargetToJoin(targetToJoin); controller->setTargetToJoin(targetToJoin);
controller->setAccountToUse(accountToUse); controller->setAccountToUse(accountToUse);

View file

@ -216,8 +216,7 @@ class Application : public QApplication {
public slots: public slots:
bool launch(BaseInstance* instance, bool launch(BaseInstance* instance,
bool online = true, LaunchMode mode = LaunchMode::Normal,
bool demo = false,
std::shared_ptr<MinecraftTarget> targetToJoin = nullptr, std::shared_ptr<MinecraftTarget> targetToJoin = nullptr,
shared_qobject_ptr<MinecraftAccount> accountToUse = nullptr, shared_qobject_ptr<MinecraftAccount> accountToUse = nullptr,
const QString& offlineName = QString()); const QString& offlineName = QString());
@ -311,7 +310,7 @@ class Application : public QApplication {
QString m_serverToJoin; QString m_serverToJoin;
QString m_worldToJoin; QString m_worldToJoin;
QString m_profileToUse; QString m_profileToUse;
bool m_offline = false; bool m_launchOffline = false;
QString m_offlineName; QString m_offlineName;
bool m_liveCheck = false; bool m_liveCheck = false;
QList<QUrl> m_urlsToImport; QList<QUrl> m_urlsToImport;

View file

@ -902,6 +902,7 @@ SET(LAUNCHER_SOURCES
ui/themes/CatPainter.h ui/themes/CatPainter.h
# Processes # Processes
LaunchMode.h
LaunchController.h LaunchController.h
LaunchController.cpp LaunchController.cpp

View file

@ -41,21 +41,16 @@
#include "minecraft/auth/AccountList.h" #include "minecraft/auth/AccountList.h"
#include "ui/InstanceWindow.h" #include "ui/InstanceWindow.h"
#include "ui/MainWindow.h"
#include "ui/dialogs/CustomMessageBox.h" #include "ui/dialogs/CustomMessageBox.h"
#include "ui/dialogs/MSALoginDialog.h" #include "ui/dialogs/MSALoginDialog.h"
#include "ui/dialogs/ProfileSelectDialog.h" #include "ui/dialogs/ProfileSelectDialog.h"
#include "ui/dialogs/ProfileSetupDialog.h" #include "ui/dialogs/ProfileSetupDialog.h"
#include "ui/dialogs/ProgressDialog.h" #include "ui/dialogs/ProgressDialog.h"
#include <QHostAddress>
#include <QHostInfo>
#include <QInputDialog> #include <QInputDialog>
#include <QLineEdit>
#include <QList> #include <QList>
#include <QPushButton> #include <QPushButton>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList>
#include "BuildConfig.h" #include "BuildConfig.h"
#include "JavaCommon.h" #include "JavaCommon.h"
@ -63,7 +58,7 @@
#include "tasks/Task.h" #include "tasks/Task.h"
#include "ui/dialogs/ChooseOfflineNameDialog.h" #include "ui/dialogs/ChooseOfflineNameDialog.h"
LaunchController::LaunchController() : Task() {} LaunchController::LaunchController() = default;
void LaunchController::executeTask() void LaunchController::executeTask()
{ {
@ -88,7 +83,7 @@ void LaunchController::decideAccount()
// Find an account to use. // Find an account to use.
auto accounts = APPLICATION->accounts(); auto accounts = APPLICATION->accounts();
if (accounts->count() <= 0 || !accounts->anyAccountIsValid()) { if (!accounts->anyAccountIsValid()) {
// Tell the user they need to log in at least one account in order to play. // Tell the user they need to log in at least one account in order to play.
auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"), auto reply = CustomMessageBox::selectable(m_parentWidget, tr("No Accounts"),
tr("In order to play Minecraft, you must have at least one Microsoft " tr("In order to play Minecraft, you must have at least one Microsoft "
@ -132,6 +127,89 @@ void LaunchController::decideAccount()
} }
} }
bool LaunchController::decideLaunchMode()
{
if (!m_accountToUse || m_wantedLaunchMode == LaunchMode::Demo) {
m_actualLaunchMode = LaunchMode::Demo;
return true;
}
if (m_wantedLaunchMode == LaunchMode::Normal) {
if (m_accountToUse->shouldRefresh() || m_accountToUse->accountState() == AccountState::Offline) {
// Force account refresh on the account used to launch the instance updating the AccountState
// only on first try and if it is not meant to be offline
m_accountToUse->refresh();
}
}
MinecraftAccountPtr accountToCheck = nullptr;
if (m_accountToUse->accountType() != AccountType::Offline) {
accountToCheck = m_accountToUse->ownsMinecraft() ? m_accountToUse : nullptr;
} else if (const MinecraftAccountPtr defaultAccount = APPLICATION->accounts()->defaultAccount();
defaultAccount && defaultAccount->ownsMinecraft()) {
accountToCheck = defaultAccount;
} else {
for (int i = 0; i < APPLICATION->accounts()->count(); i++) {
if (const MinecraftAccountPtr account = APPLICATION->accounts()->at(i); account->ownsMinecraft()) {
accountToCheck = account;
break;
}
}
}
if (!accountToCheck) {
m_actualLaunchMode = LaunchMode::Demo;
return true;
}
auto state = accountToCheck->accountState();
if (state == AccountState::Unchecked || state == AccountState::Errored) {
accountToCheck->refresh();
state = AccountState::Working;
}
if (state == AccountState::Working) {
// refresh is in progress, we need to wait for it to finish to proceed.
ProgressDialog progDialog(m_parentWidget);
progDialog.setSkipButton(true, tr("Abort"));
auto task = accountToCheck->currentTask();
progDialog.execWithTask(task.get());
if (task->getState() == State::AbortedByUser) {
return false;
}
state = accountToCheck->accountState();
}
QString reauthReason;
switch (state) {
case AccountState::Errored:
case AccountState::Expired: {
reauthReason = tr("'%1' has expired and needs to be reauthenticated").arg(accountToCheck->profileName());
} break;
case AccountState::Disabled: {
reauthReason = tr("The launcher's client identification has changed");
} break;
case AccountState::Gone: {
reauthReason = tr("'%1' no longer exists on the servers").arg(accountToCheck->profileName());
} break;
default: {
m_actualLaunchMode =
state == AccountState::Online && m_wantedLaunchMode == LaunchMode::Normal ? LaunchMode::Normal : LaunchMode::Offline;
return true; // All good to go
}
}
if (reauthenticateAccount(accountToCheck, reauthReason)) {
return decideLaunchMode();
}
return false;
}
bool LaunchController::askPlayDemo() bool LaunchController::askPlayDemo()
{ {
QMessageBox box(m_parentWidget); QMessageBox box(m_parentWidget);
@ -148,16 +226,26 @@ bool LaunchController::askPlayDemo()
return box.clickedButton() == demoButton; return box.clickedButton() == demoButton;
} }
QString LaunchController::askOfflineName(QString playerName, bool demo, bool* ok) QString LaunchController::askOfflineName(QString playerName, bool* ok)
{ {
if (ok != nullptr) { if (ok != nullptr) {
*ok = false; *ok = false;
} }
// we ask the user for a player name QString message;
QString message = tr("Choose your offline mode player name."); switch (m_actualLaunchMode) {
if (demo) { case LaunchMode::Normal:
message = tr("Choose your demo mode player name."); Q_ASSERT(false);
return "";
case LaunchMode::Demo:
message = tr("Choose your demo mode player name");
break;
case LaunchMode::Offline:
if (m_wantedLaunchMode == LaunchMode::Normal) {
message = tr("You are not connected to the Internet, launching in offline mode\n\n");
}
message += tr("Choose your offline mode player name");
break;
} }
QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString(); QString lastOfflinePlayerName = APPLICATION->settings()->get("LastOfflinePlayerName").toString();
@ -170,8 +258,7 @@ QString LaunchController::askOfflineName(QString playerName, bool demo, bool* ok
return {}; return {};
} }
const QString name = dialog.getUsername(); usedname = dialog.getUsername();
usedname = name;
APPLICATION->settings()->set("LastOfflinePlayerName", usedname); APPLICATION->settings()->set("LastOfflinePlayerName", usedname);
if (ok != nullptr) { if (ok != nullptr) {
@ -184,15 +271,15 @@ void LaunchController::login()
{ {
decideAccount(); decideAccount();
if (!m_accountToUse) { if (!decideLaunchMode()) {
// if no account is selected, ask about demo emitAborted();
if (!m_demo) { return;
m_demo = askPlayDemo();
} }
if (m_demo) {
// we ask the user for a player name if (m_actualLaunchMode == LaunchMode::Demo) {
if (m_wantedLaunchMode == LaunchMode::Demo || askPlayDemo()) {
bool ok = false; bool ok = false;
auto name = askOfflineName("Player", m_demo, &ok); auto name = askOfflineName("Player", &ok);
if (ok) { if (ok) {
m_session = std::make_shared<AuthSession>(); m_session = std::make_shared<AuthSession>();
static const QRegularExpression s_removeChars("[{}-]"); static const QRegularExpression s_removeChars("[{}-]");
@ -201,162 +288,45 @@ void LaunchController::login()
return; return;
} }
} }
// if no account is selected, we bail
emitFailed(tr("No account selected for launch.")); emitFailed(tr("No account selected for launch"));
return; return;
} }
// we loop until the user succeeds in logging in or gives up m_session = std::make_shared<AuthSession>();
bool tryagain = true; m_session->launchMode = m_actualLaunchMode;
unsigned int tries = 0; m_accountToUse->fillSession(m_session);
if ((m_accountToUse->accountType() != AccountType::Offline && m_accountToUse->accountState() == AccountState::Offline) || if (m_accountToUse->accountType() != AccountType::Offline) {
m_accountToUse->shouldRefresh()) { if (m_actualLaunchMode == LaunchMode::Normal && !m_accountToUse->hasProfile()) {
// Force account refresh on the account used to launch the instance updating the AccountState // Now handle setting up a profile name here...
// only on first try and if it is not meant to be offline if (ProfileSetupDialog dialog(m_accountToUse, m_parentWidget); dialog.exec() != QDialog::Accepted) {
m_accountToUse->refresh();
}
while (tryagain) {
if (tries > 0 && tries % 3 == 0) {
auto result =
QMessageBox::question(m_parentWidget, tr("Continue launch?"),
tr("It looks like we couldn't launch after %1 tries. Usually this can be fixed by logging out and "
"logging back in your Microsoft account. If that doesn't work, Minecraft authentication servers "
"may be having an outage or you may need a VPN in your region. Do you want to continue trying?")
.arg(tries));
if (result == QMessageBox::No) {
emitAborted(); emitAborted();
return; return;
} }
} }
tries++;
m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online;
m_session->demo = m_demo;
m_accountToUse->fillSession(m_session);
MinecraftAccountPtr accountToCheck;
if (m_accountToUse->ownsMinecraft())
accountToCheck = m_accountToUse;
else if (const MinecraftAccountPtr defaultAccount = APPLICATION->accounts()->defaultAccount();
defaultAccount != nullptr && defaultAccount->ownsMinecraft()) {
accountToCheck = defaultAccount;
} else {
for (int i = 0; i < APPLICATION->accounts()->count(); i++) {
MinecraftAccountPtr account = APPLICATION->accounts()->at(i);
if (account->ownsMinecraft())
accountToCheck = account;
}
}
if (accountToCheck == nullptr) {
if (!m_session->demo)
m_session->demo = askPlayDemo();
if (m_session->demo)
launchInstance();
else
emitFailed(tr("Launch cancelled - account does not own Minecraft."));
if (m_actualLaunchMode == LaunchMode::Offline && m_accountToUse->accountType() != AccountType::Offline) {
bool ok = false;
QString name = m_offlineName;
if (name.isEmpty()) {
name = askOfflineName(m_session->player_name, &ok);
if (!ok) {
emitAborted();
return; return;
} }
switch (accountToCheck->accountState()) {
case AccountState::Offline: {
m_session->wants_online = false;
}
/* fallthrough */
case AccountState::Online: {
if (!m_session->wants_online && m_accountToUse->accountType() != AccountType::Offline) {
// we ask the user for a player name
bool ok = false;
QString name;
if (m_offlineName.isEmpty()) {
name = askOfflineName(m_session->player_name, m_session->demo, &ok);
if (!ok) {
tryagain = false;
break;
}
} else {
name = m_offlineName;
} }
m_session->MakeOffline(name); m_session->MakeOffline(name);
// offline flavored game from here :3
} else if (m_accountToUse == accountToCheck && !m_accountToUse->hasProfile()) {
// 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;
} }
} }
if (m_accountToUse->accountType() == AccountType::Offline)
m_session->wants_online = false;
// we own Minecraft, there is a profile, it's all ready to go!
launchInstance(); launchInstance();
return;
}
case AccountState::Errored:
// This means some sort of soft error that we can fix with a refresh ... so let's refresh.
case AccountState::Unchecked: {
accountToCheck->refresh();
}
/* fallthrough */
case AccountState::Working: {
// refresh is in progress, we need to wait for it to finish to proceed.
ProgressDialog progDialog(m_parentWidget);
progDialog.setSkipButton(true, tr("Abort"));
auto task = accountToCheck->currentTask();
progDialog.execWithTask(task.get());
// don't retry if aborted
if (task->getState() == Task::State::AbortedByUser)
tryagain = false;
continue;
}
case AccountState::Expired: {
if (reauthenticateAccount(accountToCheck))
continue;
return;
}
case AccountState::Disabled: {
auto errorString = tr("The launcher's client identification has changed. Please remove '%1' and try again.")
.arg(accountToCheck->profileName());
QMessageBox::warning(m_parentWidget, tr("Client identification changed"), errorString, QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok);
emitFailed(errorString);
return;
}
case AccountState::Gone: {
auto errorString =
tr("'%1' no longer exists on the servers. It may have been migrated, in which case please add the new account "
"you migrated this one to.")
.arg(accountToCheck->profileName());
QMessageBox::warning(m_parentWidget, tr("Account gone"), errorString, QMessageBox::StandardButton::Ok,
QMessageBox::StandardButton::Ok);
emitFailed(errorString);
return;
}
}
}
emitFailed(tr("Failed to launch."));
} }
bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account) bool LaunchController::reauthenticateAccount(MinecraftAccountPtr account, QString reason)
{ {
auto button = QMessageBox::warning( auto button = QMessageBox::warning(
m_parentWidget, tr("Account refresh failed"), m_parentWidget, tr("Account refresh failed"), tr("%1. Do you want to reauthenticate this account?").arg(reason),
tr("'%1' has expired and needs to be reauthenticated. Do you want to reauthenticate this account?").arg(account->profileName()),
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::Yes); QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::Yes);
if (button == QMessageBox::StandardButton::Yes) { if (button == QMessageBox::StandardButton::Yes) {
auto accounts = APPLICATION->accounts(); auto accounts = APPLICATION->accounts();
@ -413,7 +383,7 @@ void LaunchController::launchInstance()
// Prepend Online and Auth Status // Prepend Online and Auth Status
QString online_mode; QString online_mode;
if (m_session->wants_online) { if (m_actualLaunchMode == LaunchMode::Normal) {
online_mode = "online"; online_mode = "online";
// Prepend Server Status // Prepend Server Status
@ -421,7 +391,7 @@ void LaunchController::launchInstance()
m_launcher->prependStep(makeShared<PrintServers>(m_launcher, servers)); m_launcher->prependStep(makeShared<PrintServers>(m_launcher, servers));
} else { } else {
online_mode = m_demo ? "demo" : "offline"; online_mode = m_actualLaunchMode == LaunchMode::Demo ? "demo" : "offline";
} }
m_launcher->prependStep(makeShared<TextPrint>(m_launcher, "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher)); m_launcher->prependStep(makeShared<TextPrint>(m_launcher, "Launched instance in " + online_mode + " mode\n", MessageLevel::Launcher));

View file

@ -36,12 +36,12 @@
#pragma once #pragma once
#include <BaseInstance.h> #include <BaseInstance.h>
#include <tools/BaseProfiler.h> #include <tools/BaseProfiler.h>
#include <QObject>
#include "minecraft/auth/MinecraftAccount.h" #include "minecraft/auth/MinecraftAccount.h"
#include "minecraft/launch/MinecraftTarget.h" #include "minecraft/launch/MinecraftTarget.h"
class InstanceWindow; class InstanceWindow;
class LaunchController : public Task { class LaunchController : public Task {
Q_OBJECT Q_OBJECT
public: public:
@ -54,12 +54,10 @@ class LaunchController : public Task {
BaseInstance* instance() { return m_instance; } BaseInstance* instance() { return m_instance; }
void setOnline(bool online) { m_online = online; } void setLaunchMode(const LaunchMode mode) { m_wantedLaunchMode = mode; }
void setOfflineName(const QString& offlineName) { m_offlineName = offlineName; } void setOfflineName(const QString& offlineName) { m_offlineName = offlineName; }
void setDemo(bool demo) { m_demo = demo; }
void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; } void setProfiler(BaseProfilerFactory* profiler) { m_profiler = profiler; }
void setParentWidget(QWidget* widget) { m_parentWidget = widget; } void setParentWidget(QWidget* widget) { m_parentWidget = widget; }
@ -76,9 +74,10 @@ class LaunchController : public Task {
void login(); void login();
void launchInstance(); void launchInstance();
void decideAccount(); void decideAccount();
bool decideLaunchMode();
bool askPlayDemo(); bool askPlayDemo();
QString askOfflineName(QString playerName, bool demo, bool* ok = nullptr); QString askOfflineName(QString playerName, bool* ok = nullptr);
bool reauthenticateAccount(MinecraftAccountPtr account); bool reauthenticateAccount(MinecraftAccountPtr account, QString reason);
private slots: private slots:
void readyForLaunch(); void readyForLaunch();
@ -88,10 +87,10 @@ class LaunchController : public Task {
void onProgressRequested(Task* task); void onProgressRequested(Task* task);
private: private:
LaunchMode m_wantedLaunchMode = LaunchMode::Normal;
LaunchMode m_actualLaunchMode = LaunchMode::Normal;
BaseProfilerFactory* m_profiler = nullptr; BaseProfilerFactory* m_profiler = nullptr;
bool m_online = true;
QString m_offlineName; QString m_offlineName;
bool m_demo = false;
BaseInstance* m_instance; BaseInstance* m_instance;
QWidget* m_parentWidget = nullptr; QWidget* m_parentWidget = nullptr;
InstanceWindow* m_console = nullptr; InstanceWindow* m_console = nullptr;

25
launcher/LaunchMode.h Normal file
View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2026 Octol1ttle <l1ttleofficial@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
enum class LaunchMode {
Normal,
Offline,
Demo,
};

View file

@ -313,8 +313,8 @@ void MinecraftInstance::populateLaunchMenu(QMenu* menu)
normalLaunchDemo->setEnabled(supportsDemo()); normalLaunchDemo->setEnabled(supportsDemo());
connect(normalLaunch, &QAction::triggered, [this] { APPLICATION->launch(this); }); connect(normalLaunch, &QAction::triggered, [this] { APPLICATION->launch(this); });
connect(normalLaunchOffline, &QAction::triggered, [this] { APPLICATION->launch(this, false, false); }); connect(normalLaunchOffline, &QAction::triggered, [this] { APPLICATION->launch(this, LaunchMode::Offline); });
connect(normalLaunchDemo, &QAction::triggered, [this] { APPLICATION->launch(this, false, true); }); connect(normalLaunchDemo, &QAction::triggered, [this] { APPLICATION->launch(this, LaunchMode::Demo); });
QString profilersTitle = tr("Profilers"); QString profilersTitle = tr("Profilers");
menu->addSeparator()->setText(profilersTitle); menu->addSeparator()->setText(profilersTitle);
@ -774,7 +774,7 @@ QStringList MinecraftInstance::processMinecraftArgs(AuthSessionPtr session, Mine
tokenMapping["user_properties"] = session->serializeUserProperties(); tokenMapping["user_properties"] = session->serializeUserProperties();
tokenMapping["user_type"] = session->user_type; tokenMapping["user_type"] = session->user_type;
if (session->demo) { if (session->launchMode == LaunchMode::Demo) {
args_pattern += " --demo"; args_pattern += " --demo";
} }
} }
@ -1153,7 +1153,7 @@ LaunchTask* MinecraftInstance::createLaunchTask(AuthSessionPtr session, Minecraf
// load meta // load meta
{ {
auto mode = session->status != AuthSession::PlayableOffline ? Net::Mode::Online : Net::Mode::Offline; auto mode = session->launchMode != LaunchMode::Offline ? Net::Mode::Online : Net::Mode::Offline;
process->appendStep(makeShared<TaskStepWrapper>(pptr, makeShared<MinecraftLoadAndCheck>(this, mode))); process->appendStep(makeShared<TaskStepWrapper>(pptr, makeShared<MinecraftLoadAndCheck>(this, mode)));
} }
@ -1170,11 +1170,9 @@ LaunchTask* MinecraftInstance::createLaunchTask(AuthSessionPtr session, Minecraf
process->appendStep(step); process->appendStep(step);
} }
// if we aren't in offline mode,. // if we aren't in offline mode
if (session->status != AuthSession::PlayableOffline) { if (session->launchMode != LaunchMode::Offline) {
if (!session->demo) {
process->appendStep(makeShared<ClaimAccount>(pptr, session)); process->appendStep(makeShared<ClaimAccount>(pptr, session));
}
for (auto t : createUpdateTask()) { for (auto t : createUpdateTask()) {
process->appendStep(makeShared<TaskStepWrapper>(pptr, t)); process->appendStep(makeShared<TaskStepWrapper>(pptr, t));
} }

View file

@ -20,23 +20,17 @@ QString AuthSession::serializeUserProperties()
bool AuthSession::MakeOffline(QString offline_playername) bool AuthSession::MakeOffline(QString offline_playername)
{ {
if (status != PlayableOffline && status != PlayableOnline) {
return false;
}
session = "-"; session = "-";
access_token = "0"; access_token = "0";
player_name = offline_playername; player_name = offline_playername;
status = PlayableOffline;
return true; return true;
} }
void AuthSession::MakeDemo(QString name, QString u) void AuthSession::MakeDemo(QString name, QString u)
{ {
wants_online = false;
demo = true;
uuid = u; uuid = u;
session = "-"; session = "-";
access_token = "0"; access_token = "0";
player_name = name; player_name = name;
status = PlayableOnline; // needs online to download the assets launchMode = LaunchMode::Demo;
}; };

View file

@ -3,6 +3,8 @@
#include <QString> #include <QString>
#include <memory> #include <memory>
#include "LaunchMode.h"
class MinecraftAccount; class MinecraftAccount;
struct AuthSession { struct AuthSession {
@ -11,16 +13,6 @@ struct AuthSession {
QString serializeUserProperties(); QString serializeUserProperties();
enum Status {
Undetermined,
RequiresOAuth,
RequiresPassword,
RequiresProfileSetup,
PlayableOffline,
PlayableOnline,
GoneOrMigrated
} status = Undetermined;
// combined session ID // combined session ID
QString session; QString session;
// volatile auth token // volatile auth token
@ -29,15 +21,10 @@ struct AuthSession {
QString player_name; QString player_name;
// profile ID // profile ID
QString uuid; QString uuid;
// 'legacy' or 'mojang', depending on account type // 'msa' or 'offline', depending on account type
QString user_type; QString user_type;
// Did the auth server reply? // the actual launch mode for this session
bool auth_server_online = false; LaunchMode launchMode;
// Did the user request online mode?
bool wants_online = true;
// Is this a demo session?
bool demo = false;
}; };
using AuthSessionPtr = std::shared_ptr<AuthSession>; using AuthSessionPtr = std::shared_ptr<AuthSession>;

View file

@ -236,15 +236,6 @@ bool MinecraftAccount::shouldRefresh() const
void MinecraftAccount::fillSession(AuthSessionPtr session) void MinecraftAccount::fillSession(AuthSessionPtr session)
{ {
static const QRegularExpression s_removeChars("[{}-]"); static const QRegularExpression s_removeChars("[{}-]");
if (ownsMinecraft() && !hasProfile()) {
session->status = AuthSession::RequiresProfileSetup;
} else {
if (session->wants_online) {
session->status = AuthSession::PlayableOnline;
} else {
session->status = AuthSession::PlayableOffline;
}
}
// volatile auth token // volatile auth token
session->access_token = data.accessToken(); session->access_token = data.accessToken();

View file

@ -6,7 +6,7 @@
ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session) : LaunchStep(parent) ClaimAccount::ClaimAccount(LaunchTask* parent, AuthSessionPtr session) : LaunchStep(parent)
{ {
if (session->status == AuthSession::Status::PlayableOnline && !session->demo) { if (session->launchMode == LaunchMode::Normal) {
auto accounts = APPLICATION->accounts(); auto accounts = APPLICATION->accounts();
m_account = accounts->getAccountByProfileName(session->player_name); m_account = accounts->getAccountByProfileName(session->player_name);
} }
@ -16,8 +16,8 @@ void ClaimAccount::executeTask()
{ {
if (m_account) { if (m_account) {
lock.reset(new UseLock(m_account.get())); lock.reset(new UseLock(m_account.get()));
emitSucceeded();
} }
emitSucceeded();
} }
void ClaimAccount::finalize() void ClaimAccount::finalize()

View file

@ -757,7 +757,7 @@ void ServersPage::on_actionMove_Down_triggered()
void ServersPage::on_actionJoin_triggered() void ServersPage::on_actionJoin_triggered()
{ {
const auto& address = m_model->at(currentServer)->m_address; const auto& address = m_model->at(currentServer)->m_address;
APPLICATION->launch(m_inst, true, false, std::make_shared<MinecraftTarget>(MinecraftTarget::parse(address, false))); APPLICATION->launch(m_inst, LaunchMode::Normal, std::make_shared<MinecraftTarget>(MinecraftTarget::parse(address, false)));
} }
void ServersPage::on_actionRefresh_triggered() void ServersPage::on_actionRefresh_triggered()

View file

@ -471,7 +471,7 @@ void WorldListPage::on_actionJoin_triggered()
} }
auto worldVariant = m_worlds->data(index, WorldList::ObjectRole); auto worldVariant = m_worlds->data(index, WorldList::ObjectRole);
auto world = (World*)worldVariant.value<void*>(); auto world = (World*)worldVariant.value<void*>();
APPLICATION->launch(m_inst, true, false, std::make_shared<MinecraftTarget>(MinecraftTarget::parse(world->folderName(), true))); APPLICATION->launch(m_inst, LaunchMode::Normal, std::make_shared<MinecraftTarget>(MinecraftTarget::parse(world->folderName(), true)));
} }
#include "WorldListPage.moc" #include "WorldListPage.moc"