mirror of
https://github.com/UltimMC/Launcher.git
synced 2026-01-04 14:28:09 +00:00
@@ -29,17 +29,3 @@ bool AuthSession::MakeOffline(QString offline_playername)
|
|||||||
status = PlayableOffline;
|
status = PlayableOffline;
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ struct User
|
|||||||
struct MULTIMC_LOGIC_EXPORT AuthSession
|
struct MULTIMC_LOGIC_EXPORT AuthSession
|
||||||
{
|
{
|
||||||
bool MakeOffline(QString offline_playername);
|
bool MakeOffline(QString offline_playername);
|
||||||
bool MakeCracked(QString offline_playername);
|
|
||||||
|
|
||||||
QString serializeUserProperties();
|
QString serializeUserProperties();
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString loginType = object.value("loginType").toString("mojang");
|
||||||
QString username = object.value("username").toString("");
|
QString username = object.value("username").toString("");
|
||||||
QString clientToken = object.value("clientToken").toString("");
|
QString clientToken = object.value("clientToken").toString("");
|
||||||
QString accessToken = object.value("accessToken").toString("");
|
QString accessToken = object.value("accessToken").toString("");
|
||||||
@@ -82,6 +83,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object)
|
|||||||
*/
|
*/
|
||||||
account->m_user = u;
|
account->m_user = u;
|
||||||
}
|
}
|
||||||
|
account->m_loginType = loginType;
|
||||||
account->m_username = username;
|
account->m_username = username;
|
||||||
account->m_clientToken = clientToken;
|
account->m_clientToken = clientToken;
|
||||||
account->m_accessToken = accessToken;
|
account->m_accessToken = accessToken;
|
||||||
@@ -106,6 +108,7 @@ MojangAccountPtr MojangAccount::createFromUsername(const QString &username)
|
|||||||
QJsonObject MojangAccount::saveToJson() const
|
QJsonObject MojangAccount::saveToJson() const
|
||||||
{
|
{
|
||||||
QJsonObject json;
|
QJsonObject json;
|
||||||
|
json.insert("loginType", m_loginType);
|
||||||
json.insert("username", m_username);
|
json.insert("username", m_username);
|
||||||
json.insert("clientToken", m_clientToken);
|
json.insert("clientToken", m_clientToken);
|
||||||
json.insert("accessToken", m_accessToken);
|
json.insert("accessToken", m_accessToken);
|
||||||
@@ -142,6 +145,17 @@ QJsonObject MojangAccount::saveToJson() const
|
|||||||
return json;
|
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)
|
bool MojangAccount::setCurrentProfile(const QString &profileId)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_profiles.length(); i++)
|
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);
|
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
|
// take care of the true offline status
|
||||||
if (accountStatus() == NotVerified && password.isEmpty())
|
if (accountStatus() == NotVerified && password.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -280,7 +315,7 @@ void MojangAccount::fillSession(AuthSessionPtr session)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
session->player_name = "Player";
|
session->player_name = m_username;
|
||||||
session->session = "-";
|
session->session = "-";
|
||||||
}
|
}
|
||||||
session->u = user();
|
session->u = user();
|
||||||
|
|||||||
@@ -85,6 +85,12 @@ public: /* construction */
|
|||||||
|
|
||||||
public: /* manipulation */
|
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.
|
* 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
|
* If profileId is not in the list of available profiles, the function will simply return
|
||||||
* false.
|
* false.
|
||||||
@@ -99,6 +105,11 @@ public: /* manipulation */
|
|||||||
void invalidateClientToken();
|
void invalidateClientToken();
|
||||||
|
|
||||||
public: /* queries */
|
public: /* queries */
|
||||||
|
const QString &loginType() const
|
||||||
|
{
|
||||||
|
return m_loginType;
|
||||||
|
}
|
||||||
|
|
||||||
const QString &username() const
|
const QString &username() const
|
||||||
{
|
{
|
||||||
return m_username;
|
return m_username;
|
||||||
@@ -139,6 +150,11 @@ signals:
|
|||||||
// TODO: better signalling for the various possible state changes - especially errors
|
// TODO: better signalling for the various possible state changes - especially errors
|
||||||
|
|
||||||
protected: /* variables */
|
protected: /* variables */
|
||||||
|
// Authentication system used.
|
||||||
|
// Usable values: "mojang", "dummy"
|
||||||
|
QString m_loginType;
|
||||||
|
|
||||||
|
// Username taken by account.
|
||||||
QString m_username;
|
QString m_username;
|
||||||
|
|
||||||
// Used to identify the client - the user can have multiple clients for the same account
|
// Used to identify the client - the user can have multiple clients for the same account
|
||||||
|
|||||||
@@ -36,27 +36,6 @@ void LaunchController::login()
|
|||||||
{
|
{
|
||||||
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
|
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.
|
// Find an account to use.
|
||||||
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
|
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
|
||||||
MojangAccountPtr account = accounts->activeAccount();
|
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.
|
// Tell the user they need to log in at least one account in order to play.
|
||||||
auto reply = CustomMessageBox::selectable(
|
auto reply = CustomMessageBox::selectable(
|
||||||
m_parentWidget, tr("No Accounts"),
|
m_parentWidget, tr("No Accounts"),
|
||||||
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
||||||
"account logged in to MultiMC."
|
"account logged in to MultiMC."
|
||||||
"Would you like to open the account manager to add an account now?"),
|
"Would you like to open the account manager to add an account now?"),
|
||||||
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
|
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes)
|
if (reply == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
@@ -135,75 +114,75 @@ void LaunchController::login()
|
|||||||
}
|
}
|
||||||
switch (m_session->status)
|
switch (m_session->status)
|
||||||
{
|
{
|
||||||
case AuthSession::Undetermined:
|
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)
|
|
||||||
{
|
{
|
||||||
|
qCritical() << "Received undetermined session status during login. Bye.";
|
||||||
tryagain = false;
|
tryagain = false;
|
||||||
|
emitFailed(tr("Received undetermined session status during login."));
|
||||||
break;
|
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()
|
void LaunchController::launchInstance()
|
||||||
|
|||||||
@@ -43,13 +43,22 @@ void LoginDialog::accept()
|
|||||||
|
|
||||||
// Setup the login task and start it
|
// Setup the login task and start it
|
||||||
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
|
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());
|
m_loginTask = m_account->login(nullptr, ui->passTextBox->text());
|
||||||
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
||||||
connect(m_loginTask.get(), &Task::succeeded, this,
|
connect(m_loginTask.get(), &Task::succeeded, this,
|
||||||
&LoginDialog::onTaskSucceeded);
|
&LoginDialog::onTaskSucceeded);
|
||||||
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
||||||
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
|
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)
|
void LoginDialog::setUserInputsEnabled(bool enable)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>400</width>
|
||||||
<height>162</height>
|
<height>219</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -60,6 +60,30 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|||||||
Reference in New Issue
Block a user