aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'launcher')
-rw-r--r--launcher/Application.cpp2
-rw-r--r--launcher/CMakeLists.txt32
-rw-r--r--launcher/LaunchController.cpp6
-rw-r--r--launcher/ModDownloadTask.cpp39
-rw-r--r--launcher/ModDownloadTask.h34
-rw-r--r--launcher/minecraft/auth/AccountData.cpp10
-rw-r--r--launcher/minecraft/auth/AccountData.h3
-rw-r--r--launcher/minecraft/auth/AccountList.cpp2
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.cpp31
-rw-r--r--launcher/minecraft/auth/MinecraftAccount.h12
-rw-r--r--launcher/minecraft/auth/flows/Offline.cpp17
-rw-r--r--launcher/minecraft/auth/flows/Offline.h22
-rw-r--r--launcher/minecraft/auth/steps/OfflineStep.cpp18
-rw-r--r--launcher/minecraft/auth/steps/OfflineStep.h19
-rw-r--r--launcher/minecraft/launch/LauncherPartLaunch.cpp15
-rw-r--r--launcher/modplatform/flame/FlameModIndex.cpp100
-rw-r--r--launcher/modplatform/flame/FlameModIndex.h50
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.cpp95
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackIndex.h48
-rw-r--r--launcher/resources/multimc/128x128/instances/modrinth.pngbin0 -> 10575 bytes
-rw-r--r--launcher/resources/multimc/32x32/instances/modrinth.pngbin0 -> 1913 bytes
-rw-r--r--launcher/resources/multimc/multimc.qrc3
-rw-r--r--launcher/ui/dialogs/AboutDialog.cpp17
-rw-r--r--launcher/ui/dialogs/AboutDialog.ui17
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.cpp98
-rw-r--r--launcher/ui/dialogs/ModDownloadDialog.h54
-rw-r--r--launcher/ui/dialogs/OfflineLoginDialog.cpp98
-rw-r--r--launcher/ui/dialogs/OfflineLoginDialog.h43
-rw-r--r--launcher/ui/dialogs/OfflineLoginDialog.ui67
-rw-r--r--launcher/ui/pages/global/AccountListPage.cpp30
-rw-r--r--launcher/ui/pages/global/AccountListPage.h1
-rw-r--r--launcher/ui/pages/global/AccountListPage.ui6
-rw-r--r--launcher/ui/pages/global/MinecraftPage.cpp5
-rw-r--r--launcher/ui/pages/global/MinecraftPage.ui20
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.cpp45
-rw-r--r--launcher/ui/pages/instance/ModFolderPage.h1
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.cpp47
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.h2
-rw-r--r--launcher/ui/pages/instance/ScreenshotsPage.ui18
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModModel.cpp273
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModModel.h79
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.cpp194
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.h67
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModPage.ui90
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModel.cpp11
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthModel.cpp268
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthModel.h79
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp179
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.h67
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.ui90
-rw-r--r--launcher/ui/widgets/WideBar.cpp14
-rw-r--r--launcher/ui/widgets/WideBar.h1
52 files changed, 2516 insertions, 23 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index b605e54b..7050e5dc 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -717,6 +717,8 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
// pastebin URL
m_settings->registerSetting("PastebinURL", "https://0x0.st");
+ m_settings->registerSetting("CloseAfterLaunch", false);
+
// Init page provider
{
m_globalSettingsProvider = std::make_shared<GenericPageProvider>(tr("Settings"));
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index c704563b..f4c3a9bc 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -37,6 +37,10 @@ set(CORE_SOURCES
InstanceImportTask.h
InstanceImportTask.cpp
+ # Mod downloading task
+ ModDownloadTask.h
+ ModDownloadTask.cpp
+
# Use tracking separate from memory management
Usable.h
@@ -212,7 +216,11 @@ set(MINECRAFT_SOURCES
minecraft/auth/flows/Mojang.h
minecraft/auth/flows/MSA.cpp
minecraft/auth/flows/MSA.h
+ minecraft/auth/flows/Offline.cpp
+ minecraft/auth/flows/Offline.h
+ minecraft/auth/steps/OfflineStep.cpp
+ minecraft/auth/steps/OfflineStep.h
minecraft/auth/steps/EntitlementsStep.cpp
minecraft/auth/steps/EntitlementsStep.h
minecraft/auth/steps/GetSkinStep.cpp
@@ -497,12 +505,19 @@ set(FLAME_SOURCES
# Flame
modplatform/flame/FlamePackIndex.cpp
modplatform/flame/FlamePackIndex.h
+ modplatform/flame/FlameModIndex.cpp
+ modplatform/flame/FlameModIndex.h
modplatform/flame/PackManifest.h
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
)
+set(MODRINTH_SOURCES
+ modplatform/modrinth/ModrinthPackIndex.cpp
+ modplatform/modrinth/ModrinthPackIndex.h
+)
+
set(MODPACKSCH_SOURCES
modplatform/modpacksch/FTBPackInstallTask.h
modplatform/modpacksch/FTBPackInstallTask.cpp
@@ -557,6 +572,7 @@ set(LOGIC_SOURCES
${ICONS_SOURCES}
${FTB_SOURCES}
${FLAME_SOURCES}
+ ${MODRINTH_SOURCES}
${MODPACKSCH_SOURCES}
${TECHNIC_SOURCES}
${ATLAUNCHER_SOURCES}
@@ -730,6 +746,10 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/flame/FlameModel.h
ui/pages/modplatform/flame/FlamePage.cpp
ui/pages/modplatform/flame/FlamePage.h
+ ui/pages/modplatform/flame/FlameModModel.cpp
+ ui/pages/modplatform/flame/FlameModModel.h
+ ui/pages/modplatform/flame/FlameModPage.cpp
+ ui/pages/modplatform/flame/FlameModPage.h
ui/pages/modplatform/technic/TechnicModel.cpp
ui/pages/modplatform/technic/TechnicModel.h
@@ -739,6 +759,11 @@ SET(LAUNCHER_SOURCES
ui/pages/modplatform/ImportPage.cpp
ui/pages/modplatform/ImportPage.h
+ ui/pages/modplatform/modrinth/ModrinthModel.cpp
+ ui/pages/modplatform/modrinth/ModrinthModel.h
+ ui/pages/modplatform/modrinth/ModrinthPage.cpp
+ ui/pages/modplatform/modrinth/ModrinthPage.h
+
# GUI - dialogs
ui/dialogs/AboutDialog.cpp
ui/dialogs/AboutDialog.h
@@ -760,6 +785,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/LoginDialog.h
ui/dialogs/MSALoginDialog.cpp
ui/dialogs/MSALoginDialog.h
+ ui/dialogs/OfflineLoginDialog.cpp
+ ui/dialogs/OfflineLoginDialog.h
ui/dialogs/NewComponentDialog.cpp
ui/dialogs/NewComponentDialog.h
ui/dialogs/NewInstanceDialog.cpp
@@ -776,6 +803,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/VersionSelectDialog.h
ui/dialogs/SkinUploadDialog.cpp
ui/dialogs/SkinUploadDialog.h
+ ui/dialogs/ModDownloadDialog.cpp
+ ui/dialogs/ModDownloadDialog.h
# GUI - widgets
@@ -852,10 +881,12 @@ qt5_wrap_ui(LAUNCHER_UI
ui/pages/modplatform/atlauncher/AtlPage.ui
ui/pages/modplatform/VanillaPage.ui
ui/pages/modplatform/flame/FlamePage.ui
+ ui/pages/modplatform/flame/FlameModPage.ui
ui/pages/modplatform/legacy_ftb/Page.ui
ui/pages/modplatform/ImportPage.ui
ui/pages/modplatform/ftb/FtbPage.ui
ui/pages/modplatform/technic/TechnicPage.ui
+ ui/pages/modplatform/modrinth/ModrinthPage.ui
ui/widgets/InstanceCardWidget.ui
ui/widgets/CustomCommands.ui
ui/widgets/MCModInfoFrame.ui
@@ -871,6 +902,7 @@ qt5_wrap_ui(LAUNCHER_UI
ui/dialogs/ExportInstanceDialog.ui
ui/dialogs/IconPickerDialog.ui
ui/dialogs/MSALoginDialog.ui
+ ui/dialogs/OfflineLoginDialog.ui
ui/dialogs/AboutDialog.ui
ui/dialogs/LoginDialog.ui
ui/dialogs/EditAccountDialog.ui
diff --git a/launcher/LaunchController.cpp b/launcher/LaunchController.cpp
index 7750be1a..32fc99cb 100644
--- a/launcher/LaunchController.cpp
+++ b/launcher/LaunchController.cpp
@@ -116,6 +116,12 @@ void LaunchController::login() {
m_session->wants_online = m_online;
m_accountToUse->fillSession(m_session);
+ // Launch immediately in true offline mode
+ if(m_accountToUse->isOffline()) {
+ launchInstance();
+ return;
+ }
+
switch(m_accountToUse->accountState()) {
case AccountState::Offline: {
m_session->wants_online = false;
diff --git a/launcher/ModDownloadTask.cpp b/launcher/ModDownloadTask.cpp
new file mode 100644
index 00000000..08a02d29
--- /dev/null
+++ b/launcher/ModDownloadTask.cpp
@@ -0,0 +1,39 @@
+#include "ModDownloadTask.h"
+#include "Application.h"
+
+ModDownloadTask::ModDownloadTask(const QUrl sourceUrl,const QString filename, const std::shared_ptr<ModFolderModel> mods)
+: m_sourceUrl(sourceUrl), mods(mods), filename(filename) {
+}
+
+void ModDownloadTask::executeTask() {
+ setStatus(tr("Downloading mod:\n%1").arg(m_sourceUrl.toString()));
+
+ m_filesNetJob.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
+ m_filesNetJob->addNetAction(Net::Download::makeFile(m_sourceUrl, mods->dir().absoluteFilePath(filename)));
+ connect(m_filesNetJob.get(), &NetJob::succeeded, this, &ModDownloadTask::downloadSucceeded);
+ connect(m_filesNetJob.get(), &NetJob::progress, this, &ModDownloadTask::downloadProgressChanged);
+ connect(m_filesNetJob.get(), &NetJob::failed, this, &ModDownloadTask::downloadFailed);
+ m_filesNetJob->start();
+}
+
+void ModDownloadTask::downloadSucceeded()
+{
+ emitSucceeded();
+ m_filesNetJob.reset();
+}
+
+void ModDownloadTask::downloadFailed(QString reason)
+{
+ emitFailed(reason);
+ m_filesNetJob.reset();
+}
+
+void ModDownloadTask::downloadProgressChanged(qint64 current, qint64 total)
+{
+ emit progress(current, total);
+}
+
+bool ModDownloadTask::abort() {
+ return m_filesNetJob->abort();
+}
+
diff --git a/launcher/ModDownloadTask.h b/launcher/ModDownloadTask.h
new file mode 100644
index 00000000..7e4f1b7d
--- /dev/null
+++ b/launcher/ModDownloadTask.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "QObjectPtr.h"
+#include "tasks/Task.h"
+#include "minecraft/mod/ModFolderModel.h"
+#include "net/NetJob.h"
+#include <QUrl>
+
+
+class ModDownloadTask : public Task {
+ Q_OBJECT
+public:
+ explicit ModDownloadTask(const QUrl sourceUrl, const QString filename, const std::shared_ptr<ModFolderModel> mods);
+
+public slots:
+ bool abort() override;
+protected:
+ //! Entry point for tasks.
+ void executeTask() override;
+
+private:
+ QUrl m_sourceUrl;
+ NetJob::Ptr m_filesNetJob;
+ const std::shared_ptr<ModFolderModel> mods;
+ const QString filename;
+
+ void downloadProgressChanged(qint64 current, qint64 total);
+
+ void downloadFailed(QString reason);
+
+ void downloadSucceeded();
+};
+
+
+
diff --git a/launcher/minecraft/auth/AccountData.cpp b/launcher/minecraft/auth/AccountData.cpp
index 7526c951..9b84fe1a 100644
--- a/launcher/minecraft/auth/AccountData.cpp
+++ b/launcher/minecraft/auth/AccountData.cpp
@@ -314,6 +314,8 @@ bool AccountData::resumeStateFromV3(QJsonObject data) {
type = AccountType::MSA;
} else if (typeS == "Mojang") {
type = AccountType::Mojang;
+ } else if (typeS == "Offline") {
+ type = AccountType::Offline;
} else {
qWarning() << "Failed to parse account data: type is not recognized.";
return false;
@@ -363,6 +365,9 @@ QJsonObject AccountData::saveState() const {
tokenToJSONV3(output, xboxApiToken, "xrp-main");
tokenToJSONV3(output, mojangservicesToken, "xrp-mc");
}
+ else if (type == AccountType::Offline) {
+ output["type"] = "Offline";
+ }
tokenToJSONV3(output, yggdrasilToken, "ygg");
profileToJSONV3(output, minecraftProfile, "profile");
@@ -371,7 +376,7 @@ QJsonObject AccountData::saveState() const {
}
QString AccountData::userName() const {
- if(type != AccountType::Mojang) {
+ if(type == AccountType::MSA) {
return QString();
}
return yggdrasilToken.extra["userName"].toString();
@@ -427,6 +432,9 @@ QString AccountData::accountDisplayString() const {
case AccountType::Mojang: {
return userName();
}
+ case AccountType::Offline: {
+ return userName();
+ }
case AccountType::MSA: {
if(xboxApiToken.extra.contains("gtg")) {
return xboxApiToken.extra["gtg"].toString();
diff --git a/launcher/minecraft/auth/AccountData.h b/launcher/minecraft/auth/AccountData.h
index abf84e43..606c1ad1 100644
--- a/launcher/minecraft/auth/AccountData.h
+++ b/launcher/minecraft/auth/AccountData.h
@@ -38,7 +38,8 @@ struct MinecraftProfile {
enum class AccountType {
MSA,
- Mojang
+ Mojang,
+ Offline
};
enum class AccountState {
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index ef8b435d..04470e1c 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -302,7 +302,7 @@ QVariant AccountList::data(const QModelIndex &index, int role) const
}
case MigrationColumn: {
- if(account->isMSA()) {
+ if(account->isMSA() || account->isOffline()) {
return tr("N/A", "Can Migrate?");
}
if (account->canMigrate()) {
diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp
index ed9e945e..ffc81ed8 100644
--- a/launcher/minecraft/auth/MinecraftAccount.cpp
+++ b/launcher/minecraft/auth/MinecraftAccount.cpp
@@ -30,6 +30,7 @@
#include "flows/MSA.h"
#include "flows/Mojang.h"
+#include "flows/Offline.h"
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) {
data.internalId = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
@@ -68,6 +69,23 @@ MinecraftAccountPtr MinecraftAccount::createBlankMSA()
return account;
}
+MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username)
+{
+ MinecraftAccountPtr account = new MinecraftAccount();
+ account->data.type = AccountType::Offline;
+ account->data.yggdrasilToken.token = "offline";
+ account->data.yggdrasilToken.validity = Katabasis::Validity::Certain;
+ account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
+ account->data.yggdrasilToken.extra["userName"] = username;
+ account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+ account->data.minecraftEntitlement.ownsMinecraft = true;
+ account->data.minecraftEntitlement.canPlayMinecraft = true;
+ account->data.minecraftProfile.id = QUuid::createUuid().toString().remove(QRegExp("[{}-]"));
+ account->data.minecraftProfile.name = username;
+ account->data.minecraftProfile.validity = Katabasis::Validity::Certain;
+ return account;
+}
+
QJsonObject MinecraftAccount::saveToJson() const
{
@@ -111,6 +129,16 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::loginMSA() {
return m_currentTask;
}
+shared_qobject_ptr<AccountTask> MinecraftAccount::loginOffline() {
+ Q_ASSERT(m_currentTask.get() == nullptr);
+
+ m_currentTask.reset(new OfflineLogin(&data));
+ connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded()));
+ connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString)));
+ emit activityChanged(true);
+ return m_currentTask;
+}
+
shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
if(m_currentTask) {
return m_currentTask;
@@ -119,6 +147,9 @@ shared_qobject_ptr<AccountTask> MinecraftAccount::refresh() {
if(data.type == AccountType::MSA) {
m_currentTask.reset(new MSASilent(&data));
}
+ else if(data.type == AccountType::Offline) {
+ m_currentTask.reset(new OfflineRefresh(&data));
+ }
else {
m_currentTask.reset(new MojangRefresh(&data));
}
diff --git a/launcher/minecraft/auth/MinecraftAccount.h b/launcher/minecraft/auth/MinecraftAccount.h
index 7ab3c746..6592f9c0 100644
--- a/launcher/minecraft/auth/MinecraftAccount.h
+++ b/launcher/minecraft/auth/MinecraftAccount.h
@@ -73,6 +73,8 @@ public: /* construction */
static MinecraftAccountPtr createBlankMSA();
+ static MinecraftAccountPtr createOffline(const QString &username);
+
static MinecraftAccountPtr loadFromJsonV2(const QJsonObject &json);
static MinecraftAccountPtr loadFromJsonV3(const QJsonObject &json);
@@ -89,6 +91,8 @@ public: /* manipulation */
shared_qobject_ptr<AccountTask> loginMSA();
+ shared_qobject_ptr<AccountTask> loginOffline();
+
shared_qobject_ptr<AccountTask> refresh();
shared_qobject_ptr<AccountTask> currentTask();
@@ -128,6 +132,10 @@ public: /* queries */
return data.type == AccountType::MSA;
}
+ bool isOffline() const {
+ return data.type == AccountType::Offline;
+ }
+
bool ownsMinecraft() const {
return data.minecraftEntitlement.ownsMinecraft;
}
@@ -149,6 +157,10 @@ public: /* queries */
return "msa";
}
break;
+ case AccountType::Offline: {
+ return "offline";
+ }
+ break;
default: {
return "unknown";
}
diff --git a/launcher/minecraft/auth/flows/Offline.cpp b/launcher/minecraft/auth/flows/Offline.cpp
new file mode 100644
index 00000000..fc614a8c
--- /dev/null
+++ b/launcher/minecraft/auth/flows/Offline.cpp
@@ -0,0 +1,17 @@
+#include "Offline.h"
+
+#include "minecraft/auth/steps/OfflineStep.h"
+
+OfflineRefresh::OfflineRefresh(
+ AccountData *data,
+ QObject *parent
+) : AuthFlow(data, parent) {
+ m_steps.append(new OfflineStep(m_data));
+}
+
+OfflineLogin::OfflineLogin(
+ AccountData *data,
+ QObject *parent
+) : AuthFlow(data, parent) {
+ m_steps.append(new OfflineStep(m_data));
+}
diff --git a/launcher/minecraft/auth/flows/Offline.h b/launcher/minecraft/auth/flows/Offline.h
new file mode 100644
index 00000000..5d1f83a4
--- /dev/null
+++ b/launcher/minecraft/auth/flows/Offline.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "AuthFlow.h"
+
+class OfflineRefresh : public AuthFlow
+{
+ Q_OBJECT
+public:
+ explicit OfflineRefresh(
+ AccountData *data,
+ QObject *parent = 0
+ );
+};
+
+class OfflineLogin : public AuthFlow
+{
+ Q_OBJECT
+public:
+ explicit OfflineLogin(
+ AccountData *data,
+ QObject *parent = 0
+ );
+};
diff --git a/launcher/minecraft/auth/steps/OfflineStep.cpp b/launcher/minecraft/auth/steps/OfflineStep.cpp
new file mode 100644
index 00000000..dc092bfd
--- /dev/null
+++ b/launcher/minecraft/auth/steps/OfflineStep.cpp
@@ -0,0 +1,18 @@
+#include "OfflineStep.h"
+
+#include "Application.h"
+
+OfflineStep::OfflineStep(AccountData* data) : AuthStep(data) {}
+OfflineStep::~OfflineStep() noexcept = default;
+
+QString OfflineStep::describe() {
+ return tr("Creating offline account.");
+}
+
+void OfflineStep::rehydrate() {
+ // NOOP
+}
+
+void OfflineStep::perform() {
+ emit finished(AccountTaskState::STATE_WORKING, tr("Created offline account."));
+}
diff --git a/launcher/minecraft/auth/steps/OfflineStep.h b/launcher/minecraft/auth/steps/OfflineStep.h
new file mode 100644
index 00000000..436597cd
--- /dev/null
+++ b/launcher/minecraft/auth/steps/OfflineStep.h
@@ -0,0 +1,19 @@
+#pragma once
+#include <QObject>
+
+#include "QObjectPtr.h"
+#include "minecraft/auth/AuthStep.h"
+
+#include <katabasis/DeviceFlow.h>
+
+class OfflineStep : public AuthStep {
+ Q_OBJECT
+public:
+ explicit OfflineStep(AccountData *data);
+ virtual ~OfflineStep() noexcept;
+
+ void perform() override;
+ void rehydrate() override;
+
+ QString describe() override;
+};
diff --git a/launcher/minecraft/launch/LauncherPartLaunch.cpp b/launcher/minecraft/launch/LauncherPartLaunch.cpp
index 8fd11eca..f461b847 100644
--- a/launcher/minecraft/launch/LauncherPartLaunch.cpp
+++ b/launcher/minecraft/launch/LauncherPartLaunch.cpp
@@ -25,6 +25,19 @@
LauncherPartLaunch::LauncherPartLaunch(LaunchTask *parent) : LaunchStep(parent)
{
+ if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ {
+ std::shared_ptr<QMetaObject::Connection> connection{new QMetaObject::Connection};
+ *connection = connect(&m_process, &LoggedProcess::log, this, [=](QStringList lines, MessageLevel::Enum level) {
+ qDebug() << lines;
+ if (lines.filter(QRegularExpression(".*Setting user.+", QRegularExpression::CaseInsensitiveOption)).length() != 0)
+ {
+ APPLICATION->closeAllWindows();
+ disconnect(*connection);
+ }
+ });
+ }
+
connect(&m_process, &LoggedProcess::log, this, &LauncherPartLaunch::logLines);
connect(&m_process, &LoggedProcess::stateChanged, this, &LauncherPartLaunch::on_state);
}
@@ -155,6 +168,8 @@ void LauncherPartLaunch::on_state(LoggedProcess::State state)
}
case LoggedProcess::Finished:
{
+ if (APPLICATION->settings()->get("CloseAfterLaunch").toBool())
+ APPLICATION->showMainWindow();
m_parent->setPid(-1);
// if the exit code wasn't 0, report this as a crash
auto exitCode = m_process.exitCode();
diff --git a/launcher/modplatform/flame/FlameModIndex.cpp b/launcher/modplatform/flame/FlameModIndex.cpp
new file mode 100644
index 00000000..a8b2495a
--- /dev/null
+++ b/launcher/modplatform/flame/FlameModIndex.cpp
@@ -0,0 +1,100 @@
+#include <QObject>
+#include "FlameModIndex.h"
+#include "Json.h"
+#include "net/NetJob.h"
+#include "BaseInstance.h"
+#include "minecraft/MinecraftInstance.h"
+#include "minecraft/PackProfile.h"
+
+
+void FlameMod::loadIndexedPack(FlameMod::IndexedPack & pack, QJsonObject & obj)
+{
+ pack.addonId = Json::requireInteger(obj, "id");
+ pack.name = Json::requireString(obj, "name");
+ pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
+ pack.description = Json::ensureString(obj, "summary", "");
+
+ bool thumbnailFound = false;
+ auto attachments = Json::requireArray(obj, "attachments");
+ for(auto attachmentRaw: attachments) {
+ auto attachmentObj = Json::requireObject(attachmentRaw);
+ bool isDefaul