Merge pull request #28 from AfoninZ/feature-accounts

Feature accounts
This commit is contained in:
Zakhar Afonin
2021-05-31 20:43:39 +03:00
committed by GitHub
7 changed files with 153 additions and 105 deletions

View File

@@ -29,17 +29,3 @@ bool AuthSession::MakeOffline(QString offline_playername)
status = PlayableOffline;
return true;
}
bool AuthSession::MakeCracked(QString offline_playername)
{
session = "-";
// Filling session with dummy data
client_token = "ff64ff64ff64ff64ff64ff64ff64ff64";
access_token = "ff64ff64ff64ff64ff64ff64ff64ff64";
// TODO: Fetch actual UUID's from Mojang API so they match with real ones
uuid = QString(QCryptographicHash::hash(offline_playername.toLocal8Bit(), QCryptographicHash::Md5).toHex());
player_name = offline_playername;
status = PlayableOffline;
return true;
}

View File

@@ -17,7 +17,6 @@ struct User
struct MULTIMC_LOGIC_EXPORT AuthSession
{
bool MakeOffline(QString offline_playername);
bool MakeCracked(QString offline_playername);
QString serializeUserProperties();

View File

@@ -38,6 +38,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
return nullptr;
}
QString loginType = object.value("loginType").toString("mojang");
QString username = object.value("username").toString("");
QString clientToken = object.value("clientToken").toString("");
QString accessToken = object.value("accessToken").toString("");
@@ -82,6 +83,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
*/
account->m_user = u;
}
account->m_loginType = loginType;
account->m_username = username;
account->m_clientToken = clientToken;
account->m_accessToken = accessToken;
@@ -106,6 +108,7 @@ MojangAccountPtr MojangAccount::createFromUsername(const QString &username)
QJsonObject MojangAccount::saveToJson() const
{
QJsonObject json;
json.insert("loginType", m_loginType);
json.insert("username", m_username);
json.insert("clientToken", m_clientToken);
json.insert("accessToken", m_accessToken);
@@ -142,6 +145,17 @@ QJsonObject MojangAccount::saveToJson() const
return json;
}
bool MojangAccount::setLoginType(const QString &loginType)
{
// TODO: Implement a cleaner validity check
if (loginType == "mojang" or loginType == "dummy")
{
m_loginType = loginType;
return true;
}
return false;
}
bool MojangAccount::setCurrentProfile(const QString &profileId)
{
for (int i = 0; i < m_profiles.length(); i++)
@@ -174,6 +188,27 @@ std::shared_ptr<YggdrasilTask> MojangAccount::login(AuthSessionPtr session, QStr
{
Q_ASSERT(m_currentTask.get() == nullptr);
// Handling alternative account types
if (m_loginType == "dummy")
{
if (session)
{
session->status = AuthSession::PlayableOnline;
session->auth_server_online = false;
fillSession(session);
}
if (!currentProfile())
{
// TODO: Proper profile support (idk how)
auto dummyProfile = AccountProfile();
dummyProfile.name = m_username;
dummyProfile.id = "-";
m_profiles.append(dummyProfile);
m_currentProfile = 0;
}
return nullptr;
}
// take care of the true offline status
if (accountStatus() == NotVerified && password.isEmpty())
{
@@ -280,7 +315,7 @@ void MojangAccount::fillSession(AuthSessionPtr session)
}
else
{
session->player_name = "Player";
session->player_name = m_username;
session->session = "-";
}
session->u = user();

View File

@@ -85,6 +85,12 @@ public: /* construction */
public: /* manipulation */
/**
* Overrides the login type on the account.
* Accepts "mojang" and "dummy". Returns false if other.
*/
bool setLoginType(const QString &loginType);
/**
* Sets the currently selected profile to the profile with the given ID string.
* If profileId is not in the list of available profiles, the function will simply return
* false.
@@ -99,6 +105,11 @@ public: /* manipulation */
void invalidateClientToken();
public: /* queries */
const QString &loginType() const
{
return m_loginType;
}
const QString &username() const
{
return m_username;
@@ -139,6 +150,11 @@ signals:
// TODO: better signalling for the various possible state changes - especially errors
protected: /* variables */
// Authentication system used.
// Usable values: "mojang", "dummy"
QString m_loginType;
// Username taken by account.
QString m_username;
// Used to identify the client - the user can have multiple clients for the same account

View File

@@ -36,27 +36,6 @@ void LaunchController::login()
{
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
// Mojang account login bypass
bool ok = false;
QString usedname = "Player";
QString name = QInputDialog::getText(m_parentWidget, tr("Player name"),
tr("Choose your offline mode player name."),
QLineEdit::Normal, "Player", &ok);
if (!ok)
{
return;
}
if (name.length())
{
usedname = name;
}
m_session = std::make_shared<AuthSession>();
m_session->MakeCracked(usedname);
launchInstance();
// Original login code
/*
// Find an account to use.
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
MojangAccountPtr account = accounts->activeAccount();
@@ -64,11 +43,11 @@ void LaunchController::login()
{
// 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"),
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
"account logged in to MultiMC."
"Would you like to open the account manager to add an account now?"),
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
m_parentWidget, tr("No Accounts"),
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
"account logged in to MultiMC."
"Would you like to open the account manager to add an account now?"),
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
if (reply == QMessageBox::Yes)
{
@@ -135,75 +114,75 @@ void LaunchController::login()
}
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)
{
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;
}
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::Undetermined:
{
qCritical() << "Received undetermined session status during login. Bye.";
tryagain = false;
emitFailed(tr("Received undetermined session status during login."));
break;
}
if (name.length())
case AuthSession::RequiresPassword:
{
usedname = name;
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;
}
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;
}
m_session->MakeOffline(usedname);
// offline flavored game from here :3
}
case AuthSession::PlayableOnline:
{
launchInstance();
tryagain = false;
return;
}
}
}
emitFailed(tr("Failed to launch."));*/
emitFailed(tr("Failed to launch."));
}
void LaunchController::launchInstance()

View File

@@ -43,13 +43,22 @@ void LoginDialog::accept()
// 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");
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 (!m_loginTask)
{
onTaskSucceeded();
} else {
m_loginTask->start();
}
}
void LoginDialog::setUserInputsEnabled(bool enable)

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>162</height>
<height>219</height>
</rect>
</property>
<property name="sizePolicy">
@@ -60,6 +60,30 @@
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="radioLayout">
<item>
<widget class="QRadioButton" name="radioMojang">
<property name="text">
<string>Mojang / Minecraft</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioDummy">
<property name="text">
<string>Offline (cracked)</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">