mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2026-06-29 01:54:20 +03:00
Merge f5d9e25b26 into d2fa7cf7f7
This commit is contained in:
commit
096de785ea
8 changed files with 275 additions and 6 deletions
|
|
@ -255,6 +255,8 @@ set(MINECRAFT_SOURCES
|
||||||
minecraft/update/FoldersTask.h
|
minecraft/update/FoldersTask.h
|
||||||
minecraft/update/LibrariesTask.cpp
|
minecraft/update/LibrariesTask.cpp
|
||||||
minecraft/update/LibrariesTask.h
|
minecraft/update/LibrariesTask.h
|
||||||
|
minecraft/update/ModUpdateTask.cpp
|
||||||
|
minecraft/update/ModUpdateTask.h
|
||||||
|
|
||||||
minecraft/launch/ClaimAccount.cpp
|
minecraft/launch/ClaimAccount.cpp
|
||||||
minecraft/launch/ClaimAccount.h
|
minecraft/launch/ClaimAccount.h
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@
|
||||||
#include "minecraft/update/FoldersTask.h"
|
#include "minecraft/update/FoldersTask.h"
|
||||||
#include "minecraft/update/LegacyFMLLibrariesTask.h"
|
#include "minecraft/update/LegacyFMLLibrariesTask.h"
|
||||||
#include "minecraft/update/LibrariesTask.h"
|
#include "minecraft/update/LibrariesTask.h"
|
||||||
|
#include "minecraft/update/ModUpdateTask.h"
|
||||||
|
|
||||||
#include "java/JavaUtils.h"
|
#include "java/JavaUtils.h"
|
||||||
|
|
||||||
|
|
@ -263,10 +264,16 @@ void MinecraftInstance::loadSpecificSettings()
|
||||||
connect(dataPacksEnabled.get(), &Setting::SettingChanged, this, [this] { m_data_pack_list.reset(); });
|
connect(dataPacksEnabled.get(), &Setting::SettingChanged, this, [this] { m_data_pack_list.reset(); });
|
||||||
connect(dataPacksPath.get(), &Setting::SettingChanged, this, [this] { m_data_pack_list.reset(); });
|
connect(dataPacksPath.get(), &Setting::SettingChanged, this, [this] { m_data_pack_list.reset(); });
|
||||||
|
|
||||||
// Join server on launch, this does not have a global override
|
// Set mod downloaders, this does not have a global override
|
||||||
m_settings->registerSetting("OverrideModDownloadLoaders", false);
|
m_settings->registerSetting("OverrideModDownloadLoaders", false);
|
||||||
m_settings->registerSetting("ModDownloadLoaders", "[]");
|
m_settings->registerSetting("ModDownloadLoaders", "[]");
|
||||||
|
|
||||||
|
// Enable automatic mod updates, this does not have a global override
|
||||||
|
m_settings->registerSetting("AutomaticallyUpdateMods", false);
|
||||||
|
m_settings->registerSetting("AutomaticallyUpdateModsAll", false);
|
||||||
|
m_settings->registerSetting("AutomaticallyUpdateModsEnabled", true);
|
||||||
|
// m_settings->registerSetting("AutomaticallyUpdateModsSpecified", "[]");
|
||||||
|
|
||||||
qDebug() << "Instance-type specific settings were loaded!";
|
qDebug() << "Instance-type specific settings were loaded!";
|
||||||
|
|
||||||
setSpecificSettingsLoaded(true);
|
setSpecificSettingsLoaded(true);
|
||||||
|
|
@ -1202,6 +1209,13 @@ LaunchTask* MinecraftInstance::createLaunchTask(AuthSessionPtr session, Minecraf
|
||||||
process->appendStep(makeShared<ScanModFolders>(pptr));
|
process->appendStep(makeShared<ScanModFolders>(pptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update mods if "AutomaticallyUpdateMods" is true.
|
||||||
|
// Must come after ScanModFolders to ensure mods are loaded.
|
||||||
|
if (settings()->get("AutomaticallyUpdateMods").toBool()) {
|
||||||
|
process->appendStep(
|
||||||
|
makeShared<TaskStepWrapper>(pptr, makeShared<ModUpdateTask>(this, settings()->get("AutomaticallyUpdateModsEnabled").toBool())));
|
||||||
|
}
|
||||||
|
|
||||||
// make sure we have enough RAM, warn the user if we don't
|
// make sure we have enough RAM, warn the user if we don't
|
||||||
{
|
{
|
||||||
process->appendStep(makeShared<EnsureAvailableMemory>(pptr, this));
|
process->appendStep(makeShared<EnsureAvailableMemory>(pptr, this));
|
||||||
|
|
|
||||||
|
|
@ -45,19 +45,19 @@ void ScanModFolders::executeTask()
|
||||||
auto m_inst = m_parent->instance();
|
auto m_inst = m_parent->instance();
|
||||||
|
|
||||||
auto loaders = m_inst->loaderModList();
|
auto loaders = m_inst->loaderModList();
|
||||||
connect(loaders, &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone);
|
connect(loaders, &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone, Qt::UniqueConnection);
|
||||||
if (!loaders->update()) {
|
if (!loaders->update()) {
|
||||||
m_modsDone = true;
|
m_modsDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cores = m_inst->coreModList();
|
auto cores = m_inst->coreModList();
|
||||||
connect(cores, &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone);
|
connect(cores, &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone, Qt::UniqueConnection);
|
||||||
if (!cores->update()) {
|
if (!cores->update()) {
|
||||||
m_coreModsDone = true;
|
m_coreModsDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nils = m_inst->nilModList();
|
auto nils = m_inst->nilModList();
|
||||||
connect(nils, &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
|
connect(nils, &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone, Qt::UniqueConnection);
|
||||||
if (!nils->update()) {
|
if (!nils->update()) {
|
||||||
m_nilModsDone = true;
|
m_nilModsDone = true;
|
||||||
}
|
}
|
||||||
|
|
@ -66,25 +66,63 @@ void ScanModFolders::executeTask()
|
||||||
|
|
||||||
void ScanModFolders::modsDone()
|
void ScanModFolders::modsDone()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Check done in ScanModFolders modsDone...";
|
||||||
|
if (!isRunning()) {
|
||||||
|
qDebug() << "ScanModFolders::modsDone called but step not running; ignoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_modsDone = true;
|
m_modsDone = true;
|
||||||
checkDone();
|
checkDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanModFolders::coreModsDone()
|
void ScanModFolders::coreModsDone()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Check done in ScanModFolders coreModsDone...";
|
||||||
|
if (!isRunning()) {
|
||||||
|
qDebug() << "ScanModFolders::coreModsDone called but step not running; "
|
||||||
|
"ignoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_coreModsDone = true;
|
m_coreModsDone = true;
|
||||||
checkDone();
|
checkDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanModFolders::nilModsDone()
|
void ScanModFolders::nilModsDone()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Check done in ScanModFolders nilModsDone...";
|
||||||
|
if (!isRunning()) {
|
||||||
|
qDebug() << "ScanModFolders::nilModsDone called but step not running; ignoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_nilModsDone = true;
|
m_nilModsDone = true;
|
||||||
checkDone();
|
checkDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanModFolders::checkDone()
|
void ScanModFolders::checkDone()
|
||||||
{
|
{
|
||||||
|
qDebug() << "Check done in ScanModFolders...";
|
||||||
if (m_modsDone && m_coreModsDone && m_nilModsDone) {
|
if (m_modsDone && m_coreModsDone && m_nilModsDone) {
|
||||||
|
// Disconnect model signals before finishing so the finished step doesn't
|
||||||
|
// receive later updateFinished() notifications and try to finish again.
|
||||||
|
auto m_inst = m_parent->instance();
|
||||||
|
if (m_inst) {
|
||||||
|
disconnect(m_inst->loaderModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone);
|
||||||
|
disconnect(m_inst->coreModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone);
|
||||||
|
disconnect(m_inst->nilModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
|
||||||
|
}
|
||||||
|
|
||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScanModFolders::finalize()
|
||||||
|
{
|
||||||
|
auto m_inst = m_parent->instance();
|
||||||
|
if (!m_inst) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect(m_inst->loaderModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::modsDone);
|
||||||
|
disconnect(m_inst->coreModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::coreModsDone);
|
||||||
|
disconnect(m_inst->nilModList(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,12 @@ class ScanModFolders : public LaunchStep {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ScanModFolders(LaunchTask* parent) : LaunchStep(parent) {};
|
explicit ScanModFolders(LaunchTask* parent) : LaunchStep(parent) {};
|
||||||
virtual ~ScanModFolders() {};
|
virtual ~ScanModFolders() = default;
|
||||||
|
|
||||||
virtual void executeTask() override;
|
virtual void executeTask() override;
|
||||||
virtual bool canAbort() const override { return false; }
|
virtual bool canAbort() const override { return false; }
|
||||||
|
virtual void finalize() override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void coreModsDone();
|
void coreModsDone();
|
||||||
void modsDone();
|
void modsDone();
|
||||||
|
|
|
||||||
125
launcher/minecraft/update/ModUpdateTask.cpp
Normal file
125
launcher/minecraft/update/ModUpdateTask.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
#include "ModUpdateTask.h"
|
||||||
|
|
||||||
|
#include <ui/dialogs/ProgressDialog.h>
|
||||||
|
#include <ui/dialogs/ResourceUpdateDialog.h>
|
||||||
|
#include "Application.h"
|
||||||
|
#include "BuildConfig.h"
|
||||||
|
#include "launch/LaunchStep.h"
|
||||||
|
#include "minecraft/AssetsUtils.h"
|
||||||
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "minecraft/PackProfile.h"
|
||||||
|
#include "minecraft/mod/Mod.h"
|
||||||
|
#include "minecraft/mod/ModDetails.h"
|
||||||
|
#include "minecraft/mod/ModFolderModel.h"
|
||||||
|
#include "net/ApiDownload.h"
|
||||||
|
#include "net/ChecksumValidator.h"
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
|
||||||
|
ModUpdateTask::ModUpdateTask(MinecraftInstance* inst, bool enabledModsOnly)
|
||||||
|
{
|
||||||
|
m_instance = inst;
|
||||||
|
m_enabledModsOnly = enabledModsOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModUpdateTask::executeTask()
|
||||||
|
{
|
||||||
|
setStatus(tr("Updating mods..."));
|
||||||
|
qDebug() << "Updating mods...";
|
||||||
|
|
||||||
|
if (m_instance->typeName() != "Minecraft") {
|
||||||
|
return; // this is a null instance or a legacy instance
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* profile = static_cast<MinecraftInstance*>(m_instance)->getPackProfile();
|
||||||
|
if (!profile->getModLoaders().has_value()) {
|
||||||
|
emitFailed(tr("Mod updates are unavailable when mod loader is missing!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (APPLICATION->settings()->get("ModMetadataDisabled").toBool()) {
|
||||||
|
emitFailed(tr("Mod updates are unavailable when metadata is disabled!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceUpdateDialog only accepts Resource,
|
||||||
|
// so we convert the Mod* list to a Resource* list with a simple static_cast
|
||||||
|
auto model = m_instance->loaderModList();
|
||||||
|
auto _modsList = model->allMods();
|
||||||
|
QList<Resource*> modsList;
|
||||||
|
modsList.reserve(_modsList.size());
|
||||||
|
for (auto mod : _modsList) {
|
||||||
|
modsList.append(static_cast<Resource*>(mod));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out disabled mods if "AutomaticallyUpdateModsEnabled" is true
|
||||||
|
if (m_enabledModsOnly) {
|
||||||
|
modsList.erase(std::remove_if(modsList.begin(), modsList.end(), [](Resource* resource) { return !resource->enabled(); }),
|
||||||
|
modsList.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn ResourceUpdateDialog to handle mod updates
|
||||||
|
// 99% copied from ModFolderPage.cpp
|
||||||
|
auto parent = QApplication::activeWindow();
|
||||||
|
ResourceUpdateDialog updateDialog =
|
||||||
|
ResourceUpdateDialog(parent, m_instance, model, modsList, m_includeDeps, profile->getModLoadersList());
|
||||||
|
updateDialog.checkCandidates();
|
||||||
|
|
||||||
|
if (updateDialog.aborted()) {
|
||||||
|
CustomMessageBox::selectable(parent, tr("Aborted"), tr("The mod updater was aborted!"), QMessageBox::Warning)->show();
|
||||||
|
emitAborted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (updateDialog.noUpdates()) {
|
||||||
|
QString message{ tr("'%1' is up-to-date! :)").arg(modsList.front()->name()) };
|
||||||
|
if (modsList.size() > 1) {
|
||||||
|
if (!m_enabledModsOnly) {
|
||||||
|
message = tr("All mods are up-to-date! :)");
|
||||||
|
} else {
|
||||||
|
message = tr("All enabled mods are up-to-date! :)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CustomMessageBox::selectable(parent, tr("Update checker"), message)->exec();
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDialog.exec() != 0) {
|
||||||
|
auto* tasks = new ConcurrentTask("Download Mods", APPLICATION->settings()->get("NumberOfConcurrentDownloads").toInt());
|
||||||
|
connect(tasks, &Task::failed, [this, parent, tasks](const QString& reason) {
|
||||||
|
CustomMessageBox::selectable(parent, tr("Error"), reason, QMessageBox::Critical)->show();
|
||||||
|
tasks->deleteLater();
|
||||||
|
});
|
||||||
|
connect(tasks, &Task::aborted, [this, parent, tasks]() {
|
||||||
|
CustomMessageBox::selectable(parent, tr("Aborted"), tr("Download stopped by user."), QMessageBox::Information)->show();
|
||||||
|
tasks->deleteLater();
|
||||||
|
});
|
||||||
|
connect(tasks, &Task::succeeded, [this, parent, tasks]() {
|
||||||
|
QStringList warnings = tasks->warnings();
|
||||||
|
if (warnings.count()) {
|
||||||
|
CustomMessageBox::selectable(parent, tr("Warnings"), warnings.join('\n'), QMessageBox::Warning)->show();
|
||||||
|
}
|
||||||
|
tasks->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& task : updateDialog.getTasks()) {
|
||||||
|
tasks->addTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressDialog loadDialog(parent);
|
||||||
|
loadDialog.setSkipButton(true, tr("Abort"));
|
||||||
|
loadDialog.execWithTask(tasks);
|
||||||
|
}
|
||||||
|
model->update();
|
||||||
|
qDebug() << "Finished updating mods...";
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModUpdateTask::canAbort() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModUpdateTask::abort()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
27
launcher/minecraft/update/ModUpdateTask.h
Normal file
27
launcher/minecraft/update/ModUpdateTask.h
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
class MinecraftInstance;
|
||||||
|
|
||||||
|
class ModUpdateTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModUpdateTask(MinecraftInstance* inst, bool enabled);
|
||||||
|
virtual ~ModUpdateTask() = default;
|
||||||
|
|
||||||
|
void executeTask() override;
|
||||||
|
|
||||||
|
bool canAbort() const override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static QString resourceUrl();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinecraftInstance* m_instance;
|
||||||
|
bool m_enabledModsOnly;
|
||||||
|
bool m_includeDeps = true;
|
||||||
|
};
|
||||||
|
|
@ -61,6 +61,7 @@ MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstance* instance, QW
|
||||||
m_ui->serverJoinGroupBox->hide();
|
m_ui->serverJoinGroupBox->hide();
|
||||||
m_ui->globalDataPacksGroupBox->hide();
|
m_ui->globalDataPacksGroupBox->hide();
|
||||||
m_ui->loaderGroup->hide();
|
m_ui->loaderGroup->hide();
|
||||||
|
m_ui->autoModUpdateGroup->hide();
|
||||||
} else {
|
} else {
|
||||||
m_javaSettings = new JavaSettingsWidget(m_instance, this);
|
m_javaSettings = new JavaSettingsWidget(m_instance, this);
|
||||||
m_ui->javaScrollArea->setWidget(m_javaSettings);
|
m_ui->javaScrollArea->setWidget(m_javaSettings);
|
||||||
|
|
@ -120,6 +121,18 @@ MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstance* instance, QW
|
||||||
m_ui->legacyFabric, m_ui->ornithe, m_ui->rift }) {
|
m_ui->legacyFabric, m_ui->ornithe, m_ui->rift }) {
|
||||||
connect(c, &QCheckBox::stateChanged, this, &MinecraftSettingsWidget::saveSelectedLoaders);
|
connect(c, &QCheckBox::stateChanged, this, &MinecraftSettingsWidget::saveSelectedLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(m_ui->autoModUpdateGroup, &QGroupBox::toggled, this, [this](bool value) {
|
||||||
|
m_instance->settings()->set("AutomaticallyUpdateMods", value);
|
||||||
|
// if (!value) {
|
||||||
|
// m_instance->settings()->reset("AutomaticallyUpdateModsAll");
|
||||||
|
// m_instance->settings()->reset("AutomaticallyUpdateModsEnabled");
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
connect(m_ui->allMods, &QAbstractButton::toggled, this,
|
||||||
|
[this](bool value) { m_instance->settings()->set("AutomaticallyUpdateModsAll", value); });
|
||||||
|
connect(m_ui->enabledMods, &QAbstractButton::toggled, this,
|
||||||
|
[this](bool value) { m_instance->settings()->set("AutomaticallyUpdateModsEnabled", value); });
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui->maximizedWarning->hide();
|
m_ui->maximizedWarning->hide();
|
||||||
|
|
@ -248,6 +261,10 @@ void MinecraftSettingsWidget::loadSettings()
|
||||||
|
|
||||||
m_ui->serverJoinGroupBox->setChecked(settings->get("JoinServerOnLaunch").toBool());
|
m_ui->serverJoinGroupBox->setChecked(settings->get("JoinServerOnLaunch").toBool());
|
||||||
|
|
||||||
|
m_ui->autoModUpdateGroup->setChecked(settings->get("AutomaticallyUpdateMods").toBool());
|
||||||
|
m_ui->allMods->setChecked(settings->get("AutomaticallyUpdateModsAll").toBool());
|
||||||
|
m_ui->enabledMods->setChecked(settings->get("AutomaticallyUpdateModsEnabled").toBool());
|
||||||
|
|
||||||
m_ui->instanceAccountGroupBox->setChecked(settings->get("UseAccountForInstance").toBool());
|
m_ui->instanceAccountGroupBox->setChecked(settings->get("UseAccountForInstance").toBool());
|
||||||
updateAccountsMenu(*settings);
|
updateAccountsMenu(*settings);
|
||||||
|
|
||||||
|
|
@ -455,6 +472,21 @@ void MinecraftSettingsWidget::saveSettings()
|
||||||
settings->reset("JoinWorldOnLaunch");
|
settings->reset("JoinWorldOnLaunch");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool automaticallyUpdateMods = m_ui->autoModUpdateGroup->isChecked();
|
||||||
|
settings->set("AutomaticallyUpdateMods", automaticallyUpdateMods);
|
||||||
|
// if (automaticallyUpdateMods) {
|
||||||
|
if (m_ui->allMods->isChecked()) {
|
||||||
|
settings->set("AutomaticallyUpdateModsAll", true);
|
||||||
|
settings->set("AutomaticallyUpdateModsEnabled", false);
|
||||||
|
} else {
|
||||||
|
settings->set("AutomaticallyUpdateModsAll", false);
|
||||||
|
settings->set("AutomaticallyUpdateModsEnabled", true);
|
||||||
|
}
|
||||||
|
// } else {
|
||||||
|
// settings->reset("AutomaticallyUpdateModsAll");
|
||||||
|
// settings->reset("AutomaticallyUpdateModsEnabled");
|
||||||
|
// }
|
||||||
|
|
||||||
// Use an account for this instance
|
// Use an account for this instance
|
||||||
bool useAccountForInstance = m_ui->instanceAccountGroupBox->isChecked();
|
bool useAccountForInstance = m_ui->instanceAccountGroupBox->isChecked();
|
||||||
settings->set("UseAccountForInstance", useAccountForInstance);
|
settings->set("UseAccountForInstance", useAccountForInstance);
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Allows installing data packs across all worlds if an applicable mod is installed.
|
<string>Allows installing data packs across all worlds if an applicable mod is installed.
|
||||||
It is most likely you will need to change the path - please refer to the mod's website.</string>
|
It is most likely you will need to change the path - please refer to the mod's website.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -554,6 +554,35 @@ It is most likely you will need to change the path - please refer to the mod's w
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="autoModUpdateGroup">
|
||||||
|
<property name="title">
|
||||||
|
<string>Automatically Update Mods</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="allMods">
|
||||||
|
<property name="text">
|
||||||
|
<string>All mods</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="enabledMods">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enabled mods only</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue