diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b1b5483..8dadbad4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -306,6 +306,8 @@ logic/net/PasteUpload.cpp logic/net/URLConstants.h # Yggdrasil login stuff +logic/auth/MojangAccountList.h +logic/auth/MojangAccountList.cpp logic/auth/MojangAccount.h logic/auth/MojangAccount.cpp logic/auth/YggdrasilTask.h @@ -368,8 +370,6 @@ logic/lists/ForgeVersionList.h logic/lists/ForgeVersionList.cpp logic/lists/JavaVersionList.h logic/lists/JavaVersionList.cpp -logic/lists/MojangAccountList.h -logic/lists/MojangAccountList.cpp # misc model/view logic/EnabledItemFilter.h diff --git a/MultiMC.cpp b/MultiMC.cpp index 6c88a6be..2c9e74dd 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -12,7 +12,7 @@ #include "gui/MainWindow.h" #include "gui/dialogs/VersionSelectDialog.h" #include "logic/lists/InstanceList.h" -#include "logic/lists/MojangAccountList.h" +#include "logic/auth/MojangAccountList.h" #include "logic/lists/IconList.h" #include "logic/lists/LwjglVersionList.h" #include "logic/lists/MinecraftVersionList.h" @@ -78,11 +78,13 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv), parser.addShortOpt("quietupdate", 'U'); parser.addDocumentation("quietupdate", "doesn't restart MultiMC after installing updates"); + // WARNING: disabled until further notice + /* // --launch parser.addOption("launch"); parser.addShortOpt("launch", 'l'); parser.addDocumentation("launch", "tries to launch the given instance", ""); - +*/ // parse the arguments try { @@ -212,6 +214,8 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv), m_qnam.reset(new QNetworkAccessManager(this)); // launch instance, if that's what should be done + // WARNING: disabled until further notice + /* if (!args["launch"].isNull()) { if (InstanceLauncher(args["launch"].toString()).launch()) @@ -220,7 +224,7 @@ MultiMC::MultiMC(int &argc, char **argv) : QApplication(argc, argv), m_status = MultiMC::Failed; return; } - +*/ m_status = MultiMC::Initialized; } diff --git a/gui/dialogs/AccountListDialog.h b/gui/dialogs/AccountListDialog.h index 84ff8e0e..fe0c8773 100644 --- a/gui/dialogs/AccountListDialog.h +++ b/gui/dialogs/AccountListDialog.h @@ -19,7 +19,7 @@ #include -#include "logic/lists/MojangAccountList.h" +#include "logic/auth/MojangAccountList.h" namespace Ui { diff --git a/gui/dialogs/AccountSelectDialog.h b/gui/dialogs/AccountSelectDialog.h index a539e7e9..6007253d 100644 --- a/gui/dialogs/AccountSelectDialog.h +++ b/gui/dialogs/AccountSelectDialog.h @@ -19,7 +19,7 @@ #include -#include "logic/lists/MojangAccountList.h" +#include "logic/auth/MojangAccountList.h" namespace Ui { diff --git a/logic/JavaChecker.cpp b/logic/JavaChecker.cpp index 38bbf700..2b94fbb6 100644 --- a/logic/JavaChecker.cpp +++ b/logic/JavaChecker.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #define CHECKER_FILE "JavaChecker.jar" @@ -11,14 +12,15 @@ JavaChecker::JavaChecker(QObject *parent) : QObject(parent) void JavaChecker::performCheck() { - if(QFile::exists(CHECKER_FILE)) - { - QFile::remove(CHECKER_FILE); - } - // extract the checker - QFile(":/java/checker.jar").copy(CHECKER_FILE); + checkerJar.setFileTemplate("checker_XXXXXX.jar"); + checkerJar.open(); + QFile inner(":/java/checker.jar"); + inner.open(QIODevice::ReadOnly); + checkerJar.write(inner.readAll()); + inner.close(); + checkerJar.close(); - QStringList args = {"-jar", CHECKER_FILE}; + QStringList args = {"-jar", checkerJar.fileName()}; process.reset(new QProcess()); process->setArguments(args); @@ -40,6 +42,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status) killTimer.stop(); QProcessPtr _process; _process.swap(process); + checkerJar.remove(); JavaCheckResult result; { diff --git a/logic/JavaChecker.h b/logic/JavaChecker.h index 4488da66..291bf46c 100644 --- a/logic/JavaChecker.h +++ b/logic/JavaChecker.h @@ -1,10 +1,12 @@ #pragma once #include #include +#include #include class JavaChecker; + struct JavaCheckResult { QString path; @@ -31,6 +33,7 @@ signals: private: QProcessPtr process; QTimer killTimer; + QTemporaryFile checkerJar; public slots: void timeout(); diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index b8d85ff5..337830a2 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -154,7 +154,7 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) token_mapping["game_assets"] = reconstructAssets(d->version).absolutePath(); //TODO: this is something new and not even fully implemented in the vanilla launcher. token_mapping["user_properties"] = "{ }"; - + token_mapping["user_type"] = account->currentProfile()->legacy ? "legacy" : "mojang"; // 1.7.3+ assets tokens token_mapping["assets_root"] = absAssetsDir; token_mapping["assets_index_name"] = version->assets; diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp index e586402b..8ae685f0 100644 --- a/logic/OneSixVersion.cpp +++ b/logic/OneSixVersion.cpp @@ -165,7 +165,7 @@ std::shared_ptr OneSixVersion::fromJson(QJsonObject root) root.value("minimumLauncherVersion").toDouble(); // ADD MORE HERE :D - if (launcher_ver > 0 && launcher_ver <= 12) + if (launcher_ver > 0 && launcher_ver <= 13) return fromJsonV4(root, readVersion); else { diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index b1acfb25..185c735c 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -52,15 +53,30 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) QJsonObject profileObject = profileVal.toObject(); QString id = profileObject.value("id").toString(""); QString name = profileObject.value("name").toString(""); + bool legacy = profileObject.value("legacy").toBool(false); if (id.isEmpty() || name.isEmpty()) { QLOG_WARN() << "Unable to load a profile because it was missing an ID or a name."; continue; } - profiles.append({id, name}); + profiles.append({id, name, legacy}); } MojangAccountPtr account(new MojangAccount()); + if(object.value("user").isObject()) + { + User u; + QJsonObject userStructure = object.value("user").toObject(); + u.id = userStructure.value("id").toString(); + QJsonObject propMap = userStructure.value("properties").toObject(); + for(auto key: propMap.keys()) + { + auto values = propMap.operator[](key).toArray(); + for(auto value: values) + u.properties.insert(key, value.toString()); + } + account->m_user = u; + } account->m_username = username; account->m_clientToken = clientToken; account->m_accessToken = accessToken; @@ -95,10 +111,24 @@ QJsonObject MojangAccount::saveToJson() const QJsonObject profileObj; profileObj.insert("id", profile.id); profileObj.insert("name", profile.name); + profileObj.insert("legacy", profile.legacy); profileArray.append(profileObj); } json.insert("profiles", profileArray); + QJsonObject userStructure; + { + userStructure.insert("id", m_user.id); + QJsonObject userAttrs; + for(auto key: m_user.properties.keys()) + { + auto array = QJsonArray::fromStringList(m_user.properties.values(key)); + userAttrs.insert(key, array); + } + userStructure.insert("properties", userAttrs); + } + json.insert("user", userStructure); + if (m_currentProfile != -1) json.insert("activeProfile", currentProfile()->id); diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index 95f777ce..9eecbc4f 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -41,14 +42,13 @@ struct AccountProfile { QString id; QString name; + bool legacy; }; struct User { QString id; - // pair of key:value - // we don't know if the keys:value mapping is 1:1, so a list is used. - QList> properties; + QMultiMap properties; }; enum AccountStatus diff --git a/logic/lists/MojangAccountList.cpp b/logic/auth/MojangAccountList.cpp similarity index 98% rename from logic/lists/MojangAccountList.cpp rename to logic/auth/MojangAccountList.cpp index defa5d8c..0d13cd34 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/auth/MojangAccountList.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "logic/lists/MojangAccountList.h" +#include "logic/auth/MojangAccountList.h" #include #include @@ -27,7 +27,7 @@ #include "logic/auth/MojangAccount.h" -#define ACCOUNT_LIST_FORMAT_VERSION 1 +#define ACCOUNT_LIST_FORMAT_VERSION 2 MojangAccountList::MojangAccountList(QObject *parent) : QAbstractListModel(parent) { diff --git a/logic/lists/MojangAccountList.h b/logic/auth/MojangAccountList.h similarity index 100% rename from logic/lists/MojangAccountList.h rename to logic/auth/MojangAccountList.h diff --git a/logic/auth/flows/AuthenticateTask.cpp b/logic/auth/flows/AuthenticateTask.cpp index 966548ec..cc26cd1b 100644 --- a/logic/auth/flows/AuthenticateTask.cpp +++ b/logic/auth/flows/AuthenticateTask.cpp @@ -76,7 +76,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // Read the response data. We need to get the client token, access token, and the selected // profile. QLOG_DEBUG() << "Processing authentication response."; - + // QLOG_DEBUG() << responseData; // If we already have a client token, make sure the one the server gave us matches our // existing one. QLOG_DEBUG() << "Getting client token."; @@ -123,6 +123,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // Profiles are easy, we just need their ID and name. QString id = profile.value("id").toString(""); QString name = profile.value("name").toString(""); + bool legacy = profile.value("legacy").toBool(false); if (id.isEmpty() || name.isEmpty()) { @@ -134,7 +135,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) } // Now, add a new AccountProfile entry to the list. - loadedProfiles.append({id, name}); + loadedProfiles.append({id, name, legacy}); } // Put the list of profiles we loaded into the MojangAccount object. m_account->m_profiles = loadedProfiles; @@ -166,10 +167,11 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // is it a good idea to log this? if (responseData.contains("user")) { + User u; auto obj = responseData.value("user").toObject(); - auto userId = obj.value("id").toString(); + u.id = obj.value("id").toString(); + QLOG_DEBUG() << "User ID: " << u.id ; auto propArray = obj.value("properties").toArray(); - QLOG_DEBUG() << "User ID: " << userId; QLOG_DEBUG() << "User Properties: "; for (auto prop : propArray) { @@ -177,7 +179,9 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) auto name = propTuple.value("name").toString(); auto value = propTuple.value("value").toString(); QLOG_DEBUG() << name << " : " << value; + u.properties.insert(name, value); } + m_account->m_user = u; } // We've made it through the minefield of possible errors. Return true to indicate that diff --git a/logic/auth/flows/RefreshTask.cpp b/logic/auth/flows/RefreshTask.cpp index bd38eb10..16feac6e 100644 --- a/logic/auth/flows/RefreshTask.cpp +++ b/logic/auth/flows/RefreshTask.cpp @@ -67,6 +67,7 @@ bool RefreshTask::processResponse(QJsonObject responseData) // profile. QLOG_DEBUG() << "Processing authentication response."; + // QLOG_DEBUG() << responseData; // If we already have a client token, make sure the one the server gave us matches our // existing one. QString clientToken = responseData.value("clientToken").toString(""); diff --git a/logic/updater/DownloadUpdateTask.cpp b/logic/updater/DownloadUpdateTask.cpp index 3fe24482..d9aab826 100644 --- a/logic/updater/DownloadUpdateTask.cpp +++ b/logic/updater/DownloadUpdateTask.cpp @@ -239,13 +239,19 @@ void DownloadUpdateTask::processFileLists() // delete anything in the current one version's list that isn't in the new version's list. for (VersionFileEntry entry : m_cVersionFileList) { + bool keep = false; for (VersionFileEntry newEntry : m_nVersionFileList) - { + { if (newEntry.path == entry.path) - continue; + { + QLOG_DEBUG() << "Not deleting" << entry.path << "because it is still present in the new version."; + keep = true; + break; + } } - // If the loop reaches the end, we didn't find a match. Delete the file. - m_operationList.append(UpdateOperation::DeleteOp(entry.path)); + // If the loop reaches the end and we didn't find a match, delete the file. + if(!keep) + m_operationList.append(UpdateOperation::DeleteOp(entry.path)); } // Create a network job for downloading files. diff --git a/mmc_updater/src/CMakeLists.txt b/mmc_updater/src/CMakeLists.txt index 9b39bb83..d1a32755 100644 --- a/mmc_updater/src/CMakeLists.txt +++ b/mmc_updater/src/CMakeLists.txt @@ -34,7 +34,7 @@ endif() if (UNIX) set(UPDATER_SOURCES ${UPDATER_SOURCES} UpdateDialogAscii.cpp UpdateDialogAscii.h) - add_definitions(-Wall -Werror -Wconversion) + add_definitions(-Wall -Wconversion) if (APPLE) set(MAC_DOCK_ICON_CPP_FILE ${CMAKE_CURRENT_BINARY_DIR}/mac_dock_icon.cpp) set(MAC_INFO_PLIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/mac_info_plist.cpp) diff --git a/mmc_updater/src/ProcessUtils.h b/mmc_updater/src/ProcessUtils.h index 9fa10815..e0cc3dc0 100644 --- a/mmc_updater/src/ProcessUtils.h +++ b/mmc_updater/src/ProcessUtils.h @@ -5,6 +5,10 @@ #include #include +#ifndef PLATFORM_WINDOWS +#include +#endif + /** A set of functions to get information about the current * process and launch new processes. */