PrismLauncher/launcher/ui/pages/modplatform/CustomPage.cpp
Omegaplex abfa8b51f1 Add Babric Mod Loader support
Assisted-by: claude:claude-4.6-sonnet
Signed-off-by: Omegaplex <95503207+Omegaplexx@users.noreply.github.com>
2026-06-26 19:11:11 +03:00

270 lines
10 KiB
C++

// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CustomPage.h"
#include "ui_CustomPage.h"
#include <QTabBar>
#include "Application.h"
#include "Filter.h"
#include "Version.h"
#include "meta/Index.h"
#include "meta/VersionList.h"
#include "minecraft/BabricCreationTask.h"
#include "minecraft/VanillaInstanceCreationTask.h"
#include "ui/dialogs/NewInstanceDialog.h"
#include <QTimer>
CustomPage::CustomPage(NewInstanceDialog* dialog, QWidget* parent) : QWidget(parent), dialog(dialog), ui(new Ui::CustomPage)
{
ui->setupUi(this);
// babricInfoLabel and loaderStack come from CustomPage.ui —
// no runtime widget creation or layout manipulation needed here.
ui->babricInfoLabel->setText(
tr("<b>Babric</b> is a Fabric-based mod loader "
"for <b>Minecraft Beta 1.7.3</b>.<br><br>"
"Clicking <b>OK</b> will create an instance with:<ul>"
"<li>Minecraft b1.7.3</li>"
"<li>Fabric Loader 0.18.4 + Babric mapping layer</li>"
"</ul>"));
ui->loaderPage1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
connect(ui->versionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedVersion);
filterChanged();
connect(ui->alphaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
connect(ui->betaFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
connect(ui->snapshotFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
connect(ui->releaseFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
connect(ui->experimentsFilter, &QCheckBox::stateChanged, this, &CustomPage::filterChanged);
connect(ui->refreshBtn, &QPushButton::clicked, this, &CustomPage::refresh);
connect(ui->loaderVersionList, &VersionSelectWidget::selectedVersionChanged, this, &CustomPage::setSelectedLoaderVersion);
connect(ui->noneFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->neoForgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->forgeFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->fabricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->quiltFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->babricFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->liteLoaderFilter, &QRadioButton::toggled, this, &CustomPage::loaderFilterChanged);
connect(ui->loaderRefreshBtn, &QPushButton::clicked, this, &CustomPage::loaderRefresh);
}
void CustomPage::openedImpl()
{
if (!initialized) {
auto vlist = APPLICATION->metadataIndex()->get("net.minecraft");
ui->versionList->initialize(vlist.get());
initialized = true;
} else {
suggestCurrent();
}
}
void CustomPage::refresh()
{
ui->versionList->loadList(true);
}
void CustomPage::loaderRefresh()
{
if (ui->noneFilter->isChecked() || ui->babricFilter->isChecked())
return;
ui->loaderVersionList->loadList(true);
}
void CustomPage::filterChanged()
{
QStringList out;
if (ui->alphaFilter->isChecked())
out << "(alpha)";
if (ui->betaFilter->isChecked())
out << "(beta)";
if (ui->snapshotFilter->isChecked())
out << "(snapshot)";
if (ui->releaseFilter->isChecked())
out << "(release)";
if (ui->experimentsFilter->isChecked())
out << "(experiment)";
auto regexp = out.join('|');
ui->versionList->setFilter(BaseVersionList::TypeRole, Filters::regexp(QRegularExpression(regexp)));
}
void CustomPage::setLoaderWidgetMode(bool isBabric)
{
ui->loaderStack->setCurrentIndex(isBabric ? 1 : 0);
ui->loaderRefreshBtn->setEnabled(!isBabric);
for (int i = 0; i < ui->verticalLayout_2->count(); i++) {
if (QSpacerItem* spacer = ui->verticalLayout_2->itemAt(i)->spacerItem()) {
spacer->changeSize(20, 0, QSizePolicy::Minimum,
isBabric ? QSizePolicy::Fixed : QSizePolicy::Expanding);
ui->verticalLayout_2->invalidate();
break;
}
}
}
void CustomPage::loaderFilterChanged()
{
// Always sync the widget visibility first.
setLoaderWidgetMode(ui->babricFilter->isChecked());
const QString minecraftVersion = m_selectedVersion ? m_selectedVersion->descriptor() : QString();
if (ui->noneFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA");
ui->loaderVersionList->setEmptyString(tr("No mod loader is selected."));
ui->loaderVersionList->setEmptyMode(VersionListView::String);
m_selectedLoader.clear();
suggestCurrent();
return;
}
if (ui->babricFilter->isChecked()) {
// No meta-server lookup needed — everything is embedded.
m_selectedLoader = "babric";
suggestCurrent();
return;
}
if (minecraftVersion.isEmpty()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA");
ui->loaderVersionList->setEmptyString(tr("No Minecraft version is selected."));
ui->loaderVersionList->setEmptyMode(VersionListView::String);
return;
}
if (ui->neoForgeFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "net.neoforged";
} else if (ui->forgeFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "net.minecraftforge";
} else if (ui->fabricFilter->isChecked()) {
// FIXME: dirty hack because the launcher is unaware of Fabric's dependencies
if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
else // Fabric/Quilt unsupported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
m_selectedLoader = "net.fabricmc.fabric-loader";
} else if (ui->quiltFilter->isChecked()) {
// FIXME: dirty hack because the launcher is unaware of Quilt's dependencies (same as Fabric)
if (Version(minecraftVersion) >= Version("1.14")) // Fabric/Quilt supported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "");
else // Fabric/Quilt unsupported
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, "AAA"); // clear list
m_selectedLoader = "org.quiltmc.quilt-loader";
} else if (ui->liteLoaderFilter->isChecked()) {
ui->loaderVersionList->setExactFilter(BaseVersionList::ParentVersionRole, minecraftVersion);
m_selectedLoader = "com.mumfrey.liteloader";
}
auto vlist = APPLICATION->metadataIndex()->get(m_selectedLoader);
ui->loaderVersionList->initialize(vlist.get());
ui->loaderVersionList->selectRecommended();
ui->loaderVersionList->setEmptyString(tr("No versions are currently available for Minecraft %1").arg(minecraftVersion));
}
CustomPage::~CustomPage()
{
delete ui;
}
bool CustomPage::shouldDisplay() const
{
return true;
}
void CustomPage::retranslate()
{
ui->retranslateUi(this);
}
BaseVersion::Ptr CustomPage::selectedVersion() const
{
return m_selectedVersion;
}
BaseVersion::Ptr CustomPage::selectedLoaderVersion() const
{
return m_selectedLoaderVersion;
}
QString CustomPage::selectedLoader() const
{
return m_selectedLoader;
}
void CustomPage::suggestCurrent()
{
if (!isOpened)
return;
if (ui->babricFilter->isChecked()) {
dialog->setSuggestedPack("b1.7.3", new BabricCreationTask());
dialog->setSuggestedIcon("fabric");
return;
}
if (!m_selectedVersion) {
dialog->setSuggestedPack();
return;
}
// There isn't a selected version if the version list is empty
if (ui->loaderVersionList->selectedVersion() == nullptr)
dialog->setSuggestedPack(m_selectedVersion->descriptor(), new VanillaCreationTask(m_selectedVersion));
else {
dialog->setSuggestedPack(m_selectedVersion->descriptor(),
new VanillaCreationTask(m_selectedVersion, m_selectedLoader, m_selectedLoaderVersion));
}
dialog->setSuggestedIcon("default");
}
void CustomPage::setSelectedVersion(BaseVersion::Ptr version)
{
m_selectedVersion = version;
suggestCurrent();
loaderFilterChanged();
}
void CustomPage::setSelectedLoaderVersion(BaseVersion::Ptr version)
{
m_selectedLoaderVersion = version;
suggestCurrent();
}