aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildconfig/BuildConfig.h2
-rw-r--r--launcher/CMakeLists.txt3
-rw-r--r--launcher/InstanceImportTask.cpp45
-rw-r--r--launcher/InstanceImportTask.h6
-rw-r--r--launcher/InstanceList.cpp17
-rw-r--r--launcher/InstanceList.h2
-rw-r--r--launcher/InstancePageProvider.h2
-rw-r--r--launcher/InstanceTask.cpp23
-rw-r--r--launcher/InstanceTask.h17
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.cpp55
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.h16
-rw-r--r--launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp60
-rw-r--r--launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h16
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackManifest.cpp1
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackManifest.h1
-rw-r--r--launcher/ui/InstanceWindow.cpp6
-rw-r--r--launcher/ui/pages/BasePageContainer.h3
-rw-r--r--launcher/ui/pages/instance/ManagedPackPage.cpp432
-rw-r--r--launcher/ui/pages/instance/ManagedPackPage.h152
-rw-r--r--launcher/ui/pages/instance/ManagedPackPage.ui193
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.cpp23
-rw-r--r--launcher/ui/pages/modplatform/flame/FlamePage.h2
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthPage.cpp6
-rw-r--r--launcher/ui/widgets/PageContainer.cpp5
-rw-r--r--launcher/ui/widgets/PageContainer.h1
25 files changed, 983 insertions, 106 deletions
diff --git a/buildconfig/BuildConfig.h b/buildconfig/BuildConfig.h
index 4a309073..a05d7a9e 100644
--- a/buildconfig/BuildConfig.h
+++ b/buildconfig/BuildConfig.h
@@ -161,6 +161,8 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
+ QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
+
QString versionString() const;
/**
* \brief Converts the Version to a string.
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 3eb765dc..245b6995 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -680,6 +680,8 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/GameOptionsPage.h
ui/pages/instance/VersionPage.cpp
ui/pages/instance/VersionPage.h
+ ui/pages/instance/ManagedPackPage.cpp
+ ui/pages/instance/ManagedPackPage.h
ui/pages/instance/TexturePackPage.h
ui/pages/instance/ResourcePackPage.h
ui/pages/instance/ShaderPackPage.h
@@ -919,6 +921,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/instance/OtherLogsPage.ui
ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui
+ ui/pages/instance/ManagedPackPage.ui
ui/pages/instance/WorldListPage.ui
ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
diff --git a/launcher/InstanceImportTask.cpp b/launcher/InstanceImportTask.cpp
index 5f459649..b97870da 100644
--- a/launcher/InstanceImportTask.cpp
+++ b/launcher/InstanceImportTask.cpp
@@ -55,11 +55,9 @@
#include <quazip/quazipdir.h>
-InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent)
-{
- m_sourceUrl = sourceUrl;
- m_parent = parent;
-}
+InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
+ : m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
+{}
bool InstanceImportTask::abort()
{
@@ -259,14 +257,28 @@ void InstanceImportTask::extractAborted()
void InstanceImportTask::processFlame()
{
- auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent);
+ auto pack_id_it = m_extra_info.constFind("pack_id");
+ Q_ASSERT(pack_id_it != m_extra_info.constEnd());
+ auto pack_id = pack_id_it.value();
+
+ auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
+ Q_ASSERT(pack_version_id_it != m_extra_info.constEnd());
+ auto pack_version_id = pack_version_id_it.value();
+
+ QString original_instance_id;
+ auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
+ if (original_instance_id_it != m_extra_info.constEnd())
+ original_instance_id = original_instance_id_it.value();
+
+ auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
inst_creation_task->setName(*this);
inst_creation_task->setIcon(m_instIcon);
inst_creation_task->setGroup(m_instGroup);
+ inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
- setOverride(inst_creation_task->shouldOverride());
+ setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded();
});
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
@@ -323,14 +335,29 @@ void InstanceImportTask::processMultiMC()
void InstanceImportTask::processModrinth()
{
- auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, m_sourceUrl.toString());
+ auto pack_id_it = m_extra_info.constFind("pack_id");
+ Q_ASSERT(pack_id_it != m_extra_info.constEnd());
+ auto pack_id = pack_id_it.value();
+
+ QString pack_version_id;
+ auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
+ if (pack_version_id_it != m_extra_info.constEnd())
+ pack_version_id = pack_version_id_it.value();
+
+ QString original_instance_id;
+ auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
+ if (original_instance_id_it != m_extra_info.constEnd())
+ original_instance_id = original_instance_id_it.value();
+
+ auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
inst_creation_task->setName(*this);
inst_creation_task->setIcon(m_instIcon);
inst_creation_task->setGroup(m_instGroup);
+ inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
- setOverride(inst_creation_task->shouldOverride());
+ setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded();
});
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
diff --git a/launcher/InstanceImportTask.h b/launcher/InstanceImportTask.h
index ef70c819..6b8ac966 100644
--- a/launcher/InstanceImportTask.h
+++ b/launcher/InstanceImportTask.h
@@ -56,7 +56,7 @@ class InstanceImportTask : public InstanceTask
{
Q_OBJECT
public:
- explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr);
+ explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
bool abort() override;
const QVector<Flame::File> &getBlockedFiles() const
@@ -101,6 +101,10 @@ private: /* data */
Modrinth,
} m_modpackType = ModpackType::Unknown;
+ // Extra info we might need, that's available before, but can't be derived from
+ // the source URL / the resource it points to alone.
+ QMap<QString, QString> m_extra_info;
+
//FIXME: nuke
QWidget* m_parent;
};
diff --git a/launcher/InstanceList.cpp b/launcher/InstanceList.cpp
index cebd70d7..68e3e92c 100644
--- a/launcher/InstanceList.cpp
+++ b/launcher/InstanceList.cpp
@@ -816,7 +816,7 @@ class InstanceStaging : public Task {
void childSucceded()
{
unsigned sleepTime = backoff();
- if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, m_child->shouldOverride()))
+ if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get()))
{
emitSucceeded();
return;
@@ -880,25 +880,22 @@ QString InstanceList::getStagedInstancePath()
return path;
}
-bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, bool should_override)
+bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting)
{
QDir dir;
QString instID;
InstancePtr inst;
+ auto should_override = commiting.shouldOverride();
+
if (should_override) {
- // This is to avoid problems when the instance folder gets manually renamed
- if ((inst = getInstanceByManagedName(instanceName.originalName()))) {
- instID = QFileInfo(inst->instanceRoot()).fileName();
- } else if ((inst = getInstanceByManagedName(instanceName.modifiedName()))) {
- instID = QFileInfo(inst->instanceRoot()).fileName();
- } else {
- instID = FS::RemoveInvalidFilenameChars(instanceName.modifiedName(), '-');
- }
+ instID = commiting.originalInstanceID();
} else {
instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir);
}
+ Q_ASSERT(!instID.isEmpty());
+
{
WatchLock lock(m_watcher, m_instDir);
QString destination = FS::PathCombine(m_instDir, instID);
diff --git a/launcher/InstanceList.h b/launcher/InstanceList.h
index 3673298f..edacba3c 100644
--- a/launcher/InstanceList.h
+++ b/launcher/InstanceList.h
@@ -133,7 +133,7 @@ public:
* should_override is used when another similar instance already exists, and we want to override it
* - for instance, when updating it.
*/
- bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, bool should_override);
+ bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, const InstanceTask&);
/**
* Destroy a previously created staging area given by @keyPath - used when creation fails.
diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h
index bf29377d..5d8beca9 100644
--- a/launcher/InstancePageProvider.h
+++ b/launcher/InstancePageProvider.h
@@ -5,6 +5,7 @@
#include "ui/pages/BasePageProvider.h"
#include "ui/pages/instance/LogPage.h"
#include "ui/pages/instance/VersionPage.h"
+#include "ui/pages/instance/ManagedPackPage.h"
#include "ui/pages/instance/ModFolderPage.h"
#include "ui/pages/instance/ResourcePackPage.h"
#include "ui/pages/instance/TexturePackPage.h"
@@ -33,6 +34,7 @@ public:
values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
values.append(new VersionPage(onesix.get()));
+ values.append(ManagedPackPage::createPage(onesix.get()));
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
values.append(modsPage);
diff --git a/launcher/InstanceTask.cpp b/launcher/InstanceTask.cpp
index 55a44fd3..06682782 100644
--- a/launcher/InstanceTask.cpp
+++ b/launcher/InstanceTask.cpp
@@ -18,6 +18,29 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol
return InstanceNameChange::ShouldKeep;
}
+ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name)
+{
+ auto info = CustomMessageBox::selectable(
+ parent, QObject::tr("Similar modpack was found!"),
+ QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a "
+ "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
+ "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
+ .arg(original_version_name),
+ QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
+ info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance"));
+ info->setButtonText(QMessageBox::Abort, QObject::tr("Create new instance"));
+ info->setButtonText(QMessageBox::Reset, QObject::tr("Cancel"));
+
+ info->exec();
+
+ if (info->clickedButton() == info->button(QMessageBox::Ok))
+ return ShouldUpdate::Update;
+ if (info->clickedButton() == info->button(QMessageBox::Abort))
+ return ShouldUpdate::SkipUpdating;
+ return ShouldUpdate::Cancel;
+
+}
+
QString InstanceName::name() const
{
if (!m_modified_name.isEmpty())
diff --git a/launcher/InstanceTask.h b/launcher/InstanceTask.h
index e35533fc..7c02160a 100644
--- a/launcher/InstanceTask.h
+++ b/launcher/InstanceTask.h
@@ -6,6 +6,8 @@
/* Helpers */
enum class InstanceNameChange { ShouldChange, ShouldKeep };
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
+enum class ShouldUpdate { Update, SkipUpdating, Cancel };
+[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name);
struct InstanceName {
public:
@@ -42,10 +44,20 @@ class InstanceTask : public Task, public InstanceName {
void setGroup(const QString& group) { m_instGroup = group; }
QString group() const { return m_instGroup; }
+ [[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; }
+ void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; }
+
bool shouldOverride() const { return m_override_existing; }
+ [[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; };
+
protected:
- void setOverride(bool override) { m_override_existing = override; }
+ void setOverride(bool override, QString instance_id_to_override = {})
+ {
+ m_override_existing = override;
+ if (!instance_id_to_override.isEmpty())
+ m_original_instance_id = instance_id_to_override;
+ }
protected: /* data */
SettingsObjectPtr m_globalSettings;
@@ -54,4 +66,7 @@ class InstanceTask : public Task, public InstanceName {
QString m_stagingPath;
bool m_override_existing = false;
+ bool m_confirm_update = true;
+
+ QString m_original_instance_id;
};
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index ef635243..729268d7 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -81,13 +81,19 @@ bool FlameCreationTask::updateInstance()
auto instance_list = APPLICATION->instances();
// FIXME: How to handle situations when there's more than one install already for a given modpack?
- auto inst = instance_list->getInstanceByManagedName(originalName());
+ InstancePtr inst;
+ if (auto original_id = originalInstanceID(); !original_id.isEmpty()) {
+ inst = instance_list->getInstanceById(original_id);
+ Q_ASSERT(inst);
+ } else {
+ inst = instance_list->getInstanceByManagedName(originalName());
- if (!inst) {
- inst = instance_list->getInstanceById(originalName());
+ if (!inst) {
+ inst = instance_list->getInstanceById(originalName());
- if (!inst)
- return false;
+ if (!inst)
+ return false;
+ }
}
QString index_path(FS::PathCombine(m_stagingPath, "manifest.json"));
@@ -102,25 +108,14 @@ bool FlameCreationTask::updateInstance()
auto version_id = inst->getManagedPackVersionName();
auto version_str = !version_id.isEmpty() ? tr(" (version %1)").arg(version_id) : "";
- auto info = CustomMessageBox::selectable(
- m_parent, tr("Similar modpack was found!"),
- tr("One or more of your instances are from this same modpack%1. Do you want to create a "
- "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
- "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
- .arg(version_str),
- QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
- info->setButtonText(QMessageBox::Ok, tr("Update existing instance"));
- info->setButtonText(QMessageBox::Abort, tr("Create new instance"));
- info->setButtonText(QMessageBox::Reset, tr("Cancel"));
-
- info->exec();
-
- if (info->clickedButton() == info->button(QMessageBox::Abort))
- return false;
-
- if (info->clickedButton() == info->button(QMessageBox::Reset)) {
- m_abort = true;
- return false;
+ if (shouldConfirmUpdate()) {
+ auto should_update = askIfShouldUpdate(m_parent, version_str);
+ if (should_update == ShouldUpdate::SkipUpdating)
+ return false;
+ if (should_update == ShouldUpdate::Cancel) {
+ m_abort = true;
+ return false;
+ }
}
QDir old_inst_dir(inst->instanceRoot());
@@ -244,7 +239,7 @@ bool FlameCreationTask::updateInstance()
}
}
- setOverride(true);
+ setOverride(true, inst->id());
qDebug() << "Will override instance!";
m_instance = inst;
@@ -366,7 +361,7 @@ bool FlameCreationTask::createInstance()
FS::deletePath(jarmodsPath);
}
- instance.setManagedPack("flame", {}, m_pack.name, {}, m_pack.version);
+ instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version);
instance.setName(name());
m_mod_id_resolver = new Flame::FileResolvingTask(APPLICATION->network(), m_pack);
@@ -390,14 +385,6 @@ bool FlameCreationTask::createInstance()
setAbortable(false);
auto inst = m_instance.value();
- // Only change the name if it didn't use a custom name, so that the previous custom name
- // is preserved, but if we're using the original one, we update the version string.
- // NOTE: This needs to come before the copyManagedPack call!
- if (inst->name().contains(inst->getManagedPackVersionName())) {
- if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange)
- inst->setName(instance.name());
- }
-
inst->copyManagedPack(instance);
}
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h
index 5d227ee5..3a1c729f 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.h
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h
@@ -51,11 +51,21 @@ class FlameCreationTask final : public InstanceCreationTask {
Q_OBJECT
public:
- FlameCreationTask(const QString& staging_path, SettingsObjectPtr global_settings, QWidget* parent)
- : InstanceCreationTask(), m_parent(parent)
+ FlameCreationTask(const QString& staging_path,
+ SettingsObjectPtr global_settings,
+ QWidget* parent,
+ QString id,
+ QString version_id,
+ QString original_instance_id = {})
+ : InstanceCreationTask()
+ , m_parent(parent)
+ , m_managed_id(std::move(id))
+ , m_managed_version_id(std::move(version_id))
{
setStagingPath(staging_path);
setParentSettings(global_settings);
+
+ m_original_instance_id = std::move(original_instance_id);
}
bool abort() override;
@@ -78,5 +88,7 @@ class FlameCreationTask final : public InstanceCreationTask {
NetJob* m_process_update_file_info_job = nullptr;
NetJob::Ptr m_files_job = nullptr;
+ QString m_managed_id, m_managed_version_id;
+
std::optional<InstancePtr> m_instance;
};
diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
index ddeea224..1c0e8979 100644
--- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
@@ -33,13 +33,19 @@ bool ModrinthCreationTask::updateInstance()
auto instance_list = APPLICATION->instances();
// FIXME: How to handle situations when there's more than one install already for a given modpack?
- auto inst = instance_list->getInstanceByManagedName(originalName());
+ InstancePtr inst;
+ if (auto original_id = originalInstanceID(); !original_id.isEmpty()) {
+ inst = instance_list->getInstanceById(original_id);
+ Q_ASSERT(inst);
+ } else {
+ inst = instance_list->getInstanceByManagedName(originalName());
- if (!inst) {
- inst = instance_list->getInstanceById(originalName());
+ if (!inst) {
+ inst = instance_list->getInstanceById(originalName());
- if (!inst)
- return false;
+ if (!inst)
+ return false;
+ }
}
QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json");
@@ -49,25 +55,14 @@ bool ModrinthCreationTask::updateInstance()
auto version_name = inst->getManagedPackVersionName();
auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : "";
- auto info = CustomMessageBox::selectable(
- m_parent, tr("Similar modpack was found!"),
- tr("One or more of your instances are from this same modpack%1. Do you want to create a "
- "separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
- "updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
- .arg(version_str),
- QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
- info->setButtonText(QMessageBox::Ok, tr("Create new instance"));
- info->setButtonText(QMessageBox::Abort, tr("Update existing instance"));
- info->setButtonText(QMessageBox::Reset, tr("Cancel"));
-
- info->exec();
-
- if (info->clickedButton() == info->button(QMessageBox::Ok))
- return false;
-
- if (info->clickedButton() == info->button(QMessageBox::Reset)) {
- m_abort = true;
- return false;
+ if (shouldConfirmUpdate()) {
+ auto should_update = askIfShouldUpdate(m_parent, version_str);
+ if (should_update == ShouldUpdate::SkipUpdating)
+ return false;
+ if (should_update == ShouldUpdate::Cancel) {
+ m_abort = true;
+ return false;
+ }
}
// Remove repeated files, we don't need to download them!
@@ -149,7 +144,7 @@ bool ModrinthCreationTask::updateInstance()
}
- setOverride(true);
+ setOverride(true, inst->id());
qDebug() << "Will override instance!";
m_instance = inst;
@@ -222,7 +217,7 @@ bool ModrinthCreationTask::createInstance()
instance.setIconKey("modrinth");
}
- instance.setManagedPack("modrinth", getManagedPackID(), m_managed_name, m_managed_version_id, version());
+ instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version());
instance.setName(name());
instance.saveNow();
@@ -295,7 +290,8 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector<
}
if (set_managed_info) {
- m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID");
+ if (m_managed_version_id.isEmpty())
+ m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID");
m_managed_name = Json::ensureString(obj, "name", {}, "Managed Name");
}
@@ -395,13 +391,3 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector<
return true;
}
-
-QString ModrinthCreationTask::getManagedPackID() const
-{
- if (!m_source_url.isEmpty()) {
- QRegularExpression regex(R"(data\/(.*)\/versions)");
- return regex.match(m_source_url).captured(1);
- }
-
- return {};
-}
diff --git a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h
index e459aadf..122fc5ce 100644
--- a/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h
+++ b/launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h
@@ -14,11 +14,21 @@ class ModrinthCreationTask final : public InstanceCreationTask {
Q_OBJECT
public:
- ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString source_url = {})
- : InstanceCreationTask(), m_parent(parent), m_source_url(std::move(source_url))
+ ModrinthCreationTask(QString staging_path,
+ SettingsObjectPtr global_settings,
+ QWidget* parent,
+ QString id,
+ QString version_id = {},
+ QString original_instance_id = {})
+ : InstanceCreationTask()
+ , m_parent(parent)
+ , m_managed_id(std::move(id))
+ , m_managed_version_id(std::move(version_id))
{
setStagingPath(staging_path);
setParentSettings(global_settings);
+
+ m_original_instance_id = std::move(original_instance_id);
}
bool abort() override;
@@ -28,14 +38,12 @@ class ModrinthCreationTask final : public InstanceCreationTask {
private:
bool parseManifest(const QString&, std::vector<Modrinth::File>&, bool set_managed_info = true, bool show_optional_dialog = true);
- QString getManagedPackID() const;
private:
QWidget* m_parent = nullptr;
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion;
QString m_managed_id, m_managed_version_id, m_managed_name;
- QString m_source_url;
std::vector<Modrinth::File> m_files;
NetJob::Ptr m_files_job;
diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp
index 96f54067..4dca786f 100644
--- a/launcher/modplatform/modrinth/ModrinthPackManifest.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackManifest.cpp
@@ -128,6 +128,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
file.name = Json::requireString(obj, "name");
file.version = Json::requireString(obj, "version_number");
+ file.changelog = Json::ensureString(obj, "changelog");
file.id = Json::requireString(obj, "id");
file.project_id = Json::requireString(obj, "project_id");
diff --git a/launcher/modplatform/modrinth/ModrinthPackManifest.h b/launcher/modplatform/modrinth/ModrinthPackManifest.h
index 035dc62e..2973dfba 100644
--- a/launcher/modplatform/modrinth/ModrinthPackManifest.h
+++ b/launcher/modplatform/modrinth/ModrinthPackManifest.h
@@ -80,6 +80,7 @@ struct ModpackExtra {
struct ModpackVersion {
QString name;
QString version;
+ QString changelog;
QString id;
QString project_id;
diff --git a/launcher/ui/InstanceWindow.cpp b/launcher/ui/InstanceWindow.cpp
index 09ce0d67..c62b370f 100644
--- a/launcher/ui/InstanceWindow.cpp
+++ b/launcher/ui/InstanceWindow.cpp
@@ -132,6 +132,12 @@ InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
{
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
}
+
+ // add ourself as the modpack page's instance window
+ {
+ static_cast<ManagedPackPage*>(m_container->getPage("managed_pack"))->setInstanceWindow(this);
+ }
+
show();
}
diff --git a/launcher/ui/pages/BasePageContainer.h b/launcher/ui/pages/BasePageContainer.h
index f8c7adeb..b41fe12a 100644
--- a/launcher/ui/pages/BasePageContainer.h
+++ b/launcher/ui/pages/BasePageContainer.h
@@ -1,10 +1,13 @@
#pragma once
+class BasePage;
+
class BasePageContainer
{
public:
virtual ~BasePageContainer(){};
virtual bool selectPage(QString pageId) = 0;
+ virtual BasePage* getPage(QString pageId) { return nullptr; };
virtual void refreshContainer() = 0;
virtual bool requestClose() = 0;
};
diff --git a/launcher/ui/pages/instance/ManagedPackPage.cpp b/launcher/ui/pages/instance/ManagedPackPage.cpp
new file mode 100644
index 00000000..7a0d234c
--- /dev/null
+++ b/launcher/ui/pages/instance/ManagedPackPage.cpp
@@ -0,0 +1,432 @@
+// SPDX-FileCopyrightText: 2022 flow <flowlnlnln@gmail.com>
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+#include "ManagedPackPage.h"
+#include "ui_ManagedPackPage.h"
+
+#include <QListView>
+#include <QProxyStyle>
+
+#include <HoeDown.h>
+
+#include "Application.h"
+#include "BuildConfig.h"
+#include "InstanceImportTask.h"
+#include "InstanceList.h"
+#include "InstanceTask.h"
+#include "Json.h"
+
+#include "modplatform/modrinth/ModrinthPackManifest.h"
+
+#include "ui/InstanceWindow.h"
+#include "ui/dialogs/CustomMessageBox.h"
+#include "ui/dialogs/ProgressDialog.h"
+
+/** This is just to override the combo box popup behavior so that the combo box doesn't take the whole screen.
+ * ... thanks Qt.
+ */
+class NoBigComboBoxStyle : public QProxyStyle {
+ Q_OBJECT
+
+ public:
+ NoBigComboBoxStyle(QStyle* style) : QProxyStyle(style) {}
+
+ // clang-format off
+ int styleHint(QStyle::StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
+ {
+ if (hint == QStyle::SH_ComboBox_Popup)
+ return false;
+
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ // clang-format on
+};
+
+ManagedPackPage* ManagedPackPage::createPage(BaseInstance* inst, QString type, QWidget* parent)
+{
+ if (type == "modrinth")
+ return new ModrinthManagedPackPage(inst, nullptr, parent);
+ if (type == "flame" && (APPLICATION->capabilities() & Application::SupportsFlame))
+ return new FlameManagedPackPage(inst, nullptr, parent);
+
+ return new GenericManagedPackPage(inst, nullptr, parent);
+}
+
+ManagedPackPage::ManagedPackPage(BaseInstance* inst, InstanceWindow* instance_window, QWidget* parent)
+ : QWidget(parent), m_instance_window(instance_window), ui(new Ui::ManagedPackPage), m_inst(inst)
+{
+ Q_ASSERT(inst);
+
+ ui->setupUi(this);
+
+ ui->versionsComboBox->setStyle(new NoBigComboBoxStyle(ui->versionsComboBox->style()));
+
+ ui->reloadButton->setVisible(false);
+ connect(ui->reloadButton, &QPushButton::clicked, this, [this](bool){
+ ui->reloadButton->setVisible(false);
+
+ m_loaded = false;
+ // Pretend we're opening the page again
+ openedImpl();
+ });
+}
+
+ManagedPackPage::~ManagedPackPage()
+{
+ delete ui;
+}
+
+void ManagedPackPage::openedImpl()
+{
+ ui->packName->setText(m_inst->getManagedPackName());
+ ui->packVersion->setText(m_inst->getManagedPackVersionName());
+ ui->packOrigin->setText(tr("Website: <a href=%1>%2</a> | Pack ID: %3 | Version ID: %4")
+ .arg(url(), displa