Skip to content

Commit

Permalink
Merge offline patch
Browse files Browse the repository at this point in the history
  • Loading branch information
zotanmew committed Feb 11, 2021
1 parent 1edcd9b commit 1642383
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 99 deletions.
4 changes: 3 additions & 1 deletion api/logic/minecraft/MinecraftInstance.cpp
Expand Up @@ -826,7 +826,9 @@ shared_qobject_ptr<LaunchTask> MinecraftInstance::createLaunchTask(AuthSessionPt
}
else
{
process->appendStep(new Update(pptr, Net::Mode::Offline));
// Offline mode based by this code:
// https://github.com/MultiMC/MultiMC5/commit/6ede3c13b2bcda315e65dd78f2bfd729bc8b699b
process->appendStep(new Update(pptr, Net::Mode::Online));
}

// if there are any jar mods
Expand Down
18 changes: 18 additions & 0 deletions api/logic/minecraft/auth/MojangAccount.cpp
Expand Up @@ -28,6 +28,8 @@

#include <QDebug>

#include <QCryptographicHash>

MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
{
// The JSON object must at least have a username for it to be valid.
Expand Down Expand Up @@ -103,6 +105,22 @@ MojangAccountPtr MojangAccount::createFromUsername(const QString &username)
return account;
}

MojangAccountPtr MojangAccount::createFromUsernameOffline(const QString &username)
{
// Offline mode based by this code:
// https://github.com/MultiMC/MultiMC5/commit/6ede3c13b2bcda315e65dd78f2bfd729bc8b699b
MojangAccountPtr account(new MojangAccount());
account->m_clientToken = "ff64ff64ff64ff64ff64ff64ff64ff64";
account->m_accessToken = "ff64ff64ff64ff64ff64ff64ff64ff64";
account->m_username = username;
QList<AccountProfile> profiles;
QString uuid = QCryptographicHash::hash(username.toLocal8Bit(), QCryptographicHash::Md5).toHex();
profiles.append({uuid, username, false});
account->m_profiles = profiles;
account->setCurrentProfile(uuid);
return account;
}

QJsonObject MojangAccount::saveToJson() const
{
QJsonObject json;
Expand Down
3 changes: 3 additions & 0 deletions api/logic/minecraft/auth/MojangAccount.h
Expand Up @@ -77,6 +77,9 @@ class MULTIMC_LOGIC_EXPORT MojangAccount :
//! Creates an empty account for the specified user name.
static MojangAccountPtr createFromUsername(const QString &username);

//! Creates an offline account
static MojangAccountPtr createFromUsernameOffline(const QString &username);

//! Loads a MojangAccount from the given JSON object.
static MojangAccountPtr loadFromJson(const QJsonObject &json);

Expand Down
184 changes: 98 additions & 86 deletions application/LaunchController.cpp
Expand Up @@ -78,111 +78,123 @@ void LaunchController::login()
return;
}

// we try empty password first :)
QString password;
// we loop until the user succeeds in logging in or gives up
bool tryagain = true;
// the failure. the default failure.
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter your password to log in again. <br /> <br /> This could be caused by a password change.");
QString failReason = needLoginAgain;
if(account->clientToken() != "ff64ff64ff64ff64ff64ff64ff64ff64") {
// Online
// we try empty password first :)
QString password;
// we loop until the user succeeds in logging in or gives up
bool tryagain = true;
// the failure. the default failure.
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter your password to log in again. <br /> <br /> This could be caused by a password change.");
QString failReason = needLoginAgain;

while (tryagain)
{
m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online;
auto task = account->login(m_session, password);
if (task)
while (tryagain)
{
// We'll need to validate the access token to make sure the account
// is still logged in.
ProgressDialog progDialog(m_parentWidget);
if (m_online)
m_session = std::make_shared<AuthSession>();
m_session->wants_online = m_online;
auto task = account->login(m_session, password);
if (task)
{
progDialog.setSkipButton(true, tr("Play Offline"));
}
progDialog.execWithTask(task.get());
if (!task->wasSuccessful())
{
auto failReasonNew = task->failReason();
if(failReasonNew == "Invalid token.")
// We'll need to validate the access token to make sure the account
// is still logged in.
ProgressDialog progDialog(m_parentWidget);
if (m_online)
{
account->invalidateClientToken();
failReason = needLoginAgain;
progDialog.setSkipButton(true, tr("Play Offline"));
}
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."));
break;
}
case AuthSession::RequiresPassword:
{
EditAccountDialog passDialog(failReason, m_parentWidget, EditAccountDialog::PasswordField);
auto username = m_session->username;
auto chopN = [](QString toChop, int N) -> QString
{
if(toChop.size() > N)
progDialog.execWithTask(task.get());
if (!task->wasSuccessful())
{
auto left = toChop.left(N);
left += QString("\u25CF").repeated(toChop.size() - N);
return left;
auto failReasonNew = task->failReason();
if(failReasonNew == "Invalid token.")
{
account->invalidateClientToken();
failReason = needLoginAgain;
}
else failReason = failReasonNew;
}
return toChop;
};

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_session->status)
{
password = passDialog.password();
}
else
case AuthSession::Undetermined:
{
qCritical() << "Received undetermined session status during login. Bye.";
tryagain = false;
emitFailed(tr("Received undetermined session status during login."));
break;
}
break;
}
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)
case AuthSession::RequiresPassword:
{
tryagain = false;
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;
};

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)
{
password = passDialog.password();
}
else
{
tryagain = false;
}
break;
}
if (name.length())
case AuthSession::PlayableOffline:
{
usedname = name;
// 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;
}
}
m_session->MakeOffline(usedname);
// offline flavored game from here :3
}
case AuthSession::PlayableOnline:
{
launchInstance();
tryagain = false;
return;
}
}
emitFailed(tr("Failed to launch."));
}else{
// Offline
m_session = std::make_shared<AuthSession>();
m_session->client_token = account->clientToken();
m_session->access_token = account->accessToken();
m_session->uuid = account->currentProfile()->id;
m_session->status = AuthSession::PlayableOffline;
m_session->MakeOffline(account->currentProfile()->name);
launchInstance();
}
emitFailed(tr("Failed to launch."));
}

void LaunchController::launchInstance()
Expand Down
29 changes: 18 additions & 11 deletions application/dialogs/LoginDialog.cpp
Expand Up @@ -41,15 +41,22 @@ void LoginDialog::accept()
setUserInputsEnabled(false);
ui->progressBar->setVisible(true);

// Setup the login task and start it
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
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,
&LoginDialog::onTaskSucceeded);
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
m_loginTask->start();
if(!ui->passTextBox->text().isEmpty()){
// Online mode
// Setup the login task and start it
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
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,
&LoginDialog::onTaskSucceeded);
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
m_loginTask->start();
}else{
// Offline mode
m_account = MojangAccount::createFromUsernameOffline(ui->userTextBox->text());
QDialog::accept();
}
}

void LoginDialog::setUserInputsEnabled(bool enable)
Expand All @@ -63,12 +70,12 @@ void LoginDialog::setUserInputsEnabled(bool enable)
void LoginDialog::on_userTextBox_textEdited(const QString &newText)
{
ui->buttonBox->button(QDialogButtonBox::Ok)
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
->setEnabled(!newText.isEmpty());
}
void LoginDialog::on_passTextBox_textEdited(const QString &newText)
{
ui->buttonBox->button(QDialogButtonBox::Ok)
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
->setEnabled(!ui->userTextBox->text().isEmpty());
}

void LoginDialog::onTaskFailed(const QString &reason)
Expand Down
18 changes: 17 additions & 1 deletion application/dialogs/LoginDialog.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>162</height>
<height>250</height>
</rect>
</property>
<property name="sizePolicy">
Expand All @@ -33,6 +33,22 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Note: For offline mode use &quot;Email&quot; field for username and &quot;Password&quot; field leave blank</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="userTextBox">
<property name="placeholderText">
Expand Down

0 comments on commit 1642383

Please sign in to comment.