diff --git a/CMakeLists.txt b/CMakeLists.txt index 345bb366..4617020a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,12 +309,8 @@ SET(MULTIMC_SOURCES gui/dialogs/InstanceSettings.cpp gui/dialogs/IconPickerDialog.h gui/dialogs/IconPickerDialog.cpp - gui/dialogs/LegacyModEditDialog.h - gui/dialogs/LegacyModEditDialog.cpp - gui/dialogs/OneSixModEditDialog.h - gui/dialogs/OneSixModEditDialog.cpp - gui/dialogs/ModEditDialogCommon.h - gui/dialogs/ModEditDialogCommon.cpp + gui/dialogs/InstanceEditDialog.h + gui/dialogs/InstanceEditDialog.cpp gui/dialogs/EditNotesDialog.h gui/dialogs/EditNotesDialog.cpp gui/dialogs/CustomMessageBox.h @@ -395,10 +391,6 @@ SET(MULTIMC_SOURCES logic/net/ByteArrayDownload.cpp logic/net/CacheDownload.h logic/net/CacheDownload.cpp - logic/net/ForgeMirrors.h - logic/net/ForgeMirrors.cpp - logic/net/ForgeXzDownload.h - logic/net/ForgeXzDownload.cpp logic/net/NetJob.h logic/net/NetJob.cpp logic/net/HttpMetaCache.h @@ -449,9 +441,6 @@ SET(MULTIMC_SOURCES logic/LegacyUpdate.h logic/LegacyUpdate.cpp - logic/LegacyForge.h - logic/LegacyForge.cpp - # OneSix instances logic/OneSixUpdate.h logic/OneSixUpdate.cpp @@ -476,14 +465,6 @@ SET(MULTIMC_SOURCES # Mod installers logic/BaseInstaller.h logic/BaseInstaller.cpp - logic/ForgeInstaller.h - logic/ForgeInstaller.cpp - logic/LiteLoaderInstaller.h - logic/LiteLoaderInstaller.cpp - - # Nostalgia - logic/NostalgiaInstance.h - logic/NostalgiaInstance.cpp # FTB logic/OneSixFTBInstance.h @@ -500,12 +481,8 @@ SET(MULTIMC_SOURCES logic/lists/MinecraftVersionList.cpp logic/lists/LwjglVersionList.h logic/lists/LwjglVersionList.cpp - logic/lists/ForgeVersionList.h - logic/lists/ForgeVersionList.cpp logic/lists/JavaVersionList.h logic/lists/JavaVersionList.cpp - logic/lists/LiteLoaderVersionList.h - logic/lists/LiteLoaderVersionList.cpp # the screenshots feature logic/screenshots/Screenshot.h @@ -566,6 +543,29 @@ SET(MULTIMC_SOURCES logic/tools/JProfiler.cpp logic/tools/JVisualVM.h logic/tools/JVisualVM.cpp + + # Forge and all things forge related + logic/forge/ForgeData.h + logic/forge/ForgeData.cpp + logic/forge/ForgeVersion.h + logic/forge/ForgeVersion.cpp + logic/forge/ForgeVersionList.h + logic/forge/ForgeVersionList.cpp + logic/forge/ForgeMirror.h + logic/forge/ForgeMirrors.h + logic/forge/ForgeMirrors.cpp + logic/forge/ForgeXzDownload.h + logic/forge/ForgeXzDownload.cpp + logic/forge/LegacyForge.h + logic/forge/LegacyForge.cpp + logic/forge/ForgeInstaller.h + logic/forge/ForgeInstaller.cpp + + # Liteloader and related things + logic/liteloader/LiteLoaderInstaller.h + logic/liteloader/LiteLoaderInstaller.cpp + logic/liteloader/LiteLoaderVersionList.h + logic/liteloader/LiteLoaderVersionList.cpp ) @@ -585,8 +585,7 @@ SET(MULTIMC_UIS gui/dialogs/InstanceSettings.ui gui/dialogs/ProgressDialog.ui gui/dialogs/IconPickerDialog.ui - gui/dialogs/LegacyModEditDialog.ui - gui/dialogs/OneSixModEditDialog.ui + gui/dialogs/InstanceEditDialog.ui gui/dialogs/EditNotesDialog.ui gui/dialogs/AccountListDialog.ui gui/dialogs/AccountSelectDialog.ui diff --git a/MultiMC.cpp b/MultiMC.cpp index c1fc089c..28fe8e26 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -17,8 +17,9 @@ #include "logic/icons/IconList.h" #include "logic/lists/LwjglVersionList.h" #include "logic/lists/MinecraftVersionList.h" -#include "logic/lists/ForgeVersionList.h" -#include "logic/lists/LiteLoaderVersionList.h" +#include "logic/liteloader/LiteLoaderVersionList.h" + +#include "logic/forge/ForgeVersionList.h" #include "logic/news/NewsChecker.h" diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 5ba05b2a..95f2ac4c 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -1032,7 +1032,7 @@ void MainWindow::on_actionViewSelectedInstFolder_triggered() } } -void MainWindow::on_actionEditInstMods_triggered() +void MainWindow::on_actionEditInstance_triggered() { if (m_selectedInstance) { @@ -1339,99 +1339,12 @@ void MainWindow::startTask(Task *task) task->start(); } -// Create A Desktop Shortcut -void MainWindow::on_actionMakeDesktopShortcut_triggered() -{ - QString name("Test"); - name = QInputDialog::getText(this, tr("MultiMC Shortcut"), tr("Enter a Shortcut Name."), - QLineEdit::Normal, name); - - Util::createShortCut(Util::getDesktopDir(), QApplication::instance()->applicationFilePath(), - QStringList() << "-dl" << QDir::currentPath() << "test", name, - "application-x-octet-stream"); - - CustomMessageBox::selectable( - this, tr("Not useful"), - tr("A Dummy Shortcut was created. it will not do anything productive"), - QMessageBox::Warning)->show(); -} - // BrowserDialog void MainWindow::openWebPage(QUrl url) { QDesktopServices::openUrl(url); } -void MainWindow::on_actionChangeInstMCVersion_triggered() -{ - if (view->selectionModel()->selectedIndexes().count() < 1) - return; - - VersionSelectDialog vselect(m_selectedInstance->versionList().get(), - tr("Change Minecraft version"), this); - vselect.setFuzzyFilter(1, "*OneSix*"); - if (!vselect.exec() || !vselect.selectedVersion()) - return; - - if (!MMC->accounts()->anyAccountIsValid()) - { - CustomMessageBox::selectable( - this, tr("Error"), - tr("MultiMC cannot download Minecraft or update instances unless you have at least " - "one account added.\nPlease add your Mojang or Minecraft account."), - QMessageBox::Warning)->show(); - return; - } - - if (m_selectedInstance->versionIsCustom()) - { - auto result = CustomMessageBox::selectable( - this, tr("Are you sure?"), - tr("This will remove any library/version customization you did previously. " - "This includes things like Forge install and similar."), - QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Abort, - QMessageBox::Abort)->exec(); - - if (result != QMessageBox::Ok) - return; - } - m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor()); - - auto updateTask = m_selectedInstance->doUpdate(); - if (!updateTask) - { - return; - } - ProgressDialog tDialog(this); - connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); - tDialog.exec(updateTask.get()); -} - -void MainWindow::on_actionChangeInstLWJGLVersion_triggered() -{ - if (!m_selectedInstance) - return; - - LWJGLSelectDialog lselect(this); - lselect.exec(); - if (lselect.result() == QDialog::Accepted) - { - auto ptr = std::dynamic_pointer_cast(m_selectedInstance); - if(ptr) - ptr->setLWJGLVersion(lselect.selectedVersion()); - } -} - -void MainWindow::on_actionInstanceSettings_triggered() -{ - if (view->selectionModel()->selectedIndexes().count() < 1) - return; - - InstanceSettings settings(&m_selectedInstance->settings(), this); - settings.setWindowTitle(tr("Instance settings")); - settings.exec(); -} - void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex &previous) { if(!current.isValid()) @@ -1446,12 +1359,8 @@ void MainWindow::instanceChanged(const QModelIndex ¤t, const QModelIndex & { ui->instanceToolBar->setEnabled(m_selectedInstance->canLaunch()); renameButton->setText(m_selectedInstance->name()); - ui->actionChangeInstLWJGLVersion->setEnabled( - m_selectedInstance->menuActionEnabled("actionChangeInstLWJGLVersion")); - ui->actionEditInstMods->setEnabled( - m_selectedInstance->menuActionEnabled("actionEditInstMods")); - ui->actionChangeInstMCVersion->setEnabled( - m_selectedInstance->menuActionEnabled("actionChangeInstMCVersion")); + ui->actionEditInstance->setEnabled( + m_selectedInstance->menuActionEnabled("actionEditInstance")); m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); updateInstanceToolIcon(m_selectedInstance->iconKey()); diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 69cf11b0..0cd2e84b 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -103,11 +103,7 @@ slots: void on_actionRenameInstance_triggered(); - void on_actionMakeDesktopShortcut_triggered(); - - void on_actionChangeInstMCVersion_triggered(); - - void on_actionEditInstMods_triggered(); + void on_actionEditInstance_triggered(); void on_actionEditInstNotes_triggered(); @@ -135,12 +131,8 @@ slots: void taskStart(); void taskEnd(); - void on_actionChangeInstLWJGLVersion_triggered(); - void instanceEnded(); - void on_actionInstanceSettings_triggered(); - // called when an icon is changed in the icon model. void iconUpdated(QString); diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 1d7fbec9..8ee196fd 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -74,7 +74,7 @@ - + @@ -115,10 +115,7 @@ - - - - + @@ -284,7 +281,7 @@ Open the MultiMC Patreon page. - + @@ -388,82 +385,18 @@ Edit the notes for the selected instance. - - - true - - - Settings - - - Change settings for the selected instance. - - - Change settings for the selected instance. - - - - - false - - - Make Shortcut - - - Make a shortcut on the desktop for the selected instance. - - - Make a shortcut on the desktop for the selected instance. - - - - - false - - - Manage Saves - - - Manage saves for the selected instance. - - - Manage saves for the selected instance. - - - + Edit Mods - - Edit the mods for the selected instance. - - - Edit the mods for the selected instance. - - - - - Change Version + + Edit Instance - Change the selected instance's Minecraft version. + Change the instance settings, mods and versions. - Change the selected instance's Minecraft version. - - - - - false - - - Change LWJGL - - - Change the version of LWJGL for the selected instance to use. - - - Change the version of LWJGL for the selected instance to use. + Change the instance settings, mods and versions. diff --git a/gui/dialogs/OneSixModEditDialog.cpp b/gui/dialogs/InstanceEditDialog.cpp similarity index 52% rename from gui/dialogs/OneSixModEditDialog.cpp rename to gui/dialogs/InstanceEditDialog.cpp index a3598eb9..fe2d1b03 100644 --- a/gui/dialogs/OneSixModEditDialog.cpp +++ b/gui/dialogs/InstanceEditDialog.cpp @@ -23,27 +23,74 @@ #include #include -#include "OneSixModEditDialog.h" -#include "ModEditDialogCommon.h" -#include "ui_OneSixModEditDialog.h" +#include "InstanceEditDialog.h" +#include "ui_InstanceEditDialog.h" #include "gui/Platform.h" #include "gui/dialogs/CustomMessageBox.h" #include "gui/dialogs/VersionSelectDialog.h" #include "gui/dialogs/ProgressDialog.h" +#include "InstanceSettings.h" #include "logic/ModList.h" #include "logic/VersionFinal.h" #include "logic/EnabledItemFilter.h" -#include "logic/lists/ForgeVersionList.h" -#include "logic/lists/LiteLoaderVersionList.h" -#include "logic/ForgeInstaller.h" -#include "logic/LiteLoaderInstaller.h" +#include "logic/forge/ForgeVersionList.h" +#include "logic/forge/ForgeInstaller.h" +#include "logic/liteloader/LiteLoaderVersionList.h" +#include "logic/liteloader/LiteLoaderInstaller.h" #include "logic/OneSixVersionBuilder.h" +#include "logic/auth/MojangAccountList.h" -OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) - : QDialog(parent), ui(new Ui::OneSixModEditDialog), m_inst(inst) +#include +#include + +#include "CustomMessageBox.h" +#include +#include +#include +#include + +bool lastfirst(QModelIndexList &list, int &first, int &last) +{ + if (!list.size()) + return false; + first = last = list[0].row(); + for (auto item : list) + { + int row = item.row(); + if (row < first) + first = row; + if (row > last) + last = row; + } + return true; +} + +void showWebsiteForMod(QWidget *parentDlg, Mod &m) +{ + QString url = m.homeurl(); + if (url.size()) + { + // catch the cases where the protocol is missing + if (!url.startsWith("http")) + { + url = "http://" + url; + } + QDesktopServices::openUrl(url); + } + else + { + CustomMessageBox::selectable( + parentDlg, QObject::tr("How sad!"), + QObject::tr("The mod author didn't provide a website link for this mod."), + QMessageBox::Warning); + } +} + +InstanceEditDialog::InstanceEditDialog(OneSixInstance *inst, QWidget *parent) + : QDialog(parent), ui(new Ui::InstanceEditDialog), m_inst(inst) { MultiMCPlatform::fixWM_CLASS(this); ui->setupUi(this); @@ -58,7 +105,7 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) ui->libraryTreeView->setModel(main_model); ui->libraryTreeView->installEventFilter(this); connect(ui->libraryTreeView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &OneSixModEditDialog::versionCurrent); + this, &InstanceEditDialog::versionCurrent); updateVersionControls(); } else @@ -76,6 +123,17 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(loaderCurrent(QModelIndex, QModelIndex))); } + // Core mods + { + ensureFolderPathExists(m_inst->coreModsDir()); + m_coremods = m_inst->coreModList(); + ui->coreModsTreeView->setModel(m_coremods.get()); + ui->coreModsTreeView->installEventFilter(this); + m_coremods->startWatching(); + auto smodel = ui->coreModsTreeView->selectionModel(); + connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), + SLOT(coreCurrent(QModelIndex, QModelIndex))); + } // resource packs { ensureFolderPathExists(m_inst->resourcePacksDir()); @@ -86,23 +144,24 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) } connect(m_inst, &OneSixInstance::versionReloaded, this, - &OneSixModEditDialog::updateVersionControls); + &InstanceEditDialog::updateVersionControls); } -OneSixModEditDialog::~OneSixModEditDialog() +InstanceEditDialog::~InstanceEditDialog() { m_mods->stopWatching(); m_resourcepacks->stopWatching(); + m_coremods->stopWatching(); delete ui; } -void OneSixModEditDialog::updateVersionControls() +void InstanceEditDialog::updateVersionControls() { ui->forgeBtn->setEnabled(true); ui->liteloaderBtn->setEnabled(true); } -void OneSixModEditDialog::disableVersionControls() +void InstanceEditDialog::disableVersionControls() { ui->forgeBtn->setEnabled(false); ui->liteloaderBtn->setEnabled(false); @@ -110,7 +169,7 @@ void OneSixModEditDialog::disableVersionControls() ui->removeLibraryBtn->setEnabled(false); } -bool OneSixModEditDialog::reloadInstanceVersion() +bool InstanceEditDialog::reloadInstanceVersion() { try { @@ -131,12 +190,19 @@ bool OneSixModEditDialog::reloadInstanceVersion() } } -void OneSixModEditDialog::on_reloadLibrariesBtn_clicked() +void InstanceEditDialog::on_settingsBtn_clicked() +{ + InstanceSettings settings(&m_inst->settings(), this); + settings.setWindowTitle(tr("Instance settings")); + settings.exec(); +} + +void InstanceEditDialog::on_reloadLibrariesBtn_clicked() { reloadInstanceVersion(); } -void OneSixModEditDialog::on_removeLibraryBtn_clicked() +void InstanceEditDialog::on_removeLibraryBtn_clicked() { if (ui->libraryTreeView->currentIndex().isValid()) { @@ -148,7 +214,7 @@ void OneSixModEditDialog::on_removeLibraryBtn_clicked() } } -void OneSixModEditDialog::on_resetLibraryOrderBtn_clicked() +void InstanceEditDialog::on_resetLibraryOrderBtn_clicked() { try { @@ -160,7 +226,7 @@ void OneSixModEditDialog::on_resetLibraryOrderBtn_clicked() } } -void OneSixModEditDialog::on_moveLibraryUpBtn_clicked() +void InstanceEditDialog::on_moveLibraryUpBtn_clicked() { if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) { @@ -178,7 +244,7 @@ void OneSixModEditDialog::on_moveLibraryUpBtn_clicked() } } -void OneSixModEditDialog::on_moveLibraryDownBtn_clicked() +void InstanceEditDialog::on_moveLibraryDownBtn_clicked() { if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty()) { @@ -196,7 +262,106 @@ void OneSixModEditDialog::on_moveLibraryDownBtn_clicked() } } -void OneSixModEditDialog::on_forgeBtn_clicked() +// FIXME: use this for legacy forge... or abstract away. +/* +void LegacyModEditDialog::on_addForgeBtn_clicked() +{ + VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); + vselect.setFilter(1, m_inst->intendedVersionId()); + if (vselect.exec() && vselect.selectedVersion()) + { + ForgeVersionPtr forge = + std::dynamic_pointer_cast(vselect.selectedVersion()); + if (!forge) + return; + auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename); + if (entry->stale) + { + NetJob *fjob = new NetJob("Forge download"); + fjob->addNetAction(CacheDownload::make(forge->universal_url, entry)); + ProgressDialog dlg(this); + dlg.exec(fjob); + if (dlg.result() == QDialog::Accepted) + { + m_jarmods->stopWatching(); + m_jarmods->installMod(QFileInfo(entry->getFullPath())); + m_jarmods->startWatching(); + } + else + { + // failed to download forge :/ + } + } + else + { + m_jarmods->stopWatching(); + m_jarmods->installMod(QFileInfo(entry->getFullPath())); + m_jarmods->startWatching(); + } + } +}*/ + +void InstanceEditDialog::on_changeMCVersionBtn_clicked() +{ + VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"), this); + if (!vselect.exec() || !vselect.selectedVersion()) + return; + + if (!MMC->accounts()->anyAccountIsValid()) + { + CustomMessageBox::selectable( + this, tr("Error"), + tr("MultiMC cannot download Minecraft or update instances unless you have at least " + "one account added.\nPlease add your Mojang or Minecraft account."), + QMessageBox::Warning)->show(); + return; + } + + if (m_inst->versionIsCustom()) + { + auto result = CustomMessageBox::selectable( + this, tr("Are you sure?"), + tr("This will remove any library/version customization you did previously. " + "This includes things like Forge install and similar."), + QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Abort, + QMessageBox::Abort)->exec(); + + if (result != QMessageBox::Ok) + return; + m_version->revertToVanilla(); + reloadInstanceVersion(); + } + m_inst->setIntendedVersionId(vselect.selectedVersion()->descriptor()); + + auto updateTask = m_inst->doUpdate(); + if (!updateTask) + { + return; + } + ProgressDialog tDialog(this); + connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString))); + tDialog.exec(updateTask.get()); +} + +/* +void MainWindow::on_actionChangeInstLWJGLVersion_triggered() +{ + if (!m_selectedInstance) + return; + + LWJGLSelectDialog lselect(this); + lselect.exec(); + if (lselect.result() == QDialog::Accepted) + { + auto ptr = std::dynamic_pointer_cast(m_selectedInstance); + if(ptr) + ptr->setLWJGLVersion(lselect.selectedVersion()); + } +} +*/ + + +void InstanceEditDialog::on_forgeBtn_clicked() { // FIXME: use actual model, not reloading. Move logic to model. if (m_version->hasFtbPack()) @@ -210,7 +375,7 @@ void OneSixModEditDialog::on_forgeBtn_clicked() m_version->removeFtbPack(); reloadInstanceVersion(); } - if (m_version->isCustom()) + if (m_version->usesLegacyCustomJson()) { if (QMessageBox::question(this, tr("Revert?"), tr("This action will remove your custom.json. Continue?")) != @@ -218,7 +383,7 @@ void OneSixModEditDialog::on_forgeBtn_clicked() { return; } - m_version->revertToBase(); + m_version->revertToVanilla(); reloadInstanceVersion(); } VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); @@ -232,7 +397,7 @@ void OneSixModEditDialog::on_forgeBtn_clicked() } } -void OneSixModEditDialog::on_liteloaderBtn_clicked() +void InstanceEditDialog::on_liteloaderBtn_clicked() { if (m_version->hasFtbPack()) { @@ -245,7 +410,7 @@ void OneSixModEditDialog::on_liteloaderBtn_clicked() m_version->removeFtbPack(); reloadInstanceVersion(); } - if (m_version->isCustom()) + if (m_version->usesLegacyCustomJson()) { if (QMessageBox::question(this, tr("Revert?"), tr("This action will remove your custom.json. Continue?")) != @@ -253,7 +418,7 @@ void OneSixModEditDialog::on_liteloaderBtn_clicked() { return; } - m_version->revertToBase(); + m_version->revertToVanilla(); reloadInstanceVersion(); } VersionSelectDialog vselect(MMC->liteloaderlist().get(), tr("Select LiteLoader version"), @@ -268,7 +433,7 @@ void OneSixModEditDialog::on_liteloaderBtn_clicked() } } -bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent) +bool InstanceEditDialog::loaderListFilter(QKeyEvent *keyEvent) { switch (keyEvent->key()) { @@ -284,7 +449,23 @@ bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent) return QDialog::eventFilter(ui->loaderModTreeView, keyEvent); } -bool OneSixModEditDialog::resourcePackListFilter(QKeyEvent *keyEvent) +bool InstanceEditDialog::coreListFilter(QKeyEvent *keyEvent) +{ + switch (keyEvent->key()) + { + case Qt::Key_Delete: + on_rmCoreBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addCoreBtn_clicked(); + return true; + default: + break; + } + return QDialog::eventFilter(ui->coreModsTreeView, keyEvent); +} + +bool InstanceEditDialog::resourcePackListFilter(QKeyEvent *keyEvent) { switch (keyEvent->key()) { @@ -300,7 +481,7 @@ bool OneSixModEditDialog::resourcePackListFilter(QKeyEvent *keyEvent) return QDialog::eventFilter(ui->resPackTreeView, keyEvent); } -bool OneSixModEditDialog::eventFilter(QObject *obj, QEvent *ev) +bool InstanceEditDialog::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() != QEvent::KeyPress) { @@ -309,20 +490,22 @@ bool OneSixModEditDialog::eventFilter(QObject *obj, QEvent *ev) QKeyEvent *keyEvent = static_cast(ev); if (obj == ui->loaderModTreeView) return loaderListFilter(keyEvent); + if (obj == ui->coreModsTreeView) + return coreListFilter(keyEvent); if (obj == ui->resPackTreeView) return resourcePackListFilter(keyEvent); return QDialog::eventFilter(obj, ev); } -void OneSixModEditDialog::on_buttonBox_rejected() +void InstanceEditDialog::on_buttonBox_rejected() { close(); } -void OneSixModEditDialog::on_addModBtn_clicked() +void InstanceEditDialog::on_addModBtn_clicked() { QStringList fileNames = QFileDialog::getOpenFileNames( - this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods")); + this, QApplication::translate("InstanceEditDialog", "Select Loader Mods")); for (auto filename : fileNames) { m_mods->stopWatching(); @@ -330,7 +513,7 @@ void OneSixModEditDialog::on_addModBtn_clicked() m_mods->startWatching(); } } -void OneSixModEditDialog::on_rmModBtn_clicked() +void InstanceEditDialog::on_rmModBtn_clicked() { int first, last; auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); @@ -341,15 +524,44 @@ void OneSixModEditDialog::on_rmModBtn_clicked() m_mods->deleteMods(first, last); m_mods->startWatching(); } -void OneSixModEditDialog::on_viewModBtn_clicked() +void InstanceEditDialog::on_viewModBtn_clicked() { openDirInDefaultProgram(m_inst->loaderModsDir(), true); } -void OneSixModEditDialog::on_addResPackBtn_clicked() +void InstanceEditDialog::on_addCoreBtn_clicked() +{ + //: Title of core mod selection dialog + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Core Mods")); + for (auto filename : fileNames) + { + m_coremods->stopWatching(); + m_coremods->installMod(QFileInfo(filename)); + m_coremods->startWatching(); + } +} + +void InstanceEditDialog::on_rmCoreBtn_clicked() +{ + int first, last; + auto list = ui->coreModsTreeView->selectionModel()->selectedRows(); + + if (!lastfirst(list, first, last)) + return; + m_coremods->stopWatching(); + m_coremods->deleteMods(first, last); + m_coremods->startWatching(); +} + +void InstanceEditDialog::on_viewCoreBtn_clicked() +{ + openDirInDefaultProgram(m_inst->coreModsDir(), true); +} + +void InstanceEditDialog::on_addResPackBtn_clicked() { QStringList fileNames = QFileDialog::getOpenFileNames( - this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs")); + this, QApplication::translate("InstanceEditDialog", "Select Resource Packs")); for (auto filename : fileNames) { m_resourcepacks->stopWatching(); @@ -357,7 +569,7 @@ void OneSixModEditDialog::on_addResPackBtn_clicked() m_resourcepacks->startWatching(); } } -void OneSixModEditDialog::on_rmResPackBtn_clicked() +void InstanceEditDialog::on_rmResPackBtn_clicked() { int first, last; auto list = ui->resPackTreeView->selectionModel()->selectedRows(); @@ -368,12 +580,12 @@ void OneSixModEditDialog::on_rmResPackBtn_clicked() m_resourcepacks->deleteMods(first, last); m_resourcepacks->startWatching(); } -void OneSixModEditDialog::on_viewResPackBtn_clicked() +void InstanceEditDialog::on_viewResPackBtn_clicked() { openDirInDefaultProgram(m_inst->resourcePacksDir(), true); } -void OneSixModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous) +void InstanceEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous) { if (!current.isValid()) { @@ -385,7 +597,7 @@ void OneSixModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previou ui->frame->updateWithMod(m); } -void OneSixModEditDialog::versionCurrent(const QModelIndex ¤t, +void InstanceEditDialog::versionCurrent(const QModelIndex ¤t, const QModelIndex &previous) { if (!current.isValid()) @@ -397,3 +609,15 @@ void OneSixModEditDialog::versionCurrent(const QModelIndex ¤t, ui->removeLibraryBtn->setEnabled(m_version->canRemove(current.row())); } } + +void InstanceEditDialog::coreCurrent(QModelIndex current, QModelIndex previous) +{ + if (!current.isValid()) + { + ui->coreMIFrame->clear(); + return; + } + int row = current.row(); + Mod &m = m_coremods->operator[](row); + ui->coreMIFrame->updateWithMod(m); +} diff --git a/gui/dialogs/OneSixModEditDialog.h b/gui/dialogs/InstanceEditDialog.h similarity index 73% rename from gui/dialogs/OneSixModEditDialog.h rename to gui/dialogs/InstanceEditDialog.h index e106c6fe..ea2c6496 100644 --- a/gui/dialogs/OneSixModEditDialog.h +++ b/gui/dialogs/InstanceEditDialog.h @@ -17,59 +17,81 @@ #include #include +#include class EnabledItemFilter; namespace Ui { -class OneSixModEditDialog; +class InstanceEditDialog; } -class OneSixModEditDialog : public QDialog +class InstanceEditDialog : public QDialog { Q_OBJECT public: - explicit OneSixModEditDialog(OneSixInstance *inst, QWidget *parent = 0); - virtual ~OneSixModEditDialog(); + explicit InstanceEditDialog(OneSixInstance *inst, QWidget *parent = 0); + virtual ~InstanceEditDialog(); private slots: - void on_addModBtn_clicked(); - void on_rmModBtn_clicked(); - void on_viewModBtn_clicked(); - void on_addResPackBtn_clicked(); - void on_rmResPackBtn_clicked(); - void on_viewResPackBtn_clicked(); - // Questionable: SettingsDialog doesn't need this for some reason? - void on_buttonBox_rejected(); + // version tab void on_forgeBtn_clicked(); void on_liteloaderBtn_clicked(); void on_reloadLibrariesBtn_clicked(); void on_removeLibraryBtn_clicked(); void on_resetLibraryOrderBtn_clicked(); + void on_settingsBtn_clicked(); void on_moveLibraryUpBtn_clicked(); void on_moveLibraryDownBtn_clicked(); + + // loader mod tab + void on_addModBtn_clicked(); + void on_rmModBtn_clicked(); + void on_viewModBtn_clicked(); + + // core mod tab + void on_addCoreBtn_clicked(); + void on_rmCoreBtn_clicked(); + void on_viewCoreBtn_clicked(); + + // resource pack tab + void on_addResPackBtn_clicked(); + void on_rmResPackBtn_clicked(); + void on_viewResPackBtn_clicked(); + + + // Questionable: SettingsDialog doesn't need this for some reason? + void on_buttonBox_rejected(); + void updateVersionControls(); void disableVersionControls(); - + void on_changeMCVersionBtn_clicked(); + protected: bool eventFilter(QObject *obj, QEvent *ev); + bool jarListFilter(QKeyEvent *ev); bool loaderListFilter(QKeyEvent *ev); + bool coreListFilter(QKeyEvent *ev); bool resourcePackListFilter(QKeyEvent *ev); /// FIXME: this shouldn't be necessary! bool reloadInstanceVersion(); private: - Ui::OneSixModEditDialog *ui; + Ui::InstanceEditDialog *ui; std::shared_ptr m_version; std::shared_ptr m_mods; + std::shared_ptr m_coremods; + std::shared_ptr m_jarmods; std::shared_ptr m_resourcepacks; EnabledItemFilter *main_model; OneSixInstance *m_inst; + NetJobPtr forgeJob; public slots: void loaderCurrent(QModelIndex current, QModelIndex previous); void versionCurrent(const QModelIndex ¤t, const QModelIndex &previous); + void coreCurrent(QModelIndex current, QModelIndex previous); }; diff --git a/gui/dialogs/OneSixModEditDialog.ui b/gui/dialogs/InstanceEditDialog.ui similarity index 74% rename from gui/dialogs/OneSixModEditDialog.ui rename to gui/dialogs/InstanceEditDialog.ui index 2c9f70bb..0ad79833 100644 --- a/gui/dialogs/OneSixModEditDialog.ui +++ b/gui/dialogs/InstanceEditDialog.ui @@ -1,19 +1,29 @@ - OneSixModEditDialog - + InstanceEditDialog + 0 0 - 555 - 463 + 593 + 568 - Manage Mods + Edit Instance + + + + false + + + QDialogButtonBox::Close + + + @@ -52,6 +62,13 @@ + + + + Change version + + + @@ -69,6 +86,13 @@ + + + + Add jar mod + + + @@ -127,6 +151,20 @@ + + + + Qt::Horizontal + + + + + + + Settings + + + @@ -144,6 +182,72 @@ + + + Core Mods + + + + + + + + QAbstractItemView::DropOnly + + + + + + + + + &Add + + + + + + + &Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + &View Folder + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + Loader Mods @@ -280,16 +384,6 @@ - - - - false - - - QDialogButtonBox::Close - - - diff --git a/gui/dialogs/LegacyModEditDialog.cpp b/gui/dialogs/LegacyModEditDialog.cpp deleted file mode 100644 index e5039c02..00000000 --- a/gui/dialogs/LegacyModEditDialog.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* Copyright 2013 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 "MultiMC.h" -#include "LegacyModEditDialog.h" -#include "ModEditDialogCommon.h" -#include "VersionSelectDialog.h" -#include "ProgressDialog.h" -#include "ui_LegacyModEditDialog.h" -#include "logic/ModList.h" -#include "logic/lists/ForgeVersionList.h" -#include "gui/Platform.h" - -#include -#include -//#include -#include -#include -#include - -LegacyModEditDialog::LegacyModEditDialog(LegacyInstance *inst, QWidget *parent) - : QDialog(parent), ui(new Ui::LegacyModEditDialog), m_inst(inst) -{ - MultiMCPlatform::fixWM_CLASS(this); - ui->setupUi(this); - - // Jar mods - { - ensureFolderPathExists(m_inst->jarModsDir()); - m_jarmods = m_inst->jarModList(); - ui->jarModsTreeView->setModel(m_jarmods.get()); -#ifndef Q_OS_LINUX - // FIXME: internal DnD causes segfaults later - ui->jarModsTreeView->setDragDropMode(QAbstractItemView::DragDrop); - // FIXME: DnD is glitched with contiguous (we move only first item in selection) - ui->jarModsTreeView->setSelectionMode(QAbstractItemView::SingleSelection); -#endif - ui->jarModsTreeView->installEventFilter(this); - m_jarmods->startWatching(); - auto smodel = ui->jarModsTreeView->selectionModel(); - connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - SLOT(jarCurrent(QModelIndex, QModelIndex))); - } - // Core mods - { - ensureFolderPathExists(m_inst->coreModsDir()); - m_coremods = m_inst->coreModList(); - ui->coreModsTreeView->setModel(m_coremods.get()); - ui->coreModsTreeView->installEventFilter(this); - m_coremods->startWatching(); - auto smodel = ui->coreModsTreeView->selectionModel(); - connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - SLOT(coreCurrent(QModelIndex, QModelIndex))); - } - // Loader mods - { - ensureFolderPathExists(m_inst->loaderModsDir()); - m_mods = m_inst->loaderModList(); - ui->loaderModTreeView->setModel(m_mods.get()); - ui->loaderModTreeView->installEventFilter(this); - m_mods->startWatching(); - auto smodel = ui->loaderModTreeView->selectionModel(); - connect(smodel, SIGNAL(currentChanged(QModelIndex, QModelIndex)), - SLOT(loaderCurrent(QModelIndex, QModelIndex))); - } - // texture packs - { - ensureFolderPathExists(m_inst->texturePacksDir()); - m_texturepacks = m_inst->texturePackList(); - ui->texPackTreeView->setModel(m_texturepacks.get()); - ui->texPackTreeView->installEventFilter(this); - m_texturepacks->startWatching(); - } -} - -LegacyModEditDialog::~LegacyModEditDialog() -{ - m_mods->stopWatching(); - m_coremods->stopWatching(); - m_jarmods->stopWatching(); - m_texturepacks->stopWatching(); - delete ui; -} - -bool LegacyModEditDialog::coreListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_rmCoreBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addCoreBtn_clicked(); - return true; - default: - break; - } - return QDialog::eventFilter(ui->coreModsTreeView, keyEvent); -} - -bool LegacyModEditDialog::jarListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Up: - { - if (keyEvent->modifiers() & Qt::ControlModifier) - { - on_moveJarUpBtn_clicked(); - return true; - } - break; - } - case Qt::Key_Down: - { - if (keyEvent->modifiers() & Qt::ControlModifier) - { - on_moveJarDownBtn_clicked(); - return true; - } - break; - } - case Qt::Key_Delete: - on_rmJarBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addJarBtn_clicked(); - return true; - default: - break; - } - return QDialog::eventFilter(ui->jarModsTreeView, keyEvent); -} - -bool LegacyModEditDialog::loaderListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_rmModBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addModBtn_clicked(); - return true; - default: - break; - } - return QDialog::eventFilter(ui->loaderModTreeView, keyEvent); -} - -bool LegacyModEditDialog::texturePackListFilter(QKeyEvent *keyEvent) -{ - switch (keyEvent->key()) - { - case Qt::Key_Delete: - on_rmTexPackBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addTexPackBtn_clicked(); - return true; - default: - break; - } - return QDialog::eventFilter(ui->texPackTreeView, keyEvent); -} - -bool LegacyModEditDialog::eventFilter(QObject *obj, QEvent *ev) -{ - if (ev->type() != QEvent::KeyPress) - { - return QDialog::eventFilter(obj, ev); - } - QKeyEvent *keyEvent = static_cast(ev); - if (obj == ui->jarModsTreeView) - return jarListFilter(keyEvent); - if (obj == ui->coreModsTreeView) - return coreListFilter(keyEvent); - if (obj == ui->loaderModTreeView) - return loaderListFilter(keyEvent); - if (obj == ui->texPackTreeView) - return texturePackListFilter(keyEvent); - return QDialog::eventFilter(obj, ev); -} - -void LegacyModEditDialog::on_addCoreBtn_clicked() -{ - //: Title of core mod selection dialog - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Core Mods")); - for (auto filename : fileNames) - { - m_coremods->stopWatching(); - m_coremods->installMod(QFileInfo(filename)); - m_coremods->startWatching(); - } -} -void LegacyModEditDialog::on_addForgeBtn_clicked() -{ - VersionSelectDialog vselect(MMC->forgelist().get(), tr("Select Forge version"), this); - vselect.setExactFilter(1, m_inst->intendedVersionId()); - if (vselect.exec() && vselect.selectedVersion()) - { - ForgeVersionPtr forge = - std::dynamic_pointer_cast(vselect.selectedVersion()); - if (!forge) - return; - auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename); - if (entry->stale) - { - NetJob *fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(forge->universal_url, entry)); - ProgressDialog dlg(this); - dlg.exec(fjob); - if (dlg.result() == QDialog::Accepted) - { - m_jarmods->stopWatching(); - m_jarmods->installMod(QFileInfo(entry->getFullPath())); - m_jarmods->startWatching(); - } - else - { - // failed to download forge :/ - } - } - else - { - m_jarmods->stopWatching(); - m_jarmods->installMod(QFileInfo(entry->getFullPath())); - m_jarmods->startWatching(); - } - } -} -void LegacyModEditDialog::on_addJarBtn_clicked() -{ - //: Title of jar mod selection dialog - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Jar Mods")); - for (auto filename : fileNames) - { - m_jarmods->stopWatching(); - m_jarmods->installMod(QFileInfo(filename)); - m_jarmods->startWatching(); - } -} -void LegacyModEditDialog::on_addModBtn_clicked() -{ - //: Title of regular mod selection dialog - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Loader Mods")); - for (auto filename : fileNames) - { - m_mods->stopWatching(); - m_mods->installMod(QFileInfo(filename)); - m_mods->startWatching(); - } -} -void LegacyModEditDialog::on_addTexPackBtn_clicked() -{ - //: Title of texture pack selection dialog - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Texture Packs")); - for (auto filename : fileNames) - { - m_texturepacks->stopWatching(); - m_texturepacks->installMod(QFileInfo(filename)); - m_texturepacks->startWatching(); - } -} - -void LegacyModEditDialog::on_moveJarDownBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - - m_jarmods->moveModsDown(first, last); -} -void LegacyModEditDialog::on_moveJarUpBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_jarmods->moveModsUp(first, last); -} -void LegacyModEditDialog::on_rmCoreBtn_clicked() -{ - int first, last; - auto list = ui->coreModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_coremods->stopWatching(); - m_coremods->deleteMods(first, last); - m_coremods->startWatching(); -} -void LegacyModEditDialog::on_rmJarBtn_clicked() -{ - int first, last; - auto list = ui->jarModsTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_jarmods->stopWatching(); - m_jarmods->deleteMods(first, last); - m_jarmods->startWatching(); -} -void LegacyModEditDialog::on_rmModBtn_clicked() -{ - int first, last; - auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_mods->stopWatching(); - m_mods->deleteMods(first, last); - m_mods->startWatching(); -} -void LegacyModEditDialog::on_rmTexPackBtn_clicked() -{ - int first, last; - auto list = ui->texPackTreeView->selectionModel()->selectedRows(); - - if (!lastfirst(list, first, last)) - return; - m_texturepacks->stopWatching(); - m_texturepacks->deleteMods(first, last); - m_texturepacks->startWatching(); -} -void LegacyModEditDialog::on_viewCoreBtn_clicked() -{ - openDirInDefaultProgram(m_inst->coreModsDir(), true); -} -void LegacyModEditDialog::on_viewModBtn_clicked() -{ - openDirInDefaultProgram(m_inst->loaderModsDir(), true); -} -void LegacyModEditDialog::on_viewTexPackBtn_clicked() -{ - openDirInDefaultProgram(m_inst->texturePacksDir(), true); -} - -void LegacyModEditDialog::on_buttonBox_rejected() -{ - close(); -} - -void LegacyModEditDialog::jarCurrent(QModelIndex current, QModelIndex previous) -{ - if (!current.isValid()) - { - ui->jarMIFrame->clear(); - return; - } - int row = current.row(); - Mod &m = m_jarmods->operator[](row); - ui->jarMIFrame->updateWithMod(m); -} - -void LegacyModEditDialog::coreCurrent(QModelIndex current, QModelIndex previous) -{ - if (!current.isValid()) - { - ui->coreMIFrame->clear(); - return; - } - int row = current.row(); - Mod &m = m_coremods->operator[](row); - ui->coreMIFrame->updateWithMod(m); -} - -void LegacyModEditDialog::loaderCurrent(QModelIndex current, QModelIndex previous) -{ - if (!current.isValid()) - { - ui->loaderMIFrame->clear(); - return; - } - int row = current.row(); - Mod &m = m_mods->operator[](row); - ui->loaderMIFrame->updateWithMod(m); -} diff --git a/gui/dialogs/LegacyModEditDialog.h b/gui/dialogs/LegacyModEditDialog.h deleted file mode 100644 index d5582aef..00000000 --- a/gui/dialogs/LegacyModEditDialog.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright 2013 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. - */ - -#pragma once - -#include -#include "logic/LegacyInstance.h" -#include - -namespace Ui -{ -class LegacyModEditDialog; -} - -class LegacyModEditDialog : public QDialog -{ - Q_OBJECT - -public: - explicit LegacyModEditDialog(LegacyInstance *inst, QWidget *parent = 0); - ~LegacyModEditDialog(); - -private -slots: - - void on_addJarBtn_clicked(); - void on_rmJarBtn_clicked(); - void on_addForgeBtn_clicked(); - void on_moveJarUpBtn_clicked(); - void on_moveJarDownBtn_clicked(); - - void on_addCoreBtn_clicked(); - void on_rmCoreBtn_clicked(); - void on_viewCoreBtn_clicked(); - - void on_addModBtn_clicked(); - void on_rmModBtn_clicked(); - void on_viewModBtn_clicked(); - - void on_addTexPackBtn_clicked(); - void on_rmTexPackBtn_clicked(); - void on_viewTexPackBtn_clicked(); - - // Questionable: SettingsDialog doesn't need this for some reason? - void on_buttonBox_rejected(); - - void jarCurrent(QModelIndex current, QModelIndex previous); - void coreCurrent(QModelIndex current, QModelIndex previous); - void loaderCurrent(QModelIndex current, QModelIndex previous); - -protected: - bool eventFilter(QObject *obj, QEvent *ev); - bool jarListFilter(QKeyEvent *ev); - bool coreListFilter(QKeyEvent *ev); - bool loaderListFilter(QKeyEvent *ev); - bool texturePackListFilter(QKeyEvent *ev); - -private: - Ui::LegacyModEditDialog *ui; - std::shared_ptr m_mods; - std::shared_ptr m_coremods; - std::shared_ptr m_jarmods; - std::shared_ptr m_texturepacks; - LegacyInstance *m_inst; - NetJobPtr forgeJob; -}; diff --git a/gui/dialogs/LegacyModEditDialog.ui b/gui/dialogs/LegacyModEditDialog.ui deleted file mode 100644 index 0662c712..00000000 --- a/gui/dialogs/LegacyModEditDialog.ui +++ /dev/null @@ -1,321 +0,0 @@ - - - LegacyModEditDialog - - - - 0 - 0 - 540 - 420 - - - - Edit Mods - - - - - - 0 - - - - Jar Mods - - - - - - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - - - - - - - &Add - - - - - - - &Remove - - - - - - - MCForge - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Move &Up - - - - - - - Move &Down - - - - - - - - - - - QFrame::Plain - - - - - - - - Core Mods - - - - - - - - QAbstractItemView::DropOnly - - - - - - - - - &Add - - - - - - - &Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - &View Folder - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Loader Mods - - - - - - - - true - - - QAbstractItemView::DropOnly - - - - - - - - - &Add - - - - - - - &Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - &View Folder - - - - - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - false - - - Texture Packs - - - - - - true - - - QAbstractItemView::DropOnly - - - - - - - - - &Add - - - - - - - &Remove - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - &View Folder - - - - - - - - - - - - - QDialogButtonBox::Close - - - - - - - - ModListView - QTreeView -
gui/widgets/ModListView.h
-
- - MCModInfoFrame - QFrame -
gui/widgets/MCModInfoFrame.h
- 1 -
-
- - -
diff --git a/gui/dialogs/ModEditDialogCommon.cpp b/gui/dialogs/ModEditDialogCommon.cpp deleted file mode 100644 index eee42e5e..00000000 --- a/gui/dialogs/ModEditDialogCommon.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2013 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 "ModEditDialogCommon.h" -#include "CustomMessageBox.h" -#include -#include -#include -#include -bool lastfirst(QModelIndexList &list, int &first, int &last) -{ - if (!list.size()) - return false; - first = last = list[0].row(); - for (auto item : list) - { - int row = item.row(); - if (row < first) - first = row; - if (row > last) - last = row; - } - return true; -} - -void showWebsiteForMod(QWidget *parentDlg, Mod &m) -{ - QString url = m.homeurl(); - if (url.size()) - { - // catch the cases where the protocol is missing - if (!url.startsWith("http")) - { - url = "http://" + url; - } - QDesktopServices::openUrl(url); - } - else - { - CustomMessageBox::selectable( - parentDlg, QObject::tr("How sad!"), - QObject::tr("The mod author didn't provide a website link for this mod."), - QMessageBox::Warning); - } -} diff --git a/gui/dialogs/ModEditDialogCommon.h b/gui/dialogs/ModEditDialogCommon.h deleted file mode 100644 index a226d5a9..00000000 --- a/gui/dialogs/ModEditDialogCommon.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 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. - */ - -#pragma once -#include -#include - -bool lastfirst(QModelIndexList &list, int &first, int &last); - -void showWebsiteForMod(QWidget *parentDlg, Mod &m); \ No newline at end of file diff --git a/logic/BaseInstaller.h b/logic/BaseInstaller.h index d59833cc..9531fbff 100644 --- a/logic/BaseInstaller.h +++ b/logic/BaseInstaller.h @@ -29,7 +29,7 @@ class BaseInstaller { public: BaseInstaller(); - + virtual ~BaseInstaller(){}; bool isApplied(OneSixInstance *on); virtual bool add(OneSixInstance *to); diff --git a/logic/BaseVersion.h b/logic/BaseVersion.h index 43f5942a..ed63f551 100644 --- a/logic/BaseVersion.h +++ b/logic/BaseVersion.h @@ -16,6 +16,8 @@ #pragma once #include +#include +#include /*! * An abstract base class for versions. @@ -52,4 +54,4 @@ struct BaseVersion typedef std::shared_ptr BaseVersionPtr; -Q_DECLARE_METATYPE(BaseVersionPtr) \ No newline at end of file +Q_DECLARE_METATYPE(BaseVersionPtr) diff --git a/logic/InstanceFactory.cpp b/logic/InstanceFactory.cpp index 95fd855b..955a3f5b 100644 --- a/logic/InstanceFactory.cpp +++ b/logic/InstanceFactory.cpp @@ -23,7 +23,6 @@ #include "LegacyFTBInstance.h" #include "OneSixInstance.h" #include "OneSixFTBInstance.h" -#include "NostalgiaInstance.h" #include "OneSixInstance.h" #include "BaseVersion.h" #include "MinecraftVersion.h" @@ -51,7 +50,7 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(InstancePtr &inst, QString inst_type = m_settings->get("InstanceType").toString(); // FIXME: replace with a map lookup, where instance classes register their types - if (inst_type == "OneSix") + if (inst_type == "OneSix" || inst_type == "Nostalgia") { inst.reset(new OneSixInstance(instDir, m_settings, this)); } @@ -59,10 +58,6 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(InstancePtr &inst, { inst.reset(new LegacyInstance(instDir, m_settings, this)); } - else if (inst_type == "Nostalgia") - { - inst.reset(new NostalgiaInstance(instDir, m_settings, this)); - } else if (inst_type == "LegacyFTB") { inst.reset(new LegacyFTBInstance(instDir, m_settings, this)); @@ -98,55 +93,26 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(InstancePtr &in if (type == NormalInst) { - switch (mcVer->type) - { - case MinecraftVersion::Legacy: - // TODO new instance type - m_settings->set("InstanceType", "Legacy"); - inst.reset(new LegacyInstance(instDir, m_settings, this)); - inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); - break; - case MinecraftVersion::OneSix: - m_settings->set("InstanceType", "OneSix"); - inst.reset(new OneSixInstance(instDir, m_settings, this)); - inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); - break; - case MinecraftVersion::Nostalgia: - m_settings->set("InstanceType", "Nostalgia"); - inst.reset(new NostalgiaInstance(instDir, m_settings, this)); - inst->setIntendedVersionId(version->descriptor()); - inst->setShouldUseCustomBaseJar(false); - break; - default: - { - delete m_settings; - return InstanceFactory::NoSuchVersion; - } - } + m_settings->set("InstanceType", "OneSix"); + inst.reset(new OneSixInstance(instDir, m_settings, this)); + inst->setIntendedVersionId(version->descriptor()); + inst->setShouldUseCustomBaseJar(false); } else if (type == FTBInstance) { - switch (mcVer->type) + if(mcVer->usesLegacyLauncher()) { - case MinecraftVersion::Legacy: m_settings->set("InstanceType", "LegacyFTB"); inst.reset(new LegacyFTBInstance(instDir, m_settings, this)); inst->setIntendedVersionId(version->descriptor()); inst->setShouldUseCustomBaseJar(false); - break; - case MinecraftVersion::OneSix: + } + else + { m_settings->set("InstanceType", "OneSixFTB"); inst.reset(new OneSixFTBInstance(instDir, m_settings, this)); inst->setIntendedVersionId(version->descriptor()); inst->setShouldUseCustomBaseJar(false); - break; - default: - { - delete m_settings; - return InstanceFactory::NoSuchVersion; - } } } else diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 6648e059..bc4d2cfc 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -29,8 +29,6 @@ #include "logic/LegacyUpdate.h" #include "logic/icons/IconList.h" -#include "gui/dialogs/LegacyModEditDialog.h" - LegacyInstance::LegacyInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) : BaseInstance(new LegacyInstancePrivate(), rootDir, settings, parent) @@ -138,7 +136,7 @@ std::shared_ptr LegacyInstance::texturePackList() QDialog *LegacyInstance::createModEditDialog(QWidget *parent) { - return new LegacyModEditDialog(this, parent); + return nullptr; } QString LegacyInstance::jarModsDir() const @@ -280,10 +278,7 @@ QString LegacyInstance::getStatusbarDescription() { if (flags().contains(VersionBrokenFlag)) { - return "Legacy : " + intendedVersionId() + " (broken)"; + return tr("Legacy : %1 (broken)").arg(intendedVersionId()); } - if (shouldUpdate()) - return "Legacy : " + currentVersionId() + " -> " + intendedVersionId(); - else - return "Legacy : " + currentVersionId(); + return tr("Legacy : %1").arg(intendedVersionId()); } diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 15c99234..6816df40 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -30,52 +30,6 @@ LegacyUpdate::LegacyUpdate(BaseInstance *inst, QObject *parent) : Task(parent), m_inst(inst) { - // 1.3 - 1.3.2 - auto libs13 = QList{ - {"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false}, - {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false}, - {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}}; - - fmlLibsMapping["1.3.2"] = libs13; - - auto libs14 = QList{ - {"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false}, - {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false}, - {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}, - {"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb", false}}; - - fmlLibsMapping["1.4"] = libs14; - fmlLibsMapping["1.4.1"] = libs14; - fmlLibsMapping["1.4.2"] = libs14; - fmlLibsMapping["1.4.3"] = libs14; - fmlLibsMapping["1.4.4"] = libs14; - fmlLibsMapping["1.4.5"] = libs14; - fmlLibsMapping["1.4.6"] = libs14; - fmlLibsMapping["1.4.7"] = libs14; - - fmlLibsMapping["1.5"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, - {"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8", false}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; - - fmlLibsMapping["1.5.1"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, - {"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6", false}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; - - fmlLibsMapping["1.5.2"] = QList{ - {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, - {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, - {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, - {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, - {"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9", false}, - {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; } void LegacyUpdate::executeTask() @@ -110,6 +64,7 @@ void LegacyUpdate::fmllibsStart() bool forge_present = false; QString version = inst->intendedVersionId(); + auto & fmlLibsMapping = g_forgeData.fmlLibsMapping; if (!fmlLibsMapping.contains(version)) { lwjglStart(); @@ -152,7 +107,7 @@ void LegacyUpdate::fmllibsStart() // now check the lib folder inside the instance for files. for (auto &lib : libList) { - QFileInfo libInfo(PathCombine(inst->libDir(), lib.name)); + QFileInfo libInfo(PathCombine(inst->libDir(), lib.filename)); if (libInfo.exists()) continue; fmlLibsToProcess.append(lib); @@ -171,9 +126,9 @@ void LegacyUpdate::fmllibsStart() auto metacache = MMC->metacache(); for (auto &lib : fmlLibsToProcess) { - auto entry = metacache->resolveEntry("fmllibs", lib.name); - QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.name - : URLConstants::FMLLIBS_FORGE_BASE_URL + lib.name; + auto entry = metacache->resolveEntry("fmllibs", lib.filename); + QString urlString = lib.ours ? URLConstants::FMLLIBS_OUR_BASE_URL + lib.filename + : URLConstants::FMLLIBS_FORGE_BASE_URL + lib.filename; dljob->addNetAction(CacheDownload::make(QUrl(urlString), entry)); } @@ -196,16 +151,16 @@ void LegacyUpdate::fmllibsFinished() for (auto &lib : fmlLibsToProcess) { progress(index, fmlLibsToProcess.size()); - auto entry = metacache->resolveEntry("fmllibs", lib.name); - auto path = PathCombine(inst->libDir(), lib.name); + auto entry = metacache->resolveEntry("fmllibs", lib.filename); + auto path = PathCombine(inst->libDir(), lib.filename); if(!ensureFilePathExists(path)) { emitFailed(tr("Failed creating FML library folder inside the instance.")); return; } - if (!QFile::copy(entry->getFullPath(), PathCombine(inst->libDir(), lib.name))) + if (!QFile::copy(entry->getFullPath(), PathCombine(inst->libDir(), lib.filename))) { - emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.name)); + emitFailed(tr("Failed copying Forge/FML library: %1.").arg(lib.filename)); return; } index++; @@ -265,8 +220,6 @@ void LegacyUpdate::lwjglStart() connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SIGNAL(progress(qint64, qint64))); connect(worker.get(), SIGNAL(finished(QNetworkReply *)), SLOT(lwjglFinished(QNetworkReply *))); - // connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), - // SLOT(downloadError(QNetworkReply::NetworkError))); } void LegacyUpdate::lwjglFinished(QNetworkReply *reply) diff --git a/logic/LegacyUpdate.h b/logic/LegacyUpdate.h index 5b073cb7..1550ec34 100644 --- a/logic/LegacyUpdate.h +++ b/logic/LegacyUpdate.h @@ -21,19 +21,13 @@ #include "logic/net/NetJob.h" #include "logic/tasks/Task.h" +#include "logic/forge/ForgeData.h" class MinecraftVersion; class BaseInstance; class QuaZip; class Mod; -struct FMLlib -{ - QString name; - QString checksum; - bool ours; -}; - class LegacyUpdate : public Task { Q_OBJECT @@ -84,5 +78,4 @@ private: NetJobPtr legacyDownloadJob; BaseInstance *m_inst = nullptr; QList fmlLibsToProcess; - QMap> fmlLibsMapping; }; diff --git a/logic/MinecraftVersion.h b/logic/MinecraftVersion.h index 504381a8..6cbfebbe 100644 --- a/logic/MinecraftVersion.h +++ b/logic/MinecraftVersion.h @@ -17,6 +17,7 @@ #include "BaseVersion.h" #include +#include struct MinecraftVersion : public BaseVersion { @@ -29,13 +30,8 @@ struct MinecraftVersion : public BaseVersion /// The URL that this version will be downloaded from. maybe. QString download_url; - /// This version's type. Used internally to identify what kind of version this is. - enum VersionType - { - OneSix, - Legacy, - Nostalgia - } type; + /// extra features enabled for this Minecraft version. Mostly for compatibility + QSet features; /// is this the latest version? bool is_latest = false; @@ -47,6 +43,11 @@ struct MinecraftVersion : public BaseVersion QString m_descriptor; + bool usesLegacyLauncher() + { + return features.contains("legacy"); + } + virtual QString descriptor() { return m_descriptor; @@ -59,31 +60,21 @@ struct MinecraftVersion : public BaseVersion virtual QString typeString() const { - QStringList pre_final; - if (is_latest == true) + if (is_latest && is_snapshot) { - pre_final.append("Latest"); + return QObject::tr("Latest snapshot"); } - switch (type) + else if(is_latest) { - case OneSix: - pre_final.append("OneSix"); - break; - case Legacy: - pre_final.append("Legacy"); - break; - case Nostalgia: - pre_final.append("Nostalgia"); - break; - - default: - pre_final.append(QString("Type(%1)").arg(type)); - break; + return QObject::tr("Latest release"); } - if (is_snapshot == true) + else if(is_snapshot) { - pre_final.append("Snapshot"); + return QObject::tr("Old snapshot"); + } + else + { + return QObject::tr("Regular release"); } - return pre_final.join(' '); } }; diff --git a/logic/NostalgiaInstance.cpp b/logic/NostalgiaInstance.cpp deleted file mode 100644 index 52820725..00000000 --- a/logic/NostalgiaInstance.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2013 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 "NostalgiaInstance.h" - -NostalgiaInstance::NostalgiaInstance(const QString &rootDir, SettingsObject *settings, - QObject *parent) - : OneSixInstance(rootDir, settings, parent) -{ -} - -QString NostalgiaInstance::getStatusbarDescription() -{ - if (flags().contains(VersionBrokenFlag)) - { - return "Nostalgia : " + intendedVersionId() + " (broken)"; - } - return "Nostalgia : " + intendedVersionId(); -} - -bool NostalgiaInstance::menuActionEnabled(QString action_name) const -{ - return false; -} diff --git a/logic/NostalgiaInstance.h b/logic/NostalgiaInstance.h deleted file mode 100644 index f95531d2..00000000 --- a/logic/NostalgiaInstance.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2013 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. - */ - -#pragma once - -#include "OneSixInstance.h" - -class NostalgiaInstance : public OneSixInstance -{ - Q_OBJECT -public: - explicit NostalgiaInstance(const QString &rootDir, SettingsObject *settings, - QObject *parent = 0); - virtual ~NostalgiaInstance() {}; - virtual QString getStatusbarDescription(); - virtual bool menuActionEnabled(QString action_name) const; -}; diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index 172830bb..34118111 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -3,8 +3,8 @@ #include "VersionFinal.h" #include "OneSixLibrary.h" #include "tasks/SequentialTask.h" -#include "ForgeInstaller.h" -#include "lists/ForgeVersionList.h" +#include "forge/ForgeInstaller.h" +#include "forge/ForgeVersionList.h" #include "OneSixInstance_p.h" #include "OneSixVersionBuilder.h" #include "MultiMC.h" diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 6f3018cb..dc452188 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -26,7 +26,7 @@ #include "MultiMC.h" #include "icons/IconList.h" #include "MinecraftProcess.h" -#include "gui/dialogs/OneSixModEditDialog.h" +#include "gui/dialogs/InstanceEditDialog.h" #include OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, QObject *parent) @@ -36,7 +36,6 @@ OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *settings, d->m_settings->registerSetting("IntendedVersion", ""); d->m_settings->registerSetting("ShouldUpdate", false); d->version.reset(new VersionFinal(this, this)); - d->vanillaVersion.reset(new VersionFinal(this, this)); } void OneSixInstance::init() @@ -260,6 +259,17 @@ std::shared_ptr OneSixInstance::loaderModList() return d->loader_mod_list; } +std::shared_ptr OneSixInstance::coreModList() +{ + I_D(OneSixInstance); + if (!d->core_mod_list) + { + d->core_mod_list.reset(new ModList(coreModsDir())); + } + d->core_mod_list->update(); + return d->core_mod_list; +} + std::shared_ptr OneSixInstance::resourcePackList() { I_D(OneSixInstance); @@ -273,7 +283,7 @@ std::shared_ptr OneSixInstance::resourcePackList() QDialog *OneSixInstance::createModEditDialog(QWidget *parent) { - return new OneSixModEditDialog(this, parent); + return new InstanceEditDialog(this, parent); } bool OneSixInstance::setIntendedVersionId(QString version) @@ -307,10 +317,13 @@ bool OneSixInstance::shouldUpdate() const bool OneSixInstance::versionIsCustom() { - QDir patches(PathCombine(instanceRoot(), "patches/")); - return (patches.exists() && patches.count() >= 0) - || QFile::exists(PathCombine(instanceRoot(), "custom.json")) - || QFile::exists(PathCombine(instanceRoot(), "user.json")); + I_D(const OneSixInstance); + auto ver = d->version; + if(ver) + { + return !ver->isVanilla(); + } + return false; } bool OneSixInstance::versionIsFTBPack() @@ -335,15 +348,13 @@ void OneSixInstance::reloadVersion() try { - d->version->reload(false, externalPatches()); - d->vanillaVersion->reload(true, externalPatches()); + d->version->reload(externalPatches()); d->m_flags.remove(VersionBrokenFlag); emit versionReloaded(); } catch(MMCError & error) { d->version->clear(); - d->vanillaVersion->clear(); d->m_flags.insert(VersionBrokenFlag); //TODO: rethrow to show some error message(s)? emit versionReloaded(); @@ -355,7 +366,6 @@ void OneSixInstance::clearVersion() { I_D(OneSixInstance); d->version->clear(); - d->vanillaVersion->clear(); emit versionReloaded(); } @@ -365,12 +375,6 @@ std::shared_ptr OneSixInstance::getFullVersion() const return d->version; } -std::shared_ptr OneSixInstance::getVanillaVersion() const -{ - I_D(const OneSixInstance); - return d->vanillaVersion; -} - QString OneSixInstance::defaultBaseJar() const { return "versions/" + intendedVersionId() + "/" + intendedVersionId() + ".jar"; @@ -396,16 +400,24 @@ bool OneSixInstance::menuActionEnabled(QString action_name) const QString OneSixInstance::getStatusbarDescription() { - QString descr = "OneSix : " + intendedVersionId(); + QStringList traits; if (versionIsCustom()) { - descr += " (custom)"; + traits.append(tr("custom")); } if (flags().contains(VersionBrokenFlag)) { - descr += " (broken)"; + traits.append(tr("broken")); + } + + if(traits.size()) + { + return tr("Minecraft %1 (%2)").arg(intendedVersionId()).arg(traits.join(", ")); + } + else + { + return tr("Minecraft %1").arg(intendedVersionId()); } - return descr; } QDir OneSixInstance::librariesPath() const @@ -449,6 +461,11 @@ QString OneSixInstance::loaderModsDir() const return PathCombine(minecraftRoot(), "mods"); } +QString OneSixInstance::coreModsDir() const +{ + return PathCombine(minecraftRoot(), "coremods"); +} + QString OneSixInstance::resourcePacksDir() const { return PathCombine(minecraftRoot(), "resourcepacks"); @@ -458,3 +475,8 @@ QString OneSixInstance::instanceConfigFolder() const { return PathCombine(minecraftRoot(), "config"); } + +QString OneSixInstance::jarModsDir() const +{ + return PathCombine(instanceRoot(), "jarmods"); +} diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h index 13a392c2..b26ff752 100644 --- a/logic/OneSixInstance.h +++ b/logic/OneSixInstance.h @@ -32,11 +32,14 @@ public: ////// Mod Lists ////// std::shared_ptr loaderModList(); + std::shared_ptr coreModList(); std::shared_ptr resourcePackList(); - ////// Directories ////// + ////// Directories and files ////// + QString jarModsDir() const; QString resourcePacksDir() const; QString loaderModsDir() const; + QString coreModsDir() const; virtual QString instanceConfigFolder() const override; virtual std::shared_ptr doUpdate() override; @@ -60,14 +63,16 @@ public: * throws various exceptions :3 */ void reloadVersion(); + /// clears all version information in preparation for an update void clearVersion(); + /// get the current full version info std::shared_ptr getFullVersion() const; - /// gets the current version info, but only for version.json - std::shared_ptr getVanillaVersion() const; + /// is the current version original, or custom? virtual bool versionIsCustom() override; + /// does this instance have an FTB pack patch inside? bool versionIsFTBPack(); diff --git a/logic/OneSixInstance_p.h b/logic/OneSixInstance_p.h index c70de07c..e75a8da3 100644 --- a/logic/OneSixInstance_p.h +++ b/logic/OneSixInstance_p.h @@ -24,7 +24,8 @@ class OneSixInstancePrivate : public BaseInstancePrivate public: virtual ~OneSixInstancePrivate() {}; std::shared_ptr version; - std::shared_ptr vanillaVersion; + std::shared_ptr jar_mod_list; std::shared_ptr loader_mod_list; + std::shared_ptr core_mod_list; std::shared_ptr resource_pack_list; }; diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h index 61d4c8e2..1c7169ce 100644 --- a/logic/OneSixLibrary.h +++ b/logic/OneSixLibrary.h @@ -41,7 +41,7 @@ private: // custom values /// absolute URL. takes precedence over m_download_path, if defined QString m_absolute_url; - /// download hint - how to actually get the library + /// type hint - modifies how the library is treated QString m_hint; // derived values used for real things diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index d083c2ba..da2fd29c 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -28,7 +28,7 @@ #include "VersionFinal.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" -#include "net/ForgeMirrors.h" +#include "logic/forge/ForgeMirrors.h" #include "net/URLConstants.h" #include "assets/AssetsUtils.h" diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp index be3a7da4..3fb96c5e 100644 --- a/logic/OneSixVersionBuilder.cpp +++ b/logic/OneSixVersionBuilder.cpp @@ -38,13 +38,12 @@ OneSixVersionBuilder::OneSixVersionBuilder() { } -void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, - const bool onlyVanilla, const QStringList &external) +void OneSixVersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const QStringList &external) { OneSixVersionBuilder builder; builder.m_version = version; builder.m_instance = instance; - builder.buildInternal(onlyVanilla, external); + builder.buildInternal(external); } void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, @@ -56,7 +55,7 @@ void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, builder.readJsonAndApply(obj); } -void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external) +void OneSixVersionBuilder::buildInternal(const QStringList &external) { m_version->versionFiles.clear(); @@ -111,9 +110,6 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi // QObject::tr("Error while applying %1. Please check MultiMC-0.log for more // info.").arg(root.absoluteFilePath("version.json"))); - if (onlyVanilla) - break; - // patches/ // load all, put into map for ordering, apply in the right order diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h index 7a799e5b..6646584e 100644 --- a/logic/OneSixVersionBuilder.h +++ b/logic/OneSixVersionBuilder.h @@ -28,8 +28,7 @@ class OneSixVersionBuilder { OneSixVersionBuilder(); public: - static void build(VersionFinal *version, OneSixInstance *instance, const bool onlyVanilla, - const QStringList &external); + static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external); static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj); static QMap readOverrideOrders(OneSixInstance *instance); @@ -39,7 +38,7 @@ private: VersionFinal *m_version; OneSixInstance *m_instance; - void buildInternal(const bool onlyVanilla, const QStringList &external); + void buildInternal(const QStringList& external); void readJsonAndApply(const QJsonObject &obj); VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, diff --git a/logic/VersionFile.cpp b/logic/VersionFile.cpp index cd2a4f9c..4a850f97 100644 --- a/logic/VersionFile.cpp +++ b/logic/VersionFile.cpp @@ -13,6 +13,43 @@ using namespace MMCJson; #define CURRENT_MINIMUM_LAUNCHER_VERSION 14 +JarmodPtr Jarmod::fromJson(const QJsonObject &libObj, const QString &filename) +{ + JarmodPtr out(new Jarmod()); + if (!libObj.contains("name")) + { + throw JSONValidationError(filename + + "contains a jarmod that doesn't have a 'name' field"); + } + out->name = libObj.value("name").toString(); + + auto readString = [libObj, filename](const QString & key, QString & variable) + { + if (libObj.contains(key)) + { + QJsonValue val = libObj.value(key); + if (!val.isString()) + { + QLOG_WARN() << key << "is not a string in" << filename << "(skipping)"; + } + else + { + variable = val.toString(); + } + } + }; + + readString("url", out->baseurl); + readString("MMC-absoluteUrl", out->absoluteUrl); + if(!out->baseurl.isEmpty() && out->absoluteUrl.isEmpty()) + { + out->absoluteUrl = out->baseurl + out->name; + } + return out; + +} + + RawLibraryPtr RawLibrary::fromJson(const QJsonObject &libObj, const QString &filename) { RawLibraryPtr out(new RawLibrary()); @@ -165,6 +202,14 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi } } + if (root.contains("+traits")) + { + for (auto tweakerVal : ensureArray(root.value("+traits"))) + { + out->traits.insert(ensureString(tweakerVal)); + } + } + if (root.contains("libraries")) { // FIXME: This should be done when applying. @@ -188,6 +233,18 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi } } + if (root.contains("+jarMods")) + { + for (auto libVal : ensureArray(root.value("+jarMods"))) + { + QJsonObject libObj = ensureObject(libVal); + // parse the jarmod + auto lib = Jarmod::fromJson(libObj, filename); + // and add to jar mods + out->jarMods.append(lib); + } + } + if (root.contains("+libraries")) { for (auto libVal : ensureArray(root.value("+libraries"))) @@ -258,6 +315,7 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi out->addLibs.append(lib); } } + if (root.contains("-libraries")) { for (auto libVal : ensureArray(root.value("-libraries"))) @@ -309,6 +367,16 @@ int VersionFile::findLibrary(QList haystack, const QString &ne return retval; } +bool VersionFile::isVanilla() +{ + return fileId == "org.multimc.version.json"; +} + +bool VersionFile::hasJarMods() +{ + return !jarMods.isEmpty(); +} + void VersionFile::applyTo(VersionFinal *version) { if (minimumLauncherVersion != -1) @@ -338,6 +406,10 @@ void VersionFile::applyTo(VersionFinal *version) } if (!processArguments.isNull()) { + if(isVanilla()) + { + version->vanillaProcessArguments = processArguments; + } version->processArguments = processArguments; } if (!type.isNull()) @@ -362,6 +434,10 @@ void VersionFile::applyTo(VersionFinal *version) } if (!overwriteMinecraftArguments.isNull()) { + if(isVanilla()) + { + version->vanillaMinecraftArguments = overwriteMinecraftArguments; + } version->minecraftArguments = overwriteMinecraftArguments; } if (!addMinecraftArguments.isNull()) @@ -384,13 +460,17 @@ void VersionFile::applyTo(VersionFinal *version) { version->tweakers.removeAll(tweaker); } + version->jarMods.append(jarMods); if (shouldOverwriteLibs) { - version->libraries.clear(); + QList libs; for (auto lib : overwriteLibs) { - version->libraries.append(createLibrary(lib)); + libs.append(createLibrary(lib)); } + if(isVanilla()) + version->vanillaLibraries = libs; + version->libraries = libs; } for (auto lib : addLibs) { diff --git a/logic/VersionFile.h b/logic/VersionFile.h index 169a2066..2332e6d4 100644 --- a/logic/VersionFile.h +++ b/logic/VersionFile.h @@ -81,6 +81,18 @@ struct RawLibrary static RawLibraryPtr fromJson(const QJsonObject &libObj, const QString &filename); }; +struct Jarmod; +typedef std::shared_ptr JarmodPtr; +struct Jarmod +{ + QString name; + QString baseurl; + QString hint; + QString absoluteUrl; + + static JarmodPtr fromJson(const QJsonObject &libObj, const QString &filename); +}; + struct VersionFile; typedef std::shared_ptr VersionFilePtr; struct VersionFile @@ -92,7 +104,8 @@ public: /* methods */ static OneSixLibraryPtr createLibrary(RawLibraryPtr lib); int findLibrary(QList haystack, const QString &needle); void applyTo(VersionFinal *version); - + bool isVanilla(); + bool hasJarMods(); public: /* data */ int order = 0; QString name; @@ -124,4 +137,8 @@ public: /* data */ QList overwriteLibs; QList addLibs; QList removeLibs; + + QSet traits; + + QList jarMods; }; diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp index dedf2ce5..18bd360b 100644 --- a/logic/VersionFinal.cpp +++ b/logic/VersionFinal.cpp @@ -21,16 +21,7 @@ #include "OneSixVersionBuilder.h" #include "OneSixInstance.h" - -template QMap invert(const QMap &in) -{ - QMap out; - for (auto it = in.begin(); it != in.end(); ++it) - { - out.insert(it.value(), it.key()); - } - return out; -} +#include VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) : QAbstractListModel(parent), m_instance(instance) @@ -38,11 +29,10 @@ VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent) clear(); } -void VersionFinal::reload(const bool onlyVanilla, const QStringList &external) +void VersionFinal::reload(const QStringList &external) { - //FIXME: source of epic failure. beginResetModel(); - OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external); + OneSixVersionBuilder::build(this, m_instance, external); reapply(true); endResetModel(); } @@ -60,6 +50,8 @@ void VersionFinal::clear() mainClass.clear(); libraries.clear(); tweakers.clear(); + jarMods.clear(); + traits.clear(); } bool VersionFinal::canRemove(const int index) const @@ -119,6 +111,11 @@ VersionFilePtr VersionFinal::versionFile(const QString &id) return 0; } +bool VersionFinal::hasJarMods() +{ + return !jarMods.isEmpty(); +} + bool VersionFinal::hasFtbPack() { return versionFile("org.multimc.ftb.pack.json") != nullptr; @@ -129,6 +126,36 @@ bool VersionFinal::removeFtbPack() return remove("org.multimc.ftb.pack.json"); } +bool VersionFinal::isVanilla() +{ + QDir patches(PathCombine(m_instance->instanceRoot(), "patches/")); + return versionFiles.size() > 1 || QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")); +} + +bool VersionFinal::revertToVanilla() +{ + beginResetModel(); + auto it = versionFiles.begin(); + while (it != versionFiles.end()) + { + if ((*it)->fileId != "org.multimc.version.json") + { + QFile::remove((*it)->filename); + it = versionFiles.erase(it); + } + else + it++; + } + reapply(true); + endResetModel(); + return true; +} + +bool VersionFinal::usesLegacyCustomJson() +{ + return QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")); +} + QList > VersionFinal::getActiveNormalLibs() { QList > output; @@ -229,15 +256,6 @@ int VersionFinal::columnCount(const QModelIndex &parent) const return 2; } -bool VersionFinal::isCustom() -{ - return QDir(m_instance->instanceRoot()).exists("custom.json"); -} -bool VersionFinal::revertToBase() -{ - return QDir(m_instance->instanceRoot()).remove("custom.json"); -} - QMap VersionFinal::getExistingOrder() const { @@ -356,8 +374,10 @@ void VersionFinal::finalize() { assets = "legacy"; } - if (minecraftArguments.isEmpty()) + auto finalizeArguments = [&]( QString & minecraftArguments, const QString & processArguments ) -> void { + if (!minecraftArguments.isEmpty()) + return; QString toCompare = processArguments.toLower(); if (toCompare == "legacy") { @@ -370,8 +390,11 @@ void VersionFinal::finalize() else if (toCompare == "username_session_version") { minecraftArguments = "--username ${auth_player_name} " - "--session ${auth_session} " - "--version ${profile_name}"; + "--session ${auth_session} " + "--version ${profile_name}"; } - } + }; + finalizeArguments(vanillaMinecraftArguments, vanillaProcessArguments); + finalizeArguments(minecraftArguments, processArguments); } + diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h index 41fd23bd..71e43399 100644 --- a/logic/VersionFinal.h +++ b/logic/VersionFinal.h @@ -38,22 +38,29 @@ public: virtual int columnCount(const QModelIndex &parent) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; - void reload(const bool onlyVanilla = false, const QStringList &external = QStringList()); + void reload(const QStringList &external = QStringList()); void clear(); bool canRemove(const int index) const; QString versionFileId(const int index) const; - // does this instance have an all overriding custom.json - bool isCustom(); - // remove custom.json - bool revertToBase(); - // does this instance have an FTB pack patch file? + // is this version unmodded vanilla minecraft? + bool isVanilla(); + // remove any customizations on top of vanilla + bool revertToVanilla(); + + // does this version have an FTB pack patch file? bool hasFtbPack(); // remove FTB pack bool removeFtbPack(); + // does this version have any jar mods? + bool hasJarMods(); + + // does this version still use a legacy custom.json file? + bool usesLegacyCustomJson(); + enum MoveDirection { MoveUp, MoveDown }; void move(const int index, const MoveDirection direction); @@ -91,6 +98,8 @@ public: * ex: "username_session_version" */ QString processArguments; + /// Same as above, but only for vanilla + QString vanillaProcessArguments; /** * arguments that should be used for launching minecraft * @@ -98,6 +107,8 @@ public: * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" */ QString minecraftArguments; + /// Same as above, but only for vanilla + QString vanillaMinecraftArguments; /** * the minimum launcher version required by this version ... current is 4 (at point of * writing) @@ -114,6 +125,15 @@ public: /// the list of libs - both active and inactive, native and java QList> libraries; + + /// same, but only vanilla. + QList> vanillaLibraries; + + /// traits, collected from all the version files (version files can only add) + QSet traits; + + /// A list of jar mods. version files can add those. + QList jarMods; /* FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. diff --git a/logic/forge/ForgeData.cpp b/logic/forge/ForgeData.cpp new file mode 100644 index 00000000..700b847b --- /dev/null +++ b/logic/forge/ForgeData.cpp @@ -0,0 +1,62 @@ +#include "ForgeData.h" + +extern ForgeData g_forgeData = ForgeData(); + +ForgeData::ForgeData() +{ + // 1.3.* + auto libs13 = + QList{{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false}, + {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false}, + {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}}; + + fmlLibsMapping["1.3.2"] = libs13; + + // 1.4.* + auto libs14 = QList{ + {"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false}, + {"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false}, + {"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}, + {"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb", false}}; + + fmlLibsMapping["1.4"] = libs14; + fmlLibsMapping["1.4.1"] = libs14; + fmlLibsMapping["1.4.2"] = libs14; + fmlLibsMapping["1.4.3"] = libs14; + fmlLibsMapping["1.4.4"] = libs14; + fmlLibsMapping["1.4.5"] = libs14; + fmlLibsMapping["1.4.6"] = libs14; + fmlLibsMapping["1.4.7"] = libs14; + + // 1.5 + fmlLibsMapping["1.5"] = QList{ + {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, + {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, + {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, + {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, + {"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8", false}, + {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; + + // 1.5.1 + fmlLibsMapping["1.5.1"] = QList{ + {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, + {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, + {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, + {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, + {"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6", false}, + {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; + + // 1.5.2 + fmlLibsMapping["1.5.2"] = QList{ + {"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false}, + {"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false}, + {"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false}, + {"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true}, + {"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9", false}, + {"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}}; + + // don't use installers for those. + forgeInstallerBlacklist = QSet({ + "1.5.2" + }); +} diff --git a/logic/forge/ForgeData.h b/logic/forge/ForgeData.h new file mode 100644 index 00000000..27749778 --- /dev/null +++ b/logic/forge/ForgeData.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include +#include + +struct FMLlib +{ + QString filename; + QString checksum; + bool ours; +}; + +struct ForgeData +{ + ForgeData(); + // mapping between minecraft versions and FML libraries required + QMap> fmlLibsMapping; + // set of minecraft versions for which using forge installers is blacklisted + QSet forgeInstallerBlacklist; +}; +extern ForgeData g_forgeData; diff --git a/logic/ForgeInstaller.cpp b/logic/forge/ForgeInstaller.cpp similarity index 64% rename from logic/ForgeInstaller.cpp rename to logic/forge/ForgeInstaller.cpp index 94b3f319..1204b855 100644 --- a/logic/ForgeInstaller.cpp +++ b/logic/forge/ForgeInstaller.cpp @@ -14,9 +14,15 @@ */ #include "ForgeInstaller.h" -#include "VersionFinal.h" -#include "OneSixLibrary.h" -#include "net/HttpMetaCache.h" +#include "logic/VersionFinal.h" +#include "logic/OneSixLibrary.h" +#include "logic/net/HttpMetaCache.h" +#include "logic/tasks/Task.h" +#include "logic/OneSixInstance.h" +#include "logic/forge/ForgeVersionList.h" +#include "ForgeData.h" +#include "gui/dialogs/ProgressDialog.h" + #include #include #include @@ -24,18 +30,12 @@ #include #include #include "MultiMC.h" -#include "tasks/Task.h" -#include "OneSixInstance.h" -#include "lists/ForgeVersionList.h" -#include "gui/dialogs/ProgressDialog.h" - #include #include #include #include -ForgeInstaller::ForgeInstaller() - : BaseInstaller() +ForgeInstaller::ForgeInstaller() : BaseInstaller() { } void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl) @@ -115,8 +115,8 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr } file.close(); - m_forge_version = newVersion; - realVersionId = m_forge_version->id = installObj.value("minecraft").toString(); + m_forge_json = newVersion; + realVersionId = m_forge_json->id = installObj.value("minecraft").toString(); } bool ForgeInstaller::add(OneSixInstance *to) { @@ -128,7 +128,7 @@ bool ForgeInstaller::add(OneSixInstance *to) QJsonObject obj; obj.insert("order", 5); - if (!m_forge_version) + if (!m_forge_json) return false; int sliding_insert_window = 0; { @@ -136,7 +136,7 @@ bool ForgeInstaller::add(OneSixInstance *to) // for each library in the version we are adding (except for the blacklisted) QSet blacklist{"lwjgl", "lwjgl_util", "lwjgl-platform"}; - for (auto lib : m_forge_version->libraries) + for (auto lib : m_forge_json->libraries) { QString libName = lib->name(); // WARNING: This could actually break. @@ -157,7 +157,7 @@ bool ForgeInstaller::add(OneSixInstance *to) bool found = false; bool equals = false; // find an entry that matches this one - for (auto tolib : to->getVanillaVersion()->libraries) + for (auto tolib : to->getFullVersion()->vanillaLibraries) { if (tolib->name() != libName) continue; @@ -187,8 +187,8 @@ bool ForgeInstaller::add(OneSixInstance *to) librariesPlus.prepend(libObj); } obj.insert("+libraries", librariesPlus); - obj.insert("mainClass", m_forge_version->mainClass); - QString args = m_forge_version->minecraftArguments; + obj.insert("mainClass", m_forge_json->mainClass); + QString args = m_forge_json->minecraftArguments; QStringList tweakers; { QRegularExpression expression("--tweakClass ([a-zA-Z0-9\\.]*)"); @@ -200,7 +200,7 @@ bool ForgeInstaller::add(OneSixInstance *to) match = expression.match(args); } } - if (!args.isEmpty() && args != to->getVanillaVersion()->minecraftArguments) + if (!args.isEmpty() && args != to->getFullVersion()->vanillaMinecraftArguments) { obj.insert("minecraftArguments", args); } @@ -208,10 +208,10 @@ bool ForgeInstaller::add(OneSixInstance *to) { obj.insert("+tweakers", QJsonArray::fromStringList(tweakers)); } - if (!m_forge_version->processArguments.isEmpty() && - m_forge_version->processArguments != to->getVanillaVersion()->processArguments) + if (!m_forge_json->processArguments.isEmpty() && + m_forge_json->processArguments != to->getFullVersion()->vanillaProcessArguments) { - obj.insert("processArguments", m_forge_version->processArguments); + obj.insert("processArguments", m_forge_json->processArguments); } } @@ -233,11 +233,54 @@ bool ForgeInstaller::add(OneSixInstance *to) return true; } +bool ForgeInstaller::addLegacy(OneSixInstance *to) +{ + if (!BaseInstaller::add(to)) + { + return false; + } + + QJsonObject obj; + obj.insert("order", 5); + { + QJsonArray jarmodsPlus; + { + QJsonObject libObj; + libObj.insert("name", m_forge_version->universal_filename); + jarmodsPlus.append(libObj); + } + obj.insert("+jarMods", jarmodsPlus); + } + + obj.insert("name", QString("Forge")); + obj.insert("fileId", id()); + obj.insert("version", m_forge_version->jobbuildver); + obj.insert("mcVersion", to->intendedVersionId()); + if (g_forgeData.fmlLibsMapping.contains(m_forge_version->mcver)) + { + QJsonArray traitsPlus; + traitsPlus.append(QString("legacyFML")); + obj.insert("+traits", traitsPlus); + } + + QFile file(filename(to->instanceRoot())); + if (!file.open(QFile::WriteOnly)) + { + QLOG_ERROR() << "Error opening" << file.fileName() + << "for reading:" << file.errorString(); + return false; + } + file.write(QJsonDocument(obj).toJson()); + file.close(); + return true; +} + class ForgeInstallTask : public Task { Q_OBJECT public: - ForgeInstallTask(ForgeInstaller *installer, OneSixInstance *instance, BaseVersionPtr version, QObject *parent = 0) + ForgeInstallTask(ForgeInstaller *installer, OneSixInstance *instance, + BaseVersionPtr version, QObject *parent = 0) : Task(parent), m_installer(installer), m_instance(instance), m_version(version) { } @@ -245,57 +288,60 @@ public: protected: void executeTask() override { + setStatus(tr("Installing forge...")); + ForgeVersionPtr forgeVersion = std::dynamic_pointer_cast(m_version); + if (!forgeVersion) { - setStatus(tr("Installing forge...")); - ForgeVersionPtr forgeVersion = - std::dynamic_pointer_cast(m_version); - if (!forgeVersion) + emitFailed(tr("Unknown error occured")); + return; + } + prepare(forgeVersion); + } + void prepare(ForgeVersionPtr forgeVersion) + { + auto entry = + MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename()); + auto installFunction = [this, entry, forgeVersion]() + { + if (!install(entry, forgeVersion)) { - emitFailed(tr("Unknown error occured")); - return; - } - auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename); - if (entry->stale) - { - NetJob *fjob = new NetJob("Forge download"); - fjob->addNetAction(CacheDownload::make(forgeVersion->installer_url, entry)); - connect(fjob, &NetJob::progress, [this](qint64 current, qint64 total){setProgress(100 * current / qMax((qint64)1, total));}); - connect(fjob, &NetJob::status, [this](const QString &msg){setStatus(msg);}); - connect(fjob, &NetJob::failed, [this](){emitFailed(tr("Failure to download forge"));}); - connect(fjob, &NetJob::succeeded, [this, entry, forgeVersion]() - { - if (!install(entry, forgeVersion)) - { - QLOG_ERROR() << "Failure installing forge"; - emitFailed(tr("Failure to install forge")); - } - else - { - reload(); - } - }); - fjob->start(); + QLOG_ERROR() << "Failure installing forge"; + emitFailed(tr("Failure to install forge")); } else { - if (!install(entry, forgeVersion)) - { - QLOG_ERROR() << "Failure installing forge"; - emitFailed(tr("Failure to install forge")); - } - else - { - reload(); - } + reload(); } + }; + + if (entry->stale) + { + NetJob *fjob = new NetJob("Forge download"); + fjob->addNetAction(CacheDownload::make(forgeVersion->url(), entry)); + connect(fjob, &NetJob::progress, [this](qint64 current, qint64 total) + { setProgress(100 * current / qMax((qint64)1, total)); }); + connect(fjob, &NetJob::status, [this](const QString & msg) + { setStatus(msg); }); + connect(fjob, &NetJob::failed, [this]() + { emitFailed(tr("Failure to download forge")); }); + connect(fjob, &NetJob::succeeded, installFunction); + fjob->start(); + } + else + { + installFunction(); } } - bool install(const std::shared_ptr &entry, const ForgeVersionPtr &forgeVersion) { - QString forgePath = entry->getFullPath(); - m_installer->prepare(forgePath, forgeVersion->universal_url); - return m_installer->add(m_instance); + if (forgeVersion->usesInstaller()) + { + QString forgePath = entry->getFullPath(); + m_installer->prepare(forgePath, forgeVersion->universal_url); + return m_installer->add(m_instance); + } + else + return m_installer->addLegacy(m_instance); } void reload() { @@ -320,8 +366,14 @@ private: BaseVersionPtr m_version; }; -ProgressProvider *ForgeInstaller::createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) +ProgressProvider *ForgeInstaller::createInstallTask(OneSixInstance *instance, + BaseVersionPtr version, QObject *parent) { + if (!version) + { + return nullptr; + } + m_forge_version = std::dynamic_pointer_cast(version); return new ForgeInstallTask(this, instance, version, parent); } diff --git a/logic/ForgeInstaller.h b/logic/forge/ForgeInstaller.h similarity index 64% rename from logic/ForgeInstaller.h rename to logic/forge/ForgeInstaller.h index 05cc994b..dafa6305 100644 --- a/logic/ForgeInstaller.h +++ b/logic/forge/ForgeInstaller.h @@ -15,28 +15,34 @@ #pragma once -#include "BaseInstaller.h" +#include "logic/BaseInstaller.h" #include #include class VersionFinal; +class ForgeInstallTask; +class ForgeVersion; class ForgeInstaller : public BaseInstaller { + friend class ForgeInstallTask; public: ForgeInstaller(); + virtual ~ForgeInstaller(){}; + virtual ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override; +protected: + virtual QString id() const override { return "net.minecraftforge"; } void prepare(const QString &filename, const QString &universalUrl); bool add(OneSixInstance *to) override; - - QString id() const override { return "net.minecraftforge"; } - - ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override; + bool addLegacy(OneSixInstance *to); private: - // the version, read from the installer - std::shared_ptr m_forge_version; + // the parsed version json, read from the installer + std::shared_ptr m_forge_json; + // the actual forge version + std::shared_ptr m_forge_version; QString internalPath; QString finalPath; QString realVersionId; diff --git a/logic/net/ForgeMirror.h b/logic/forge/ForgeMirror.h similarity index 100% rename from logic/net/ForgeMirror.h rename to logic/forge/ForgeMirror.h diff --git a/logic/net/ForgeMirrors.cpp b/logic/forge/ForgeMirrors.cpp similarity index 100% rename from logic/net/ForgeMirrors.cpp rename to logic/forge/ForgeMirrors.cpp diff --git a/logic/net/ForgeMirrors.h b/logic/forge/ForgeMirrors.h similarity index 91% rename from logic/net/ForgeMirrors.h rename to logic/forge/ForgeMirrors.h index 6784fba1..d25762db 100644 --- a/logic/net/ForgeMirrors.h +++ b/logic/forge/ForgeMirrors.h @@ -15,10 +15,10 @@ #pragma once -#include "NetAction.h" -#include "HttpMetaCache.h" -#include "ForgeXzDownload.h" -#include "NetJob.h" +#include "logic/net/NetAction.h" +#include "logic/net/HttpMetaCache.h" +#include "logic/net/NetJob.h" +#include "logic/forge/ForgeXzDownload.h" #include #include typedef std::shared_ptr ForgeMirrorsPtr; diff --git a/logic/forge/ForgeVersion.cpp b/logic/forge/ForgeVersion.cpp new file mode 100644 index 00000000..fd4efc4b --- /dev/null +++ b/logic/forge/ForgeVersion.cpp @@ -0,0 +1,55 @@ +#include "ForgeVersion.h" +#include "ForgeData.h" +#include + +QString ForgeVersion::name() +{ + return "Forge " + jobbuildver; +} + +QString ForgeVersion::descriptor() +{ + return universal_filename; +} + +QString ForgeVersion::typeString() const +{ + if (is_recommended) + return QObject::tr("Recommended"); + return QString(); +} + +bool ForgeVersion::operator<(BaseVersion &a) +{ + ForgeVersion *pa = dynamic_cast(&a); + if (!pa) + return true; + return m_buildnr < pa->m_buildnr; +} + +bool ForgeVersion::operator>(BaseVersion &a) +{ + ForgeVersion *pa = dynamic_cast(&a); + if (!pa) + return false; + return m_buildnr > pa->m_buildnr; +} + +bool ForgeVersion::usesInstaller() +{ + if(installer_url.isEmpty()) + return false; + if(g_forgeData.forgeInstallerBlacklist.contains(mcver)) + return false; + return true; +} + +QString ForgeVersion::filename() +{ + return usesInstaller() ? installer_filename : universal_filename; +} + +QString ForgeVersion::url() +{ + return usesInstaller() ? installer_url : universal_url; +} diff --git a/logic/forge/ForgeVersion.h b/logic/forge/ForgeVersion.h new file mode 100644 index 00000000..74e45c5a --- /dev/null +++ b/logic/forge/ForgeVersion.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include "logic/BaseVersion.h" + +struct ForgeVersion; +typedef std::shared_ptr ForgeVersionPtr; + +struct ForgeVersion : public BaseVersion +{ + virtual QString descriptor() override; + virtual QString name() override; + virtual QString typeString() const override; + virtual bool operator<(BaseVersion &a) override; + virtual bool operator>(BaseVersion &a) override; + + QString filename(); + QString url(); + + bool usesInstaller(); + + int m_buildnr = 0; + QString universal_url; + QString changelog_url; + QString installer_url; + QString jobbuildver; + QString mcver; + QString universal_filename; + QString installer_filename; + bool is_recommended = false; +}; diff --git a/logic/lists/ForgeVersionList.cpp b/logic/forge/ForgeVersionList.cpp similarity index 95% rename from logic/lists/ForgeVersionList.cpp rename to logic/forge/ForgeVersionList.cpp index 4902dc64..c873bab7 100644 --- a/logic/lists/ForgeVersionList.cpp +++ b/logic/forge/ForgeVersionList.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ -#include "ForgeVersionList.h" -#include -#include +#include "logic/forge/ForgeVersionList.h" +#include "logic/forge/ForgeVersion.h" +#include "logic/net/NetJob.h" +#include "logic/net/URLConstants.h" #include "MultiMC.h" #include @@ -236,7 +237,7 @@ bool ForgeListLoadTask::parseForgeList(QList &out) if (!build_nr) continue; QJsonArray files = obj.value("files").toArray(); - QString url, jobbuildver, mcver, buildtype, filename; + QString url, jobbuildver, mcver, buildtype, universal_filename; QString changelog_url, installer_url; QString installer_filename; bool valid = false; @@ -254,7 +255,7 @@ bool ForgeListLoadTask::parseForgeList(QList &out) url = file.value("url").toString(); jobbuildver = file.value("jobbuildver").toString(); int lastSlash = url.lastIndexOf('/'); - filename = url.mid(lastSlash + 1); + universal_filename = url.mid(lastSlash + 1); valid = true; } else if (buildtype == "changelog") @@ -282,14 +283,8 @@ bool ForgeListLoadTask::parseForgeList(QList &out) fVersion->installer_url = installer_url; fVersion->jobbuildver = jobbuildver; fVersion->mcver = mcver; - if (installer_filename.isEmpty()) - { - fVersion->filename = filename; - } - else - { - fVersion->filename = installer_filename; - } + fVersion->installer_filename = installer_filename; + fVersion->universal_filename = universal_filename; fVersion->m_buildnr = build_nr; out.append(fVersion); } @@ -342,7 +337,7 @@ bool ForgeListLoadTask::parseForgeGradleList(QList &out) fVersion->m_buildnr = number.value("build").toDouble(); fVersion->jobbuildver = number.value("version").toString(); fVersion->mcver = number.value("mcversion").toString(); - fVersion->filename = ""; + fVersion->universal_filename = ""; QString filename, installer_filename; QJsonArray files = number.value("files").toArray(); for (auto fIt = files.begin(); fIt != files.end(); ++fIt) @@ -380,7 +375,8 @@ bool ForgeListLoadTask::parseForgeGradleList(QList &out) { continue; } - fVersion->filename = fVersion->installer_url.isEmpty() ? filename : installer_filename; + fVersion->universal_filename = filename; + fVersion->installer_filename = installer_filename; out.append(fVersion); } diff --git a/logic/lists/ForgeVersionList.h b/logic/forge/ForgeVersionList.h similarity index 68% rename from logic/lists/ForgeVersionList.h rename to logic/forge/ForgeVersionList.h index b19d3f56..c848e9b8 100644 --- a/logic/lists/ForgeVersionList.h +++ b/logic/forge/ForgeVersionList.h @@ -18,57 +18,12 @@ #include #include #include - #include -#include "BaseVersionList.h" + +#include "logic/lists/BaseVersionList.h" #include "logic/tasks/Task.h" #include "logic/net/NetJob.h" - -class ForgeVersion; -typedef std::shared_ptr ForgeVersionPtr; - -struct ForgeVersion : public BaseVersion -{ - virtual QString descriptor() override - { - return filename; - } - ; - virtual QString name() override - { - return "Forge " + jobbuildver; - } - ; - virtual QString typeString() const override - { - if (installer_url.isEmpty()) - return "Universal"; - else - return "Installer"; - } - - virtual bool operator<(BaseVersion &a) override - { - ForgeVersion *pa = dynamic_cast(&a); - if(!pa) - return true; - return m_buildnr < pa->m_buildnr; - } - virtual bool operator>(BaseVersion &a) override - { - ForgeVersion *pa = dynamic_cast(&a); - if(!pa) - return false; - return m_buildnr > pa->m_buildnr; - } - int m_buildnr = 0; - QString universal_url; - QString changelog_url; - QString installer_url; - QString jobbuildver; - QString mcver; - QString filename; -}; +#include "logic/forge/ForgeVersion.h" class ForgeVersionList : public BaseVersionList { diff --git a/logic/net/ForgeXzDownload.cpp b/logic/forge/ForgeXzDownload.cpp similarity index 100% rename from logic/net/ForgeXzDownload.cpp rename to logic/forge/ForgeXzDownload.cpp diff --git a/logic/net/ForgeXzDownload.h b/logic/forge/ForgeXzDownload.h similarity index 96% rename from logic/net/ForgeXzDownload.h rename to logic/forge/ForgeXzDownload.h index 7bdfb6d9..f2564380 100644 --- a/logic/net/ForgeXzDownload.h +++ b/logic/forge/ForgeXzDownload.h @@ -15,8 +15,8 @@ #pragma once -#include "NetAction.h" -#include "HttpMetaCache.h" +#include "logic/net/NetAction.h" +#include "logic/net/HttpMetaCache.h" #include #include #include "ForgeMirror.h" diff --git a/logic/LegacyForge.cpp b/logic/forge/LegacyForge.cpp similarity index 100% rename from logic/LegacyForge.cpp rename to logic/forge/LegacyForge.cpp diff --git a/logic/LegacyForge.h b/logic/forge/LegacyForge.h similarity index 97% rename from logic/LegacyForge.h rename to logic/forge/LegacyForge.h index f4165ffa..ec49f63c 100644 --- a/logic/LegacyForge.h +++ b/logic/forge/LegacyForge.h @@ -15,7 +15,7 @@ #pragma once -#include "Mod.h" +#include "logic/Mod.h" class MinecraftForge : public Mod { diff --git a/logic/lists/MinecraftVersionList.cpp b/logic/lists/MinecraftVersionList.cpp index b9d60c61..ec2f2d21 100644 --- a/logic/lists/MinecraftVersionList.cpp +++ b/logic/lists/MinecraftVersionList.cpp @@ -212,6 +212,7 @@ void MCVListLoadTask::list_downloaded() { bool is_snapshot = false; bool is_latest = false; + bool legacyLaunch = false; // Load the version info. if (!versions[i].isObject()) @@ -236,32 +237,28 @@ void MCVListLoadTask::list_downloaded() // FIXME: log this somewhere continue; } - // Parse the type. - MinecraftVersion::VersionType versionType; // OneSix or Legacy. use filter to determine type if (versionTypeStr == "release") { - versionType = legacyWhitelist.contains(versionID) ? MinecraftVersion::Legacy - : MinecraftVersion::OneSix; + legacyLaunch = legacyWhitelist.contains(versionID); is_latest = (versionID == latestReleaseID); is_snapshot = false; } else if (versionTypeStr == "snapshot") // It's a snapshot... yay { - versionType = legacyWhitelist.contains(versionID) ? MinecraftVersion::Legacy - : MinecraftVersion::OneSix; + legacyLaunch = legacyWhitelist.contains(versionID); is_latest = (versionID == latestSnapshotID); is_snapshot = true; } else if (versionTypeStr == "old_alpha") { - versionType = MinecraftVersion::Nostalgia; + legacyLaunch = false; is_latest = false; is_snapshot = false; } else if (versionTypeStr == "old_beta") { - versionType = MinecraftVersion::Legacy; + legacyLaunch = true; is_latest = false; is_snapshot = false; } @@ -280,7 +277,8 @@ void MCVListLoadTask::list_downloaded() mcVersion->download_url = dlUrl; mcVersion->is_latest = is_latest; mcVersion->is_snapshot = is_snapshot; - mcVersion->type = versionType; + if(legacyLaunch) + mcVersion->features.insert("legacy"); tempList.append(mcVersion); } m_list->updateListData(tempList); diff --git a/logic/LiteLoaderInstaller.cpp b/logic/liteloader/LiteLoaderInstaller.cpp similarity index 96% rename from logic/LiteLoaderInstaller.cpp rename to logic/liteloader/LiteLoaderInstaller.cpp index 99cc5643..1a94e644 100644 --- a/logic/LiteLoaderInstaller.cpp +++ b/logic/liteloader/LiteLoaderInstaller.cpp @@ -20,11 +20,11 @@ #include "logger/QsLog.h" -#include "VersionFinal.h" -#include "OneSixLibrary.h" -#include "OneSixInstance.h" +#include "logic/VersionFinal.h" +#include "logic/OneSixLibrary.h" +#include "logic/OneSixInstance.h" #include "MultiMC.h" -#include "lists/LiteLoaderVersionList.h" +#include "logic/liteloader/LiteLoaderVersionList.h" LiteLoaderInstaller::LiteLoaderInstaller() : BaseInstaller() { diff --git a/logic/LiteLoaderInstaller.h b/logic/liteloader/LiteLoaderInstaller.h similarity index 92% rename from logic/LiteLoaderInstaller.h rename to logic/liteloader/LiteLoaderInstaller.h index 3ab5acb2..43ad6b83 100644 --- a/logic/LiteLoaderInstaller.h +++ b/logic/liteloader/LiteLoaderInstaller.h @@ -15,12 +15,11 @@ #pragma once -#include "BaseInstaller.h" - #include #include -#include "logic/lists/LiteLoaderVersionList.h" +#include "logic/BaseInstaller.h" +#include "logic/liteloader/LiteLoaderVersionList.h" class LiteLoaderInstaller : public BaseInstaller { diff --git a/logic/lists/LiteLoaderVersionList.cpp b/logic/liteloader/LiteLoaderVersionList.cpp similarity index 100% rename from logic/lists/LiteLoaderVersionList.cpp rename to logic/liteloader/LiteLoaderVersionList.cpp diff --git a/logic/lists/LiteLoaderVersionList.h b/logic/liteloader/LiteLoaderVersionList.h similarity index 96% rename from logic/lists/LiteLoaderVersionList.h rename to logic/liteloader/LiteLoaderVersionList.h index bfc913e5..aa35f1ca 100644 --- a/logic/lists/LiteLoaderVersionList.h +++ b/logic/liteloader/LiteLoaderVersionList.h @@ -19,10 +19,10 @@ #include #include -#include "BaseVersionList.h" +#include "logic/lists/BaseVersionList.h" #include "logic/tasks/Task.h" #include "logic/BaseVersion.h" -#include +#include "logic/net/NetJob.h" class LLListLoadTask; class QNetworkReply; diff --git a/logic/net/NetJob.h b/logic/net/NetJob.h index 2df8428b..66bf7fb6 100644 --- a/logic/net/NetJob.h +++ b/logic/net/NetJob.h @@ -21,7 +21,7 @@ #include "MD5EtagDownload.h" #include "CacheDownload.h" #include "HttpMetaCache.h" -#include "ForgeXzDownload.h" +//#include "logic/forge/ForgeXzDownload.h" #include "logic/tasks/ProgressProvider.h" class NetJob;