diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 58596fa041..717fbb6851 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -13,7 +13,7 @@ Before submitting this issue, please make sure you have: 5. Place all information below the ---- of lines. - It makes the issue look pretty -If you believe your issue to be a bug, please make sure you check the wiki page: https://github.com/MultiMC/MultiMC5/wiki/Report-a-Bug +If you believe your issue to be a bug, please make sure you check the wiki page: https://github.com/Ponywka/MultiMC5-with-offline/wiki/Report-a-Bug --> System Information @@ -44,7 +44,7 @@ Suspected cause: Logs/Screenshots: ---------------------------- -[//]: # (Please refer to https://github.com/MultiMC/MultiMC5/wiki/Log-Upload for instructions on how to attach your logs.) +[//]: # (Please refer to https://github.com/Ponywka/MultiMC5-with-offline/wiki/Log-Upload for instructions on how to attach your logs.) Additional Info: diff --git a/BUILD.md b/BUILD.md index 9f0061a00b..29f16949cd 100644 --- a/BUILD.md +++ b/BUILD.md @@ -22,7 +22,7 @@ an administrator/root level account. Don't use `sudo`. It won't work and it's no Clone the source code using git and grab all the submodules: ``` -git clone git@github.com:MultiMC/MultiMC5.git +git clone git@github.com:Ponywka/MultiMC5-Cracked.git git submodule init git submodule update ``` @@ -50,7 +50,7 @@ mkdir ~/MultiMC && cd ~/MultiMC mkdir build mkdir install # clone the complete source -git clone --recursive https://github.com/MultiMC/MultiMC5.git src +git clone --recursive https://github.com/Ponywka/MultiMC5-Cracked.git src # configure the project cd build cmake -DCMAKE_INSTALL_PREFIX=../install ../src @@ -143,7 +143,7 @@ Getting the project to build and run on Windows is easy if you use Qt's IDE, Qt **These build instructions worked for me (Drayshak) on a fresh Windows 8 x64 Professional install. If they don't work for you, let us know on IRC ([Esper/#MultiMC](http://webchat.esper.net/?nick=&channels=MultiMC))!** ### Compile from command line on Windows 1. If you installed Qt with the web installer, there should be a shortcut called `Qt 5.4 for Desktop (MinGW 4.9 32-bit)` in the Start menu on Windows 7 and 10. Best way to find it is to search for it. Do note you cannot just use cmd.exe, you have to use the shortcut, otherwise the proper MinGW software will not be on the PATH. -2. Once that is open, change into your user directory, and clone MultiMC by doing `git clone --recursive https://github.com/MultiMC/MultiMC5.git`, and change directory to the folder you cloned to. +2. Once that is open, change into your user directory, and clone MultiMC by doing `git clone --recursive https://github.com/Ponywka/MultiMC5-Cracked.git`, and change directory to the folder you cloned to. 3. Make a build directory, and change directory to the directory and do `cmake -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=C:\Path\that\makes\sense\for\you`. By default, it will install to C:\Program Files (x86), which you might not want, if you want a local installation. If you want to install it to that directory, make sure to run the command window as administrator. 3. Do `mingw32-make -jX`, where X is the number of cores your CPU has plus one. 4. Now to wait for it to compile. This could take some time. Hopefully it compiles properly. @@ -168,7 +168,7 @@ brew install cmake Pick an installation path - this is where the final `.app` will be constructed when you run `make install`. Supply it as the `CMAKE_INSTALL_PREFIX` argument during CMake configuration. ``` -git clone https://github.com/MultiMC/MultiMC5.git +git clone https://github.com/Ponywka/MultiMC5-with-offline.git cd MultiMC5 git submodule init git submodule update diff --git a/README.md b/README.md index a66c21d3e6..9b9870670c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ -

- MultiMC logo -

+**This is a "cracked" version of a popular Minecraft launcher that lets you play the game without a Mojang account.** +This software is not related to MultiMC developers and provided without any warranty. Please don't bomb MultiMC developers if something gets wrong using this launcher. + +Offline mode based by this code: +https://github.com/MultiMC/MultiMC5/commit/6ede3c13b2bcda315e65dd78f2bfd729bc8b699b + +Rewrited for use license and offline accounts at the same time + +Details about the original launcher below: MultiMC 5 ========= @@ -13,7 +19,7 @@ The project uses C++ and Qt5 as the language and base framework. This might seem We can do more, with less, on worse hardware and leave more resources for the game while keeping the launcher running and providing extra features. -If you want to contribute, either talk to us on [Discord](https://discord.gg/0k2zsXGNHs0fE4Wm), [IRC](http://webchat.esper.net/?nick=&channels=MultiMC)(esper.net/#MultiMC) or pick up some item from the github issues [workflowy](https://github.com/MultiMC/MultiMC5/issues) - there is always plenty of ideas around. +If you want to contribute, either talk to us on [Discord](https://discord.gg/0k2zsXGNHs0fE4Wm), [IRC](http://webchat.esper.net/?nick=&channels=MultiMC)(esper.net/#MultiMC) or pick up some item from the github issues [workflowy](https://github.com/Ponywka/MultiMC5-with-offline/issues) - there is always plenty of ideas around. ### Building If you want to build MultiMC yourself, check [BUILD.md](BUILD.md) for build instructions. diff --git a/api/logic/minecraft/MinecraftInstance.cpp b/api/logic/minecraft/MinecraftInstance.cpp index db259395ef..009f806d93 100644 --- a/api/logic/minecraft/MinecraftInstance.cpp +++ b/api/logic/minecraft/MinecraftInstance.cpp @@ -821,7 +821,9 @@ shared_qobject_ptr 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 diff --git a/api/logic/minecraft/auth/MojangAccount.cpp b/api/logic/minecraft/auth/MojangAccount.cpp index 657e00095a..3e49320797 100644 --- a/api/logic/minecraft/auth/MojangAccount.cpp +++ b/api/logic/minecraft/auth/MojangAccount.cpp @@ -28,6 +28,8 @@ #include +#include + MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) { // The JSON object must at least have a username for it to be valid. @@ -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 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; diff --git a/api/logic/minecraft/auth/MojangAccount.h b/api/logic/minecraft/auth/MojangAccount.h index 7006435e65..9cc8a02c46 100644 --- a/api/logic/minecraft/auth/MojangAccount.h +++ b/api/logic/minecraft/auth/MojangAccount.h @@ -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); diff --git a/application/LaunchController.cpp b/application/LaunchController.cpp index bebc3db1b8..748f20b817 100644 --- a/application/LaunchController.cpp +++ b/application/LaunchController.cpp @@ -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.

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.

This could be caused by a password change."); + QString failReason = needLoginAgain; - while (tryagain) - { - m_session = std::make_shared(); - 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(); + 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(); + 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() diff --git a/application/dialogs/LoginDialog.cpp b/application/dialogs/LoginDialog.cpp index 484cb8e204..a74b898dcb 100644 --- a/application/dialogs/LoginDialog.cpp +++ b/application/dialogs/LoginDialog.cpp @@ -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) @@ -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) diff --git a/application/dialogs/LoginDialog.ui b/application/dialogs/LoginDialog.ui index d92fbae391..43b09bd927 100644 --- a/application/dialogs/LoginDialog.ui +++ b/application/dialogs/LoginDialog.ui @@ -7,7 +7,7 @@ 0 0 400 - 162 + 250 @@ -33,6 +33,22 @@ + + + + + 75 + true + + + + Note: For offline mode use "Email" field for username and "Password" field leave blank + + + Qt::RichText + + +