From ceca6959d2a7f258d62ac4f589095b65084706c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 22 Sep 2013 04:21:36 +0200 Subject: [PATCH] Working 1.6 modding (currently only forge) --- .clang-format | 24 +++ CMakeLists.txt | 148 ++++++++--------- MultiMC.cpp | 70 +++----- MultiMC.h | 39 ++--- gui/IconPickerDialog.cpp | 4 +- gui/LegacyModEditDialog.cpp | 2 +- gui/OneSixModEditDialog.cpp | 181 ++++++++++++--------- gui/OneSixModEditDialog.h | 3 +- gui/instancedelegate.h | 2 +- gui/lwjglselectdialog.cpp | 6 +- gui/mainwindow.cpp | 6 +- gui/mainwindow.ui | 2 +- gui/newinstancedialog.cpp | 2 +- gui/settingsdialog.cpp | 4 +- logic/BaseInstance.cpp | 2 +- logic/BaseInstance.h | 2 +- logic/ForgeInstaller.cpp | 125 +++++++++++++++ logic/ForgeInstaller.h | 25 +++ logic/LegacyUpdate.cpp | 4 +- logic/ModList.h | 3 + logic/OneSixInstance.cpp | 114 +++++++------- logic/OneSixLibrary.cpp | 98 +++++++++--- logic/OneSixLibrary.h | 26 +-- logic/OneSixRule.cpp | 66 +++++++- logic/OneSixRule.h | 6 +- logic/OneSixUpdate.cpp | 85 +++++----- logic/OneSixVersion.cpp | 263 +++++++++++++++++++++++++++---- logic/OneSixVersion.h | 60 ++++--- logic/OpSys.cpp | 11 ++ logic/OpSys.h | 1 + logic/VersionFactory.cpp | 196 ----------------------- logic/VersionFactory.h | 24 --- logic/lists/ForgeVersionList.cpp | 11 +- logic/lists/ForgeVersionList.h | 52 +++--- logic/tasks/LoginTask.cpp | 2 +- 35 files changed, 996 insertions(+), 673 deletions(-) create mode 100644 .clang-format create mode 100644 logic/ForgeInstaller.cpp create mode 100644 logic/ForgeInstaller.h delete mode 100644 logic/VersionFactory.cpp delete mode 100644 logic/VersionFactory.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..167a8fa7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,24 @@ +UseTab: true +IndentWidth: 4 +TabWidth: 4 +ConstructorInitializerIndentWidth: 4 +AccessModifierOffset: -4 +IndentCaseLabels: false +IndentFunctionDeclarationAfterType: false +NamespaceIndentation: None + +BreakBeforeBraces: Allman +AllowShortIfStatementsOnASingleLine: false +ColumnLimit: 96 +MaxEmptyLinesToKeep: 1 + +Standard: Cpp11 +Cpp11BracedListStyle: true + +SpacesInParentheses: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpaceAfterControlStatementKeyword: true + +AlignTrailingComments: true +SpacesBeforeTrailingComments: 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f09e324..aa7a91f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,165 +147,143 @@ ADD_DEFINITIONS(-DLIBGROUPVIEW_STATIC) ################################ FILES ################################ -######## Headers ######## -SET(MULTIMC_HEADERS +######## Sources and headers ######## +SET(MULTIMC_SOURCES +# Application base MultiMC.h +MultiMC.cpp MultiMCVersion.h +# GUI gui/mainwindow.h +gui/mainwindow.cpp gui/settingsdialog.h +gui/settingsdialog.cpp gui/newinstancedialog.h +gui/newinstancedialog.cpp gui/logindialog.h +gui/logindialog.cpp gui/ProgressDialog.h +gui/ProgressDialog.cpp gui/aboutdialog.h +gui/aboutdialog.cpp gui/consolewindow.h +gui/consolewindow.cpp gui/instancedelegate.h +gui/instancedelegate.cpp gui/versionselectdialog.h +gui/versionselectdialog.cpp gui/lwjglselectdialog.h +gui/lwjglselectdialog.cpp gui/instancesettings.h +gui/instancesettings.cpp gui/IconPickerDialog.h +gui/IconPickerDialog.cpp gui/LegacyModEditDialog.h +gui/LegacyModEditDialog.cpp gui/OneSixModEditDialog.h +gui/OneSixModEditDialog.cpp gui/ModEditDialogCommon.h +gui/ModEditDialogCommon.cpp gui/ModListView.h +gui/ModListView.cpp gui/LabeledToolButton.h +gui/LabeledToolButton.cpp gui/EditNotesDialog.h +gui/EditNotesDialog.cpp # Base classes and infrastructure logic/BaseVersion.h logic/MinecraftVersion.h logic/InstanceFactory.h +logic/InstanceFactory.cpp logic/BaseUpdate.h +logic/BaseUpdate.cpp logic/BaseInstance.h +logic/BaseInstance.cpp logic/BaseInstance_p.h + logic/MinecraftProcess.h +logic/MinecraftProcess.cpp logic/Mod.h +logic/Mod.cpp logic/ModList.h +logic/ModList.cpp # Basic instance launcher for starting from terminal logic/InstanceLauncher.h +logic/InstanceLauncher.cpp # network stuffs logic/net/Download.h logic/net/FileDownload.h -logic/net/ByteArrayDownload.h -logic/net/CacheDownload.h -logic/net/DownloadJob.h -logic/net/HttpMetaCache.h - -# legacy instances -logic/LegacyInstance.h -logic/LegacyInstance_p.h -logic/LegacyUpdate.h -logic/LegacyForge.h - -# 1.6 instances -logic/OneSixAssets.h -logic/OneSixInstance.h -logic/OneSixInstance_p.h -logic/OneSixUpdate.h -logic/OneSixVersion.h -logic/OneSixLibrary.h -logic/OneSixRule.h -logic/VersionFactory.h -logic/OpSys.h - - -# Nostalgia -logic/NostalgiaInstance.h - -# Lists -logic/lists/InstanceList.h -logic/lists/IconList.h -logic/lists/BaseVersionList.h -logic/lists/MinecraftVersionList.h -logic/lists/LwjglVersionList.h -logic/lists/ForgeVersionList.h - -# misc model/view -logic/EnabledItemFilter.h - -# Tasks -logic/tasks/Task.h -logic/tasks/LoginTask.h -logic/tasks/ProgressProvider.h -) - - -######## Sources ######## -SET(MULTIMC_SOURCES -MultiMC.cpp - -gui/mainwindow.cpp -gui/settingsdialog.cpp -gui/newinstancedialog.cpp -gui/logindialog.cpp -gui/aboutdialog.cpp -gui/consolewindow.cpp -gui/instancedelegate.cpp -gui/versionselectdialog.cpp -gui/lwjglselectdialog.cpp -gui/instancesettings.cpp - -gui/ProgressDialog.cpp -gui/IconPickerDialog.cpp -gui/LegacyModEditDialog.cpp -gui/OneSixModEditDialog.cpp -gui/ModEditDialogCommon.cpp -gui/ModListView.cpp -gui/LabeledToolButton.cpp -gui/EditNotesDialog.cpp - -# Base classes and infrastructure -logic/InstanceFactory.cpp -logic/BaseUpdate.cpp -logic/BaseInstance.cpp -logic/MinecraftProcess.cpp -logic/Mod.cpp -logic/ModList.cpp - -# Basic instance launcher for starting from terminal -logic/InstanceLauncher.cpp - -# network stuffs - to be moved into a depend lib ~_~ logic/net/FileDownload.cpp +logic/net/ByteArrayDownload.h logic/net/ByteArrayDownload.cpp +logic/net/CacheDownload.h logic/net/CacheDownload.cpp +logic/net/DownloadJob.h logic/net/DownloadJob.cpp +logic/net/HttpMetaCache.h logic/net/HttpMetaCache.cpp # legacy instances +logic/LegacyInstance.h logic/LegacyInstance.cpp +logic/LegacyInstance_p.h +logic/LegacyUpdate.h logic/LegacyUpdate.cpp +logic/LegacyForge.h logic/LegacyForge.cpp # 1.6 instances +logic/OneSixAssets.h logic/OneSixAssets.cpp +logic/OneSixInstance.h logic/OneSixInstance.cpp +logic/OneSixInstance_p.h +logic/OneSixUpdate.h logic/OneSixUpdate.cpp +logic/OneSixVersion.h logic/OneSixVersion.cpp +logic/OneSixLibrary.h logic/OneSixLibrary.cpp +logic/OneSixRule.h logic/OneSixRule.cpp -logic/VersionFactory.cpp +logic/OpSys.h logic/OpSys.cpp +logic/ForgeInstaller.h +logic/ForgeInstaller.cpp # Nostalgia +logic/NostalgiaInstance.h logic/NostalgiaInstance.cpp # Lists +logic/lists/InstanceList.h logic/lists/InstanceList.cpp +logic/lists/IconList.h logic/lists/IconList.cpp +logic/lists/BaseVersionList.h logic/lists/BaseVersionList.cpp +logic/lists/MinecraftVersionList.h logic/lists/MinecraftVersionList.cpp +logic/lists/LwjglVersionList.h logic/lists/LwjglVersionList.cpp +logic/lists/ForgeVersionList.h logic/lists/ForgeVersionList.cpp # misc model/view +logic/EnabledItemFilter.h logic/EnabledItemFilter.cpp # Tasks +logic/tasks/ProgressProvider.h +logic/tasks/Task.h logic/tasks/Task.cpp +logic/tasks/LoginTask.h logic/tasks/LoginTask.cpp + ) @@ -328,7 +306,7 @@ gui/OneSixModEditDialog.ui gui/EditNotesDialog.ui ) -set (FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE} ${MULTIMC_SOURCES} ${MULTIMC_UIS} ${MULTIMC_HEADERS}) +set (FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE} ${MULTIMC_SOURCES} ${MULTIMC_UIS}) ######## Windows resource files ######## @@ -362,7 +340,7 @@ QT5_ADD_RESOURCES(MULTIMC_QRC multimc.qrc) # Add executable ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32 - ${MULTIMC_SOURCES} ${MULTIMC_HEADERS} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS}) + ${MULTIMC_SOURCES} ${MULTIMC_UI} ${MULTIMC_QRC} ${MULTIMC_RCS}) # Link QT5_USE_MODULES(MultiMC Widgets Network Xml) diff --git a/MultiMC.cpp b/MultiMC.cpp index 4b5b40b2..decc22bf 100644 --- a/MultiMC.cpp +++ b/MultiMC.cpp @@ -123,7 +123,7 @@ MultiMC::MultiMC ( int& argc, char** argv ) initGlobalSettings(); // and instances - m_instances = new InstanceList(m_settings->get("InstanceDir").toString(),this); + m_instances.reset(new InstanceList(m_settings->get("InstanceDir").toString(),this)); std::cout << "Loading Instances..." << std::endl; m_instances->loadList(); @@ -131,7 +131,7 @@ MultiMC::MultiMC ( int& argc, char** argv ) initHttpMetaCache(); // create the global network manager - m_qnam = new QNetworkAccessManager(this); + m_qnam.reset(new QNetworkAccessManager(this)); // Register meta types. qRegisterMetaType("LoginResponse"); @@ -152,80 +152,59 @@ MultiMC::~MultiMC() { if(m_mmc_translator) { - removeTranslator(m_mmc_translator); - delete m_mmc_translator; - m_mmc_translator = nullptr; + removeTranslator(m_mmc_translator.data()); } if(m_qt_translator) { - removeTranslator(m_qt_translator); - delete m_qt_translator; - m_qt_translator = nullptr; + removeTranslator(m_qt_translator.data()); } - if(m_icons) - { - delete m_icons; - m_icons = nullptr; - } - if(m_lwjgllist) - { - delete m_lwjgllist; - m_lwjgllist = nullptr; - } - if(m_minecraftlist) - { - delete m_minecraftlist; - m_minecraftlist = nullptr; - } - delete m_settings; - delete m_metacache; } void MultiMC::initTranslations() { - m_qt_translator = new QTranslator(); + m_qt_translator.reset(new QTranslator()); if(m_qt_translator->load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { std::cout << "Loading Qt Language File for " << QLocale::system().name().toLocal8Bit().constData() << "..."; - if(!installTranslator(m_qt_translator)) + if(!installTranslator(m_qt_translator.data())) { std::cout << " failed."; + m_qt_translator.reset(); } std::cout << std::endl; } else { - delete m_qt_translator; - m_qt_translator = nullptr; + m_qt_translator.reset(); } - m_mmc_translator = new QTranslator(); + m_mmc_translator.reset(new QTranslator()); if(m_mmc_translator->load("mmc_" + QLocale::system().name(), QDir("translations").absolutePath())) { std::cout << "Loading MMC Language File for " << QLocale::system().name().toLocal8Bit().constData() << "..."; - if(!installTranslator(m_mmc_translator)) + if(!installTranslator(m_mmc_translator.data())) { std::cout << " failed."; + m_mmc_translator.reset(); } std::cout << std::endl; } else { - delete m_mmc_translator; - m_mmc_translator = nullptr; + m_mmc_translator.reset(); } } void MultiMC::initGlobalSettings() { - m_settings = new INISettingsObject("multimc.cfg", this); + m_settings.reset(new INISettingsObject("multimc.cfg", this)); // Updates m_settings->registerSetting(new Setting("UseDevBuilds", false)); m_settings->registerSetting(new Setting("AutoUpdate", true)); @@ -278,7 +257,7 @@ void MultiMC::initGlobalSettings() void MultiMC::initHttpMetaCache() { - m_metacache = new HttpMetaCache("metacache"); + m_metacache.reset(new HttpMetaCache("metacache")); m_metacache->addBase("assets", QDir("assets").absolutePath()); m_metacache->addBase("versions", QDir("versions").absolutePath()); m_metacache->addBase("libraries", QDir("libraries").absolutePath()); @@ -287,37 +266,38 @@ void MultiMC::initHttpMetaCache() } -IconList* MultiMC::icons() +QSharedPointer MultiMC::icons() { if ( !m_icons ) { - m_icons = new IconList; + m_icons.reset(new IconList); } return m_icons; } -LWJGLVersionList* MultiMC::lwjgllist() +QSharedPointer MultiMC::lwjgllist() { if ( !m_lwjgllist ) { - m_lwjgllist = new LWJGLVersionList(); + m_lwjgllist.reset(new LWJGLVersionList()); } return m_lwjgllist; } -ForgeVersionList* MultiMC::forgelist() + +QSharedPointer MultiMC::forgelist() { if ( !m_forgelist ) { - m_forgelist = new ForgeVersionList(); + m_forgelist.reset(new ForgeVersionList()); } return m_forgelist; } -MinecraftVersionList* MultiMC::minecraftlist() +QSharedPointer MultiMC::minecraftlist() { if ( !m_minecraftlist ) { - m_minecraftlist = new MinecraftVersionList(); + m_minecraftlist.reset(new MinecraftVersionList()); } return m_minecraftlist; } @@ -345,4 +325,6 @@ int main(int argc, char *argv[]) } } -#include "MultiMC.moc" \ No newline at end of file +#include "MultiMC.moc" + + diff --git a/MultiMC.h b/MultiMC.h index d3e92584..1c1298e2 100644 --- a/MultiMC.h +++ b/MultiMC.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "MultiMCVersion.h" #include "config.h" @@ -33,17 +34,17 @@ public: MultiMC ( int& argc, char** argv ); virtual ~MultiMC(); - SettingsObject * settings() + QSharedPointer settings() { return m_settings; }; - InstanceList * instances() + QSharedPointer instances() { return m_instances; }; - IconList * icons(); + QSharedPointer icons(); Status status() { @@ -55,21 +56,21 @@ public: return m_version; } - QNetworkAccessManager * qnam() + QSharedPointer qnam() { return m_qnam; } - HttpMetaCache * metacache() + QSharedPointer metacache() { return m_metacache; } - LWJGLVersionList * lwjgllist(); + QSharedPointer lwjgllist(); - ForgeVersionList * forgelist(); + QSharedPointer forgelist(); - MinecraftVersionList * minecraftlist(); + QSharedPointer minecraftlist(); private: void initGlobalSettings(); @@ -77,17 +78,17 @@ private: void initTranslations(); private: - QTranslator * m_qt_translator = nullptr; - QTranslator * m_mmc_translator = nullptr; - SettingsObject * m_settings = nullptr; - InstanceList * m_instances = nullptr; - IconList * m_icons = nullptr; - QNetworkAccessManager * m_qnam = nullptr; - HttpMetaCache * m_metacache = nullptr; - Status m_status = MultiMC::Failed; - LWJGLVersionList * m_lwjgllist = nullptr; - ForgeVersionList * m_forgelist = nullptr; - MinecraftVersionList * m_minecraftlist = nullptr; + QSharedPointer m_qt_translator; + QSharedPointer m_mmc_translator; + QSharedPointer m_settings; + QSharedPointer m_instances; + QSharedPointer m_icons; + QSharedPointer m_qnam; + QSharedPointer m_metacache; + QSharedPointer m_lwjgllist; + QSharedPointer m_forgelist; + QSharedPointer m_minecraftlist; + Status m_status = MultiMC::Failed; MultiMCVersion m_version = {VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD}; }; \ No newline at end of file diff --git a/gui/IconPickerDialog.cpp b/gui/IconPickerDialog.cpp index f3947d21..8f5d8256 100644 --- a/gui/IconPickerDialog.cpp +++ b/gui/IconPickerDialog.cpp @@ -39,7 +39,7 @@ IconPickerDialog::IconPickerDialog(QWidget *parent) : contentsWidget->installEventFilter(this); - contentsWidget->setModel(MMC->icons()); + contentsWidget->setModel(MMC->icons().data()); auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"),QDialogButtonBox::ResetRole); auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"),QDialogButtonBox::ResetRole); @@ -119,7 +119,7 @@ void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelectio int IconPickerDialog::exec ( QString selection ) { - IconList * list = MMC->icons(); + auto list = MMC->icons(); auto contentsWidget = ui->iconView; selectedIconKey = selection; diff --git a/gui/LegacyModEditDialog.cpp b/gui/LegacyModEditDialog.cpp index 1a1198b1..20296769 100644 --- a/gui/LegacyModEditDialog.cpp +++ b/gui/LegacyModEditDialog.cpp @@ -199,7 +199,7 @@ void LegacyModEditDialog::on_addCoreBtn_clicked() } void LegacyModEditDialog::on_addForgeBtn_clicked() { - VersionSelectDialog vselect(MMC->forgelist(), this); + VersionSelectDialog vselect(MMC->forgelist().data(), this); vselect.setFilter(1, m_inst->intendedVersionId()); if (vselect.exec() && vselect.selectedVersion()) { diff --git a/gui/OneSixModEditDialog.cpp b/gui/OneSixModEditDialog.cpp index 7cbb9cbd..94fea933 100644 --- a/gui/OneSixModEditDialog.cpp +++ b/gui/OneSixModEditDialog.cpp @@ -1,9 +1,9 @@ /* 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 @@ -20,6 +20,7 @@ #include "logic/OneSixVersion.h" #include "logic/EnabledItemFilter.h" #include "logic/lists/ForgeVersionList.h" +#include #include "gui/versionselectdialog.h" #include "ProgressDialog.h" @@ -30,30 +31,33 @@ #include #include -OneSixModEditDialog::OneSixModEditDialog(OneSixInstance * inst, QWidget *parent): - m_inst(inst), - QDialog(parent), - ui(new Ui::OneSixModEditDialog) +OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent) + : m_inst(inst), QDialog(parent), ui(new Ui::OneSixModEditDialog) { ui->setupUi(this); - //libraries! + // libraries! + + m_version = m_inst->getFullVersion(); + if (m_version) { - m_version = m_inst->getFullVersion(); - main_model = new EnabledItemFilter(this); main_model->setActive(true); main_model->setSourceModel(m_version.data()); ui->libraryTreeView->setModel(main_model); - ui->libraryTreeView->installEventFilter( this ); + ui->libraryTreeView->installEventFilter(this); ui->mainClassEdit->setText(m_version->mainClass); - updateButtons(); + updateVersionControls(); + } + else + { + disableVersionControls(); } // Loader mods { ensureFolderPathExists(m_inst->loaderModsDir()); m_mods = m_inst->loaderModList(); ui->loaderModTreeView->setModel(m_mods.data()); - ui->loaderModTreeView->installEventFilter( this ); + ui->loaderModTreeView->installEventFilter(this); m_mods->startWatching(); } // resource packs @@ -61,7 +65,7 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance * inst, QWidget *parent) ensureFolderPathExists(m_inst->resourcePacksDir()); m_resourcepacks = m_inst->resourcePackList(); ui->resPackTreeView->setModel(m_resourcepacks.data()); - ui->resPackTreeView->installEventFilter( this ); + ui->resPackTreeView->installEventFilter(this); m_resourcepacks->startWatching(); } } @@ -73,48 +77,62 @@ OneSixModEditDialog::~OneSixModEditDialog() delete ui; } -void OneSixModEditDialog::updateButtons() +void OneSixModEditDialog::updateVersionControls() { bool customVersion = m_inst->versionIsCustom(); ui->customizeBtn->setEnabled(!customVersion); ui->revertBtn->setEnabled(customVersion); + ui->forgeBtn->setEnabled(true); } +void OneSixModEditDialog::disableVersionControls() +{ + ui->customizeBtn->setEnabled(false); + ui->revertBtn->setEnabled(false); + ui->forgeBtn->setEnabled(false); +} void OneSixModEditDialog::on_customizeBtn_clicked() { - if(m_inst->customizeVersion()) + if (m_inst->customizeVersion()) { m_version = m_inst->getFullVersion(); main_model->setSourceModel(m_version.data()); - updateButtons(); + updateVersionControls(); } } void OneSixModEditDialog::on_revertBtn_clicked() { - auto reply = QMessageBox::question(this, tr("Revert?"), tr("Do you want to revert the version of this instance to its original configuration?"),QMessageBox::Yes|QMessageBox::No); + auto reply = QMessageBox::question( + this, tr("Revert?"), tr("Do you want to revert the " + "version of this instance to its original configuration?"), + QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { - if(m_inst->revertCustomVersion()) + if (m_inst->revertCustomVersion()) { m_version = m_inst->getFullVersion(); main_model->setSourceModel(m_version.data()); - updateButtons(); + updateVersionControls(); } } } - void OneSixModEditDialog::on_forgeBtn_clicked() { - VersionSelectDialog vselect(MMC->forgelist(), this); + VersionSelectDialog vselect(MMC->forgelist().data(), this); vselect.setFilter(1, m_inst->currentVersionId()); if (vselect.exec() && vselect.selectedVersion()) { - if(m_inst->versionIsCustom()) + if (m_inst->versionIsCustom()) { - auto reply = QMessageBox::question(this, tr("Revert?"), tr("This will revert any changes you did to the version up to this point. Is that OK?"),QMessageBox::Yes|QMessageBox::No); + auto reply = QMessageBox::question( + this, tr("Revert?"), + tr("This will revert any " + "changes you did to the version up to this point. Is that " + "OK?"), + QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::Yes) { m_inst->revertCustomVersion(); @@ -122,24 +140,38 @@ void OneSixModEditDialog::on_forgeBtn_clicked() { m_version = m_inst->getFullVersion(); main_model->setSourceModel(m_version.data()); - updateButtons(); + updateVersionControls(); } } - else return; + else + return; } - ForgeVersionPtr forge = vselect.selectedVersion().dynamicCast(); - if(!forge) - return; - auto entry = MMC->metacache()->resolveEntry("minecraftforge", forge->filename); - if(entry->stale) + else { - DownloadJob * fjob = new DownloadJob("Forge download"); - fjob->add(forge->universal_url, entry); + m_inst->customizeVersion(); + m_version = m_inst->getFullVersion(); + main_model->setSourceModel(m_version.data()); + updateVersionControls(); + } + ForgeVersionPtr forgeVersion = vselect.selectedVersion().dynamicCast(); + if (!forgeVersion) + return; + auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename); + if (entry->stale) + { + DownloadJob *fjob = new DownloadJob("Forge download"); + fjob->add(forgeVersion->installer_url, entry); ProgressDialog dlg(this); dlg.exec(fjob); - if(dlg.result() == QDialog::Accepted) + if (dlg.result() == QDialog::Accepted) { // install + QString forgePath = entry->getFullPath(); + ForgeInstaller forge(forgePath, forgeVersion->universal_url); + if (!forge.apply(m_version)) + { + // failure notice + } } else { @@ -149,55 +181,60 @@ void OneSixModEditDialog::on_forgeBtn_clicked() else { // install + QString forgePath = entry->getFullPath(); + ForgeInstaller forge(forgePath, forgeVersion->universal_url); + if (!forge.apply(m_version)) + { + // failure notice + } } } } -bool OneSixModEditDialog::loaderListFilter ( QKeyEvent* keyEvent ) +bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) { - case Qt::Key_Delete: - on_rmModBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addModBtn_clicked(); - return true; - default: - break; + 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 ); + return QDialog::eventFilter(ui->loaderModTreeView, keyEvent); } -bool OneSixModEditDialog::resourcePackListFilter ( QKeyEvent* keyEvent ) +bool OneSixModEditDialog::resourcePackListFilter(QKeyEvent *keyEvent) { - switch(keyEvent->key()) + switch (keyEvent->key()) { - case Qt::Key_Delete: - on_rmResPackBtn_clicked(); - return true; - case Qt::Key_Plus: - on_addResPackBtn_clicked(); - return true; - default: - break; + case Qt::Key_Delete: + on_rmResPackBtn_clicked(); + return true; + case Qt::Key_Plus: + on_addResPackBtn_clicked(); + return true; + default: + break; } - return QDialog::eventFilter( ui->resPackTreeView, keyEvent ); + return QDialog::eventFilter(ui->resPackTreeView, keyEvent); } - -bool OneSixModEditDialog::eventFilter ( QObject* obj, QEvent* ev ) +bool OneSixModEditDialog::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() != QEvent::KeyPress) { - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } - QKeyEvent *keyEvent = static_cast(ev); - if(obj == ui->loaderModTreeView) + QKeyEvent *keyEvent = static_cast(ev); + if (obj == ui->loaderModTreeView) return loaderListFilter(keyEvent); - if(obj == ui->resPackTreeView) + if (obj == ui->resPackTreeView) return resourcePackListFilter(keyEvent); - return QDialog::eventFilter( obj, ev ); + return QDialog::eventFilter(obj, ev); } void OneSixModEditDialog::on_buttonBox_rejected() @@ -207,8 +244,9 @@ void OneSixModEditDialog::on_buttonBox_rejected() void OneSixModEditDialog::on_addModBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods")); - for(auto filename:fileNames) + QStringList fileNames = QFileDialog::getOpenFileNames( + this, QApplication::translate("LegacyModEditDialog", "Select Loader Mods")); + for (auto filename : fileNames) { m_mods->stopWatching(); m_mods->installMod(QFileInfo(filename)); @@ -219,8 +257,8 @@ void OneSixModEditDialog::on_rmModBtn_clicked() { int first, last; auto list = ui->loaderModTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_mods->stopWatching(); m_mods->deleteMods(first, last); @@ -231,11 +269,11 @@ void OneSixModEditDialog::on_viewModBtn_clicked() openDirInDefaultProgram(m_inst->loaderModsDir(), true); } - void OneSixModEditDialog::on_addResPackBtn_clicked() { - QStringList fileNames = QFileDialog::getOpenFileNames(this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs")); - for(auto filename:fileNames) + QStringList fileNames = QFileDialog::getOpenFileNames( + this, QApplication::translate("LegacyModEditDialog", "Select Resource Packs")); + for (auto filename : fileNames) { m_resourcepacks->stopWatching(); m_resourcepacks->installMod(QFileInfo(filename)); @@ -246,8 +284,8 @@ void OneSixModEditDialog::on_rmResPackBtn_clicked() { int first, last; auto list = ui->resPackTreeView->selectionModel()->selectedRows(); - - if(!lastfirst(list, first, last)) + + if (!lastfirst(list, first, last)) return; m_resourcepacks->stopWatching(); m_resourcepacks->deleteMods(first, last); @@ -257,4 +295,3 @@ void OneSixModEditDialog::on_viewResPackBtn_clicked() { openDirInDefaultProgram(m_inst->resourcePacksDir(), true); } - diff --git a/gui/OneSixModEditDialog.h b/gui/OneSixModEditDialog.h index 714c911a..e70bd73f 100644 --- a/gui/OneSixModEditDialog.h +++ b/gui/OneSixModEditDialog.h @@ -44,7 +44,8 @@ private slots: void on_forgeBtn_clicked(); void on_customizeBtn_clicked(); void on_revertBtn_clicked(); - void updateButtons(); + void updateVersionControls(); + void disableVersionControls(); protected: bool eventFilter(QObject *obj, QEvent *ev); bool loaderListFilter( QKeyEvent* ev ); diff --git a/gui/instancedelegate.h b/gui/instancedelegate.h index c80f95a5..56bc34ba 100644 --- a/gui/instancedelegate.h +++ b/gui/instancedelegate.h @@ -9,4 +9,4 @@ public: protected: void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; -}; \ No newline at end of file +}; diff --git a/gui/lwjglselectdialog.cpp b/gui/lwjglselectdialog.cpp index 7c424a6c..e48bb975 100644 --- a/gui/lwjglselectdialog.cpp +++ b/gui/lwjglselectdialog.cpp @@ -26,10 +26,10 @@ LWJGLSelectDialog::LWJGLSelectDialog(QWidget *parent) : ui->setupUi(this); ui->labelStatus->setVisible(false); auto lwjgllist = MMC->lwjgllist(); - ui->lwjglListView->setModel(lwjgllist); + ui->lwjglListView->setModel(lwjgllist.data()); - connect(lwjgllist, SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool))); - connect(lwjgllist, SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString))); + connect(lwjgllist.data(), SIGNAL(loadingStateUpdated(bool)), SLOT(loadingStateUpdated(bool))); + connect(lwjgllist.data(), SIGNAL(loadListFailed(QString)), SLOT(loadingFailed(QString))); loadingStateUpdated(lwjgllist->isLoading()); } diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 6f707236..d3b167fa 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -124,7 +124,7 @@ MainWindow::MainWindow ( QWidget *parent ) //proxymodel->setDynamicSortFilter ( true ); // FIXME: instList should be global-ish, or at least not tied to the main window... maybe the application itself? - proxymodel->setSourceModel ( MMC->instances() ); + proxymodel->setSourceModel ( MMC->instances().data() ); proxymodel->sort ( 0 ); view->setFrameShape ( QFrame::NoFrame ); view->setModel ( proxymodel ); @@ -149,7 +149,7 @@ MainWindow::MainWindow ( QWidget *parent ) ); // model reset -> selection is invalid. All the instance pointers are wrong. // FIXME: stop using POINTERS everywhere - connect(MMC->instances() ,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); + connect(MMC->instances().data() ,SIGNAL(dataIsInvalid()),SLOT(selectionBad())); // run the things that load and download other things... FIXME: this is NOT the place // FIXME: invisible actions in the background = NOPE. @@ -601,7 +601,7 @@ void MainWindow::on_actionChangeInstMCVersion_triggered() if (view->selectionModel()->selectedIndexes().count() < 1) return; - VersionSelectDialog vselect(m_selectedInstance->versionList(), this); + VersionSelectDialog vselect(m_selectedInstance->versionList().data(), this); if (vselect.exec() && vselect.selectedVersion()) { m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor()); diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui index 4360f5f6..1cda7a34 100644 --- a/gui/mainwindow.ui +++ b/gui/mainwindow.ui @@ -440,7 +440,7 @@ Meow - <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnatok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> + <html><head/><body><p align="center"><span style=" font-weight:600; color:#ff0004;">Catnarok!</span></p><p align="center">Or just a cat with a ball of yarn?</p><p align="center"><span style=" font-style:italic;">WHO KNOWS?!</span></p><p align="center"><img src=":/icons/instances/tnt"/></p></body></html> diff --git a/gui/newinstancedialog.cpp b/gui/newinstancedialog.cpp index 6604d03b..859077d9 100644 --- a/gui/newinstancedialog.cpp +++ b/gui/newinstancedialog.cpp @@ -96,7 +96,7 @@ BaseVersionPtr NewInstanceDialog::selectedVersion() const void NewInstanceDialog::on_btnChangeVersion_clicked() { - VersionSelectDialog vselect(MMC->minecraftlist(), this); + VersionSelectDialog vselect(MMC->minecraftlist().data(), this); vselect.exec(); if (vselect.result() == QDialog::Accepted) { diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index a5283b36..9736c1c7 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -27,7 +27,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) : { ui->setupUi(this); - loadSettings(MMC->settings()); + loadSettings(MMC->settings().data()); updateCheckboxStuff(); } @@ -85,7 +85,7 @@ void SettingsDialog::on_maximizedCheckBox_clicked(bool checked) void SettingsDialog::on_buttonBox_accepted() { - applySettings(MMC->settings()); + applySettings(MMC->settings().data()); } void SettingsDialog::applySettings(SettingsObject *s) diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index 10bb4573..ec86596a 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -132,7 +132,7 @@ InstanceList *BaseInstance::instList() const return NULL; } -BaseVersionList *BaseInstance::versionList() const +QSharedPointer BaseInstance::versionList() const { return MMC->minecraftlist(); } diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index fa317ba1..374d1437 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -134,7 +134,7 @@ public: * \brief Gets a pointer to this instance's version list. * \return A pointer to the available version list for this instance. */ - virtual BaseVersionList *versionList() const; + virtual QSharedPointer versionList() const; /*! * \brief Gets this instance's settings object. diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp new file mode 100644 index 00000000..00ad8d19 --- /dev/null +++ b/logic/ForgeInstaller.cpp @@ -0,0 +1,125 @@ +#include "ForgeInstaller.h" +#include "OneSixVersion.h" +#include "OneSixLibrary.h" +#include +#include +#include +#include + +ForgeInstaller::ForgeInstaller(QString filename, QString universal_url) +{ + QSharedPointer newVersion; + m_universal_url = universal_url; + + QuaZip zip(filename); + if (!zip.open(QuaZip::mdUnzip)) + return; + + QuaZipFile file(&zip); + + // read the install profile + if (!zip.setCurrentFile("install_profile.json")) + return; + + QJsonParseError jsonError; + if (!file.open(QIODevice::ReadOnly)) + return; + QJsonDocument jsonDoc = QJsonDocument::fromJson(file.readAll(), &jsonError); + file.close(); + if (jsonError.error != QJsonParseError::NoError) + return; + + if (!jsonDoc.isObject()) + return; + + QJsonObject root = jsonDoc.object(); + + auto installVal = root.value("install"); + auto versionInfoVal = root.value("versionInfo"); + if (!installVal.isObject() || !versionInfoVal.isObject()) + return; + + // read the forge version info + { + newVersion = OneSixVersion::fromJson(versionInfoVal.toObject()); + if (!newVersion) + return; + } + + QJsonObject installObj = installVal.toObject(); + QString libraryName = installObj.value("path").toString(); + internalPath = installObj.value("filePath").toString(); + + // where do we put the library? decode the mojang path + OneSixLibrary lib(libraryName); + lib.finalize(); + finalPath = "libraries/" + lib.storagePath(); + if (!ensureFilePathExists(finalPath)) + return; + + if (!zip.setCurrentFile(internalPath)) + return; + if (!file.open(QIODevice::ReadOnly)) + return; + { + QByteArray data = file.readAll(); + // extract file + QSaveFile extraction(finalPath); + if (!extraction.open(QIODevice::WriteOnly)) + return; + if (extraction.write(data) != data.size()) + return; + if (!extraction.commit()) + return; + } + file.close(); + + m_forge_version = newVersion; + realVersionId = m_forge_version->id = installObj.value("minecraft").toString(); +} + +bool ForgeInstaller::apply(QSharedPointer to) +{ + if (!m_forge_version) + return false; + to->externalUpdateStart(); + int sliding_insert_window = 0; + { + // 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) + { + QString libName = lib->name(); + // if this is the actual forge lib, set an absolute url for the download + if(libName.contains("minecraftforge")) + { + lib->setAbsoluteUrl(m_universal_url); + } + if (blacklist.contains(libName)) + continue; + + // find an entry that matches this one + bool found = false; + for (auto tolib : to->libraries) + { + if (tolib->name() != libName) + continue; + found = true; + // replace lib + tolib = lib; + break; + } + if (!found) + { + // add lib + to->libraries.insert(sliding_insert_window, lib); + sliding_insert_window++; + } + } + to->mainClass = m_forge_version->mainClass; + to->minecraftArguments = m_forge_version->minecraftArguments; + to->processArguments = m_forge_version->processArguments; + } + to->externalUpdateFinish(); + return to->toOriginalFile(); +} diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h new file mode 100644 index 00000000..f4ceaaef --- /dev/null +++ b/logic/ForgeInstaller.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +class OneSixVersion; + +class ForgeInstaller +{ +public: + ForgeInstaller(QString filename, QString universal_url); + + bool apply(QSharedPointer to); + +private: + // the version, read from the installer + QSharedPointer m_forge_version; + QString internalPath; + QString finalPath; + QString realVersionId; + QString m_universal_url; +}; + + + + diff --git a/logic/LegacyUpdate.cpp b/logic/LegacyUpdate.cpp index 0f58e3e3..84d3d830 100644 --- a/logic/LegacyUpdate.cpp +++ b/logic/LegacyUpdate.cpp @@ -60,7 +60,7 @@ void LegacyUpdate::lwjglStart() m_reply = QSharedPointer (rep, &QObject::deleteLater); connect(rep, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); - connect(worker, SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); + connect(worker.data(), SIGNAL(finished(QNetworkReply*)), SLOT(lwjglFinished(QNetworkReply*))); //connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError))); } @@ -77,7 +77,7 @@ void LegacyUpdate::lwjglFinished(QNetworkReply* reply) "\nSometimes you have to wait a bit if you download many LWJGL versions in a row. YMMV"); return; } - auto *worker = MMC->qnam(); + auto worker = MMC->qnam(); //Here i check if there is a cookie for me in the reply and extract it QList cookies = qvariant_cast>(reply->header(QNetworkRequest::SetCookieHeader)); if(cookies.count() != 0) diff --git a/logic/ModList.h b/logic/ModList.h index 5395e9ae..e99b6c82 100644 --- a/logic/ModList.h +++ b/logic/ModList.h @@ -112,3 +112,6 @@ protected: QString m_list_id; QList mods; }; + + + diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 8124b4a0..9262b155 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -2,7 +2,7 @@ #include "OneSixInstance_p.h" #include "OneSixUpdate.h" #include "MinecraftProcess.h" -#include "VersionFactory.h" +#include "OneSixVersion.h" #include #include @@ -10,8 +10,9 @@ #include #include -OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting_obj, QObject* parent ) -: BaseInstance ( new OneSixInstancePrivate(), rootDir, setting_obj, parent ) +OneSixInstance::OneSixInstance(const QString &rootDir, SettingsObject *setting_obj, + QObject *parent) + : BaseInstance(new OneSixInstancePrivate(), rootDir, setting_obj, parent) { I_D(OneSixInstance); d->m_settings->registerSetting(new Setting("IntendedVersion", "")); @@ -19,7 +20,7 @@ OneSixInstance::OneSixInstance ( const QString& rootDir, SettingsObject* setting reloadFullVersion(); } -BaseUpdate* OneSixInstance::doUpdate() +BaseUpdate *OneSixInstance::doUpdate() { return new OneSixUpdate(this); } @@ -34,10 +35,10 @@ QString replaceTokensIn(QString text, QMap with) int head = 0; while ((head = token_regexp.indexIn(text, head)) != -1) { - result.append(text.mid(tail, head-tail)); + result.append(text.mid(tail, head - tail)); QString key = token_regexp.cap(1); auto iter = with.find(key); - if(iter != with.end()) + if (iter != with.end()) { result.append(*iter); } @@ -48,26 +49,26 @@ QString replaceTokensIn(QString text, QMap with) return result; } -QStringList OneSixInstance::processMinecraftArgs( QString user, QString session ) +QStringList OneSixInstance::processMinecraftArgs(QString user, QString session) { I_D(OneSixInstance); auto version = d->version; QString args_pattern = version->minecraftArguments; - + QMap token_mapping; token_mapping["auth_username"] = user; token_mapping["auth_session"] = session; - //FIXME: user and player name are DIFFERENT! + // FIXME: user and player name are DIFFERENT! token_mapping["auth_player_name"] = user; - //FIXME: WTF is this. I just plugged in a random UUID here. + // FIXME: WTF is this. I just plugged in a random UUID here. token_mapping["auth_uuid"] = "7d4bacf0-fd62-11e2-b778-0800200c9a66"; // obviously fake. - + // this is for offline: /* map["auth_player_name"] = "Player"; map["auth_player_name"] = "00000000-0000-0000-0000-000000000000"; */ - + token_mapping["profile_name"] = name(); token_mapping["version_name"] = version->id; @@ -75,8 +76,8 @@ QStringList OneSixInstance::processMinecraftArgs( QString user, QString session token_mapping["game_directory"] = absRootDir; QString absAssetsDir = QDir("assets/").absolutePath(); token_mapping["game_assets"] = absAssetsDir; - - QStringList parts = args_pattern.split(' ',QString::SkipEmptyParts); + + QStringList parts = args_pattern.split(' ', QString::SkipEmptyParts); for (int i = 0; i < parts.length(); i++) { parts[i] = replaceTokensIn(parts[i], token_mapping); @@ -84,27 +85,28 @@ QStringList OneSixInstance::processMinecraftArgs( QString user, QString session return parts; } -MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString session ) +MinecraftProcess *OneSixInstance::prepareForLaunch(QString user, QString session) { I_D(OneSixInstance); cleanupAfterRun(); auto version = d->version; - if(!version) + if (!version) return nullptr; auto libs_to_extract = version->getActiveNativeLibs(); QString natives_dir_raw = PathCombine(instanceRoot(), "natives/"); bool success = ensureFolderPathExists(natives_dir_raw); - if(!success) + if (!success) { // FIXME: handle errors return nullptr; } - - for(auto lib: libs_to_extract) + + for (auto lib : libs_to_extract) { QString path = "libraries/" + lib->storagePath(); qDebug() << "Will extract " << path.toLocal8Bit(); - if(JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes).isEmpty()) + if (JlCompress::extractWithExceptions(path, natives_dir_raw, lib->extract_excludes) + .isEmpty()) { return nullptr; } @@ -116,11 +118,11 @@ MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString sessi args << QString("-Xmx%1m").arg(settings().get("MaxMemAlloc").toInt()); args << QString("-XX:PermSize=%1m").arg(settings().get("PermGen").toInt()); QDir natives_dir(natives_dir_raw); - args << QString("-Djava.library.path=%1").arg( natives_dir.absolutePath() ); + args << QString("-Djava.library.path=%1").arg(natives_dir.absolutePath()); QString classPath; { auto libs = version->getActiveNormalLibs(); - for (auto lib: libs) + for (auto lib : libs) { QFileInfo fi(QString("libraries/") + lib->storagePath()); classPath.append(fi.absoluteFilePath()); @@ -134,16 +136,16 @@ MinecraftProcess* OneSixInstance::prepareForLaunch ( QString user, QString sessi QFileInfo fi(targetstr); classPath.append(fi.absoluteFilePath()); } - if(classPath.size()) + if (classPath.size()) { args << "-cp"; args << classPath; } args << version->mainClass; args.append(processMinecraftArgs(user, session)); - + // create the process and set its parameters - MinecraftProcess * proc = new MinecraftProcess(this); + MinecraftProcess *proc = new MinecraftProcess(this); proc->setMinecraftArguments(args); proc->setMinecraftWorkdir(minecraftRoot()); return proc; @@ -156,10 +158,10 @@ void OneSixInstance::cleanupAfterRun() dir.removeRecursively(); } -QSharedPointer< ModList > OneSixInstance::loaderModList() +QSharedPointer OneSixInstance::loaderModList() { I_D(OneSixInstance); - if(!d->loader_mod_list) + if (!d->loader_mod_list) { d->loader_mod_list.reset(new ModList(loaderModsDir())); } @@ -168,10 +170,10 @@ QSharedPointer< ModList > OneSixInstance::loaderModList() return d->loader_mod_list; } -QSharedPointer< ModList > OneSixInstance::resourcePackList() +QSharedPointer OneSixInstance::resourcePackList() { I_D(OneSixInstance); - if(!d->resource_pack_list) + if (!d->resource_pack_list) { d->resource_pack_list.reset(new ModList(resourcePacksDir())); } @@ -180,13 +182,12 @@ QSharedPointer< ModList > OneSixInstance::resourcePackList() return d->resource_pack_list; } - -QDialog * OneSixInstance::createModEditDialog ( QWidget* parent ) +QDialog *OneSixInstance::createModEditDialog(QWidget *parent) { return new OneSixModEditDialog(this, parent); } -bool OneSixInstance::setIntendedVersionId ( QString version ) +bool OneSixInstance::setIntendedVersionId(QString version) { settings().set("IntendedVersion", version); setShouldUpdate(true); @@ -198,16 +199,16 @@ QString OneSixInstance::intendedVersionId() const return settings().get("IntendedVersion").toString(); } -void OneSixInstance::setShouldUpdate ( bool val ) +void OneSixInstance::setShouldUpdate(bool val) { - settings().set ( "ShouldUpdate", val ); + settings().set("ShouldUpdate", val); } bool OneSixInstance::shouldUpdate() const { I_D(OneSixInstance); - QVariant var = settings().get ( "ShouldUpdate" ); - if ( !var.isValid() || var.toBool() == false ) + QVariant var = settings().get("ShouldUpdate"); + if (!var.isValid() || var.toBool() == false) { return intendedVersionId() != currentVersionId(); } @@ -228,56 +229,51 @@ QString OneSixInstance::currentVersionId() const bool OneSixInstance::customizeVersion() { - if(!versionIsCustom()) + if (!versionIsCustom()) { auto pathCustom = PathCombine(instanceRoot(), "custom.json"); auto pathOrig = PathCombine(instanceRoot(), "version.json"); QFile::copy(pathOrig, pathCustom); return reloadFullVersion(); } - else return true; + else + return true; } bool OneSixInstance::revertCustomVersion() { - if(versionIsCustom()) + if (versionIsCustom()) { auto path = PathCombine(instanceRoot(), "custom.json"); QFile::remove(path); return reloadFullVersion(); } - else return true; + else + return true; } - bool OneSixInstance::reloadFullVersion() { I_D(OneSixInstance); - + QString verpath = PathCombine(instanceRoot(), "version.json"); { QString verpath_custom = PathCombine(instanceRoot(), "custom.json"); QFile versionfile(verpath_custom); - if(versionfile.exists()) + if (versionfile.exists()) verpath = verpath_custom; } - - QFile versionfile(verpath); - if(versionfile.exists() && versionfile.open(QIODevice::ReadOnly)) + + auto version = OneSixVersion::fromFile(verpath); + if (version) { - FullVersionFactory fvf; - auto version = fvf.parse(versionfile.readAll()); - versionfile.close(); - if(version) - { - d->version = version; - return true; - } - }; + d->version = version; + return true; + } return false; } -QSharedPointer< OneSixVersion > OneSixInstance::getFullVersion() +QSharedPointer OneSixInstance::getFullVersion() { I_D(OneSixInstance); return d->version; @@ -293,9 +289,9 @@ QString OneSixInstance::defaultCustomBaseJar() const return PathCombine(instanceRoot(), "custom.jar"); } -bool OneSixInstance::menuActionEnabled ( QString action_name ) const +bool OneSixInstance::menuActionEnabled(QString action_name) const { - if(action_name == "actionChangeInstLWJGLVersion") + if (action_name == "actionChangeInstLWJGLVersion") return false; return true; } @@ -303,7 +299,7 @@ bool OneSixInstance::menuActionEnabled ( QString action_name ) const QString OneSixInstance::getStatusbarDescription() { QString descr = "One Six : " + intendedVersionId(); - if(versionIsCustom()) + if (versionIsCustom()) { descr + " (custom)"; } diff --git a/logic/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp index a45a4aec..8da1fde7 100644 --- a/logic/OneSixLibrary.cpp +++ b/logic/OneSixLibrary.cpp @@ -1,18 +1,19 @@ #include "OneSixLibrary.h" #include "OneSixRule.h" #include "OpSys.h" +#include void OneSixLibrary::finalize() { - QStringList parts = m_name.split ( ':' ); + QStringList parts = m_name.split(':'); QString relative = parts[0]; - relative.replace ( '.','/' ); + relative.replace('.', '/'); relative += '/' + parts[1] + '/' + parts[2] + '/' + parts[1] + '-' + parts[2]; - - if ( !m_is_native ) + + if (!m_is_native) relative += ".jar"; else { - if ( m_native_suffixes.contains ( currentSystem ) ) + if (m_native_suffixes.contains(currentSystem)) { relative += "-" + m_native_suffixes[currentSystem] + ".jar"; } @@ -22,30 +23,30 @@ void OneSixLibrary::finalize() relative += ".jar"; } } - + m_decentname = parts[1]; m_decentversion = parts[2]; m_storage_path = relative; - m_download_path = m_base_url + relative; - - if ( m_rules.empty() ) + m_download_url = m_base_url + relative; + + if (m_rules.empty()) { m_is_active = true; } else { RuleAction result = Disallow; - for ( auto rule: m_rules ) + for (auto rule : m_rules) { - RuleAction temp = rule->apply ( this ); - if ( temp != Defer ) + RuleAction temp = rule->apply(this); + if (temp != Defer) result = temp; } - m_is_active = ( result == Allow ); + m_is_active = (result == Allow); } - if ( m_is_native ) + if (m_is_native) { - m_is_active = m_is_active && m_native_suffixes.contains ( currentSystem ); + m_is_active = m_is_active && m_native_suffixes.contains(currentSystem); m_decenttype = "Native"; } else @@ -54,11 +55,11 @@ void OneSixLibrary::finalize() } } -void OneSixLibrary::setName ( QString name ) +void OneSixLibrary::setName(QString name) { m_name = name; } -void OneSixLibrary::setBaseUrl ( QString base_url ) +void OneSixLibrary::setBaseUrl(QString base_url) { m_base_url = base_url; } @@ -66,12 +67,12 @@ void OneSixLibrary::setIsNative() { m_is_native = true; } -void OneSixLibrary::addNative ( OpSys os, QString suffix ) +void OneSixLibrary::addNative(OpSys os, QString suffix) { m_is_native = true; m_native_suffixes[os] = suffix; } -void OneSixLibrary::setRules ( QList< QSharedPointer< Rule > > rules ) +void OneSixLibrary::setRules(QList> rules) { m_rules = rules; } @@ -83,11 +84,66 @@ bool OneSixLibrary::isNative() { return m_is_native; } -QString OneSixLibrary::downloadPath() +QString OneSixLibrary::downloadUrl() { - return m_download_path; + if(m_absolute_url.size()) + return m_absolute_url; + return m_download_url; } QString OneSixLibrary::storagePath() { return m_storage_path; } + +void OneSixLibrary::setAbsoluteUrl(QString absolute_url) +{ + m_absolute_url = absolute_url; +} + +QString OneSixLibrary::absoluteUrl() +{ + return m_absolute_url; +} + +QJsonObject OneSixLibrary::toJson() +{ + QJsonObject libRoot; + libRoot.insert("name", m_name); + if(m_absolute_url.size()) + libRoot.insert("MMC-absulute_url", m_absolute_url); + if(m_base_url != "https://s3.amazonaws.com/Minecraft.Download/libraries/") + libRoot.insert("url", m_base_url); + if (isNative() && m_native_suffixes.size()) + { + QJsonObject nativeList; + auto iter = m_native_suffixes.begin(); + while (iter != m_native_suffixes.end()) + { + nativeList.insert(OpSys_toString(iter.key()), iter.value()); + iter++; + } + libRoot.insert("natives", nativeList); + } + if (isNative() && extract_excludes.size()) + { + QJsonArray excludes; + QJsonObject extract; + for (auto exclude : extract_excludes) + { + excludes.append(exclude); + } + extract.insert("exclude", excludes); + libRoot.insert("extract", extract); + } + if (m_rules.size()) + { + QJsonArray allRules; + for (auto &rule : m_rules) + { + QJsonObject ruleObj = rule->toJson(); + allRules.append(ruleObj); + } + libRoot.insert("rules", allRules); + } + return libRoot; +} diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h index ac16d3d3..f3106483 100644 --- a/logic/OneSixLibrary.h +++ b/logic/OneSixLibrary.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "OpSys.h" class Rule; @@ -12,9 +13,13 @@ class OneSixLibrary private: // basic values used internally (so far) QString m_name; - QString m_base_url; + QString m_base_url = "https://s3.amazonaws.com/Minecraft.Download/libraries/"; QList > m_rules; - + + // custom values + /// absolute URL. takes precedence over m_download_path, if defined + QString m_absolute_url; + // derived values used for real things /// a decent name fit for display QString m_decentname; @@ -25,11 +30,11 @@ private: /// where to store the lib locally QString m_storage_path; /// where to download the lib from - QString m_download_path; + QString m_download_url; /// is this lib actually active on the current OS? - bool m_is_active; + bool m_is_active = false; /// is the library a native? - bool m_is_native; + bool m_is_native = false; /// native suffixes per OS QMap m_native_suffixes; public: @@ -39,12 +44,11 @@ public: /// Constructor OneSixLibrary(QString name) { - m_is_native = false; - m_is_active = false; m_name = name; - m_base_url = "https://s3.amazonaws.com/Minecraft.Download/libraries/"; } + QJsonObject toJson(); + /** * finalize the library, processing the input values into derived values and state * @@ -84,7 +88,11 @@ public: /// Returns true if the library is native bool isNative(); /// Get the URL to download the library from - QString downloadPath(); + QString downloadUrl(); /// Get the relative path where the library should be saved QString storagePath(); + + /// set an absolute URL for the library. This is an MMC extension. + void setAbsoluteUrl(QString absolute_url); + QString absoluteUrl(); }; diff --git a/logic/OneSixRule.cpp b/logic/OneSixRule.cpp index 85f7d434..545cd641 100644 --- a/logic/OneSixRule.cpp +++ b/logic/OneSixRule.cpp @@ -1,10 +1,72 @@ #include "OneSixRule.h" +#include +#include + +QList> rulesFromJsonV4(QJsonObject &objectWithRules) +{ + QList> rules; + auto rulesVal = objectWithRules.value("rules"); + if (!rulesVal.isArray()) + return rules; + + QJsonArray ruleList = rulesVal.toArray(); + for (auto ruleVal : ruleList) + { + QSharedPointer rule; + if (!ruleVal.isObject()) + continue; + auto ruleObj = ruleVal.toObject(); + auto actionVal = ruleObj.value("action"); + if (!actionVal.isString()) + continue; + auto action = RuleAction_fromString(actionVal.toString()); + if (action == Defer) + continue; + + auto osVal = ruleObj.value("os"); + if (!osVal.isObject()) + { + // add a new implicit action rule + rules.append(ImplicitRule::create(action)); + continue; + } + + auto osObj = osVal.toObject(); + auto osNameVal = osObj.value("name"); + if (!osNameVal.isString()) + continue; + OpSys requiredOs = OpSys_fromString(osNameVal.toString()); + QString versionRegex = osObj.value("version").toString(); + // add a new OS rule + rules.append(OsRule::create(action, requiredOs, versionRegex)); + } +} + +QJsonObject ImplicitRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + return ruleObj; +} + +QJsonObject OsRule::toJson() +{ + QJsonObject ruleObj; + ruleObj.insert("action", m_result == Allow ? QString("allow") : QString("disallow")); + QJsonObject osObj; + { + osObj.insert("name", OpSys_toString(m_system)); + osObj.insert("version", m_version_regexp); + } + ruleObj.insert("os", osObj); + return ruleObj; +} RuleAction RuleAction_fromString(QString name) { - if(name == "allow") + if (name == "allow") return Allow; - if(name == "disallow") + if (name == "disallow") return Disallow; return Defer; } \ No newline at end of file diff --git a/logic/OneSixRule.h b/logic/OneSixRule.h index 465c963f..23d20ff4 100644 --- a/logic/OneSixRule.h +++ b/logic/OneSixRule.h @@ -1,8 +1,6 @@ #pragma once #include #include - -class OneSixLibrary; #include "OneSixLibrary.h" enum RuleAction @@ -13,6 +11,7 @@ enum RuleAction }; RuleAction RuleAction_fromString(QString); +QList> rulesFromJsonV4(QJsonObject &objectWithRules); class Rule { @@ -23,6 +22,7 @@ public: Rule(RuleAction result) :m_result(result) {} virtual ~Rule(){}; + virtual QJsonObject toJson() = 0; RuleAction apply(OneSixLibrary * parent) { if(applies(parent)) @@ -47,6 +47,7 @@ protected: OsRule(RuleAction result, OpSys system, QString version_regexp) : Rule(result), m_system(system), m_version_regexp(version_regexp) {} public: + virtual QJsonObject toJson(); static QSharedPointer create(RuleAction result, OpSys system, QString version_regexp) { return QSharedPointer (new OsRule(result, system, version_regexp)); @@ -63,6 +64,7 @@ protected: ImplicitRule(RuleAction result) : Rule(result) {} public: + virtual QJsonObject toJson(); static QSharedPointer create(RuleAction result) { return QSharedPointer (new ImplicitRule(result)); diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp index 298ad28a..d0af8b93 100644 --- a/logic/OneSixUpdate.cpp +++ b/logic/OneSixUpdate.cpp @@ -3,7 +3,7 @@ * 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 @@ -26,20 +26,20 @@ #include "BaseInstance.h" #include "lists/MinecraftVersionList.h" -#include "VersionFactory.h" #include "OneSixVersion.h" #include "OneSixLibrary.h" #include "OneSixInstance.h" #include "pathutils.h" - -OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent):BaseUpdate(inst, parent){} +OneSixUpdate::OneSixUpdate(BaseInstance *inst, QObject *parent) : BaseUpdate(inst, parent) +{ +} void OneSixUpdate::executeTask() { QString intendedVersion = m_inst->intendedVersionId(); - + // Make directories QDir mcDir(m_inst->minecraftRoot()); if (!mcDir.exists() && !mcDir.mkpath(".")) @@ -47,17 +47,18 @@ void OneSixUpdate::executeTask() emitFailed("Failed to create bin folder."); return; } - + // Get a pointer to the version object that corresponds to the instance's version. - targetVersion = MMC->minecraftlist()->findVersion(intendedVersion).dynamicCast(); - if(targetVersion == nullptr) + targetVersion = + MMC->minecraftlist()->findVersion(intendedVersion).dynamicCast(); + if (targetVersion == nullptr) { // don't do anything if it was invalid emitSucceeded(); return; } - - if(m_inst->shouldUpdate()) + + if (m_inst->shouldUpdate()) { versionFileStart(); } @@ -70,62 +71,65 @@ void OneSixUpdate::executeTask() void OneSixUpdate::versionFileStart() { setStatus("Getting the version files from Mojang."); - + QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += targetVersion->descriptor() + "/" + targetVersion->descriptor() + ".json"; auto job = new DownloadJob("Version index"); job->add(QUrl(urlstr)); specificVersionDownloadJob.reset(job); - connect(specificVersionDownloadJob.data(), SIGNAL(succeeded()), SLOT(versionFileFinished())); + connect(specificVersionDownloadJob.data(), SIGNAL(succeeded()), + SLOT(versionFileFinished())); connect(specificVersionDownloadJob.data(), SIGNAL(failed()), SLOT(versionFileFailed())); - connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); + connect(specificVersionDownloadJob.data(), SIGNAL(progress(qint64, qint64)), + SIGNAL(progress(qint64, qint64))); specificVersionDownloadJob->start(); } void OneSixUpdate::versionFileFinished() { DownloadPtr DlJob = specificVersionDownloadJob->first(); - OneSixInstance * inst = (OneSixInstance *) m_inst; - + OneSixInstance *inst = (OneSixInstance *)m_inst; + QString version_id = targetVersion->descriptor(); QString inst_dir = m_inst->instanceRoot(); // save the version file in $instanceId/version.json { - QString version1 = PathCombine(inst_dir, "/version.json"); + QString version1 = PathCombine(inst_dir, "/version.json"); ensureFilePathExists(version1); // FIXME: detect errors here, download to a temp file, swap - QSaveFile vfile1 (version1); - if(!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly )) + QSaveFile vfile1(version1); + if (!vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly)) { emitFailed("Can't open " + version1 + " for writing."); return; } auto data = DlJob.dynamicCast()->m_data; qint64 actual = 0; - if((actual = vfile1.write(data)) != data.size()) + if ((actual = vfile1.write(data)) != data.size()) { - emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " + data.size() + '.'); + emitFailed("Failed to write into " + version1 + ". Written " + actual + " out of " + + data.size() + '.'); return; } - if(!vfile1.commit()) + if (!vfile1.commit()) { emitFailed("Can't commit changes to " + version1); return; } } - + // the version is downloaded safely. update is 'done' at this point m_inst->setShouldUpdate(false); - + // delete any custom version inside the instance (it's no longer relevant, we did an update) - QString custom = PathCombine(inst_dir, "/custom.json"); + QString custom = PathCombine(inst_dir, "/custom.json"); QFile finfo(custom); - if(finfo.exists()) + if (finfo.exists()) { finfo.remove(); } inst->reloadFullVersion(); - + jarlibStart(); } @@ -136,42 +140,44 @@ void OneSixUpdate::versionFileFailed() void OneSixUpdate::jarlibStart() { - OneSixInstance * inst = (OneSixInstance *) m_inst; + OneSixInstance *inst = (OneSixInstance *)m_inst; bool successful = inst->reloadFullVersion(); - if(!successful) + if (!successful) { - emitFailed("Failed to load the version description file (version.json). It might be corrupted, missing or simply too new."); + emitFailed("Failed to load the version description file (version.json). It might be " + "corrupted, missing or simply too new."); return; } - + QSharedPointer version = inst->getFullVersion(); - + // download the right jar, save it in versions/$version/$version.jar QString urlstr("http://s3.amazonaws.com/Minecraft.Download/versions/"); urlstr += version->id + "/" + version->id + ".jar"; - QString targetstr ("versions/"); + QString targetstr("versions/"); targetstr += version->id + "/" + version->id + ".jar"; - + auto job = new DownloadJob("Libraries for instance " + inst->name()); job->add(QUrl(urlstr), targetstr); jarlibDownloadJob.reset(job); - + auto libs = version->getActiveNativeLibs(); libs.append(version->getActiveNormalLibs()); - + auto metacache = MMC->metacache(); - for(auto lib: libs) + for (auto lib : libs) { - QString download_path = lib->downloadPath(); + QString download_path = lib->downloadUrl(); auto entry = metacache->resolveEntry("libraries", lib->storagePath()); - if(entry->stale) + if (entry->stale) { jarlibDownloadJob->add(download_path, entry); } } connect(jarlibDownloadJob.data(), SIGNAL(succeeded()), SLOT(jarlibFinished())); connect(jarlibDownloadJob.data(), SIGNAL(failed()), SLOT(jarlibFailed())); - connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64))); + connect(jarlibDownloadJob.data(), SIGNAL(progress(qint64, qint64)), + SIGNAL(progress(qint64, qint64))); jarlibDownloadJob->start(); } @@ -185,4 +191,3 @@ void OneSixUpdate::jarlibFailed() { emitFailed("Failed to download the binary garbage. Try again. Maybe. IF YOU DARE"); } - diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp index dc1b5d6f..663d903a 100644 --- a/logic/OneSixVersion.cpp +++ b/logic/OneSixVersion.cpp @@ -1,10 +1,201 @@ #include "OneSixVersion.h" #include "OneSixLibrary.h" +#include "OneSixRule.h" -QList > OneSixVersion::getActiveNormalLibs() +QSharedPointer fromJsonV4(QJsonObject root, + QSharedPointer fullVersion) { - QList > output; - for ( auto lib: libraries ) + fullVersion->id = root.value("id").toString(); + + fullVersion->mainClass = root.value("mainClass").toString(); + auto procArgsValue = root.value("processArguments"); + if (procArgsValue.isString()) + { + fullVersion->processArguments = procArgsValue.toString(); + QString toCompare = fullVersion->processArguments.toLower(); + if (toCompare == "legacy") + { + fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}"; + } + else if (toCompare == "username_session") + { + fullVersion->minecraftArguments = + "--username ${auth_player_name} --session ${auth_session}"; + } + else if (toCompare == "username_session_version") + { + fullVersion->minecraftArguments = "--username ${auth_player_name} " + "--session ${auth_session} " + "--version ${profile_name}"; + } + } + + auto minecraftArgsValue = root.value("minecraftArguments"); + if (minecraftArgsValue.isString()) + { + fullVersion->minecraftArguments = minecraftArgsValue.toString(); + } + + auto minecraftTypeValue = root.value("type"); + if (minecraftTypeValue.isString()) + { + fullVersion->type = minecraftTypeValue.toString(); + } + + fullVersion->releaseTime = root.value("releaseTime").toString(); + fullVersion->time = root.value("time").toString(); + + // Iterate through the list, if it's a list. + auto librariesValue = root.value("libraries"); + if (!librariesValue.isArray()) + return fullVersion; + + QJsonArray libList = root.value("libraries").toArray(); + for (auto libVal : libList) + { + if (!libVal.isObject()) + { + continue; + } + + QJsonObject libObj = libVal.toObject(); + + // Library name + auto nameVal = libObj.value("name"); + if (!nameVal.isString()) + continue; + QSharedPointer library(new OneSixLibrary(nameVal.toString())); + + auto urlVal = libObj.value("url"); + if (urlVal.isString()) + { + library->setBaseUrl(urlVal.toString()); + } + auto urlAbsVal = libObj.value("MMC-absulute_url"); + if (urlAbsVal.isString()) + { + library->setAbsoluteUrl(urlAbsVal.toString()); + } + // Extract excludes (if any) + auto extractVal = libObj.value("extract"); + if (extractVal.isObject()) + { + QStringList excludes; + auto extractObj = extractVal.toObject(); + auto excludesVal = extractObj.value("exclude"); + if (excludesVal.isArray()) + { + auto excludesList = excludesVal.toArray(); + for (auto excludeVal : excludesList) + { + if (excludeVal.isString()) + excludes.append(excludeVal.toString()); + } + library->extract_excludes = excludes; + } + } + + auto nativesVal = libObj.value("natives"); + if (nativesVal.isObject()) + { + library->setIsNative(); + auto nativesObj = nativesVal.toObject(); + auto iter = nativesObj.begin(); + while (iter != nativesObj.end()) + { + auto osType = OpSys_fromString(iter.key()); + if (osType == Os_Other) + continue; + if (!iter.value().isString()) + continue; + library->addNative(osType, iter.value().toString()); + iter++; + } + } + library->setRules(rulesFromJsonV4(libObj)); + library->finalize(); + fullVersion->libraries.append(library); + } + return fullVersion; +} + +QSharedPointer OneSixVersion::fromJson(QJsonObject root) +{ + QSharedPointer readVersion(new OneSixVersion()); + int launcher_ver = readVersion->minimumLauncherVersion = + root.value("minimumLauncherVersion").toDouble(); + + // ADD MORE HERE :D + if (launcher_ver > 0 && launcher_ver <= 7) + return fromJsonV4(root, readVersion); + else + { + return QSharedPointer(); + } +} + +QSharedPointer OneSixVersion::fromFile(QString filepath) +{ + QFile file(filepath); + if (!file.open(QIODevice::ReadOnly)) + { + return QSharedPointer(); + } + + auto data = file.readAll(); + QJsonParseError jsonError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); + + if (jsonError.error != QJsonParseError::NoError) + { + return QSharedPointer(); + } + + if (!jsonDoc.isObject()) + { + return QSharedPointer(); + } + QJsonObject root = jsonDoc.object(); + auto version = fromJson(root); + version->original_file = filepath; + return version; +} + +bool OneSixVersion::toOriginalFile() +{ + if (original_file.isEmpty()) + return false; + QSaveFile file(original_file); + if (!file.open(QIODevice::WriteOnly)) + { + return false; + } + // serialize base attributes (those we care about anyway) + QJsonObject root; + root.insert("minecraftArguments", minecraftArguments); + root.insert("mainClass", mainClass); + root.insert("minimumLauncherVersion", minimumLauncherVersion); + root.insert("time", time); + root.insert("id", id); + root.insert("type", type); + // screw processArguments + root.insert("releaseTime", releaseTime); + QJsonArray libarray; + for(const auto & lib: libraries) + { + libarray.append(lib->toJson()); + } + if(libarray.count()) + root.insert("libraries", libarray); + QJsonDocument doc(root); + file.write(doc.toJson()); + return file.commit(); +} + +QList> OneSixVersion::getActiveNormalLibs() +{ + QList> output; + for (auto lib : libraries) { if (lib->isActive() && !lib->isNative()) { @@ -14,10 +205,10 @@ QList > OneSixVersion::getActiveNormalLibs() return output; } -QList > OneSixVersion::getActiveNativeLibs() +QList> OneSixVersion::getActiveNativeLibs() { - QList > output; - for ( auto lib: libraries ) + QList> output; + for (auto lib : libraries) { if (lib->isActive() && lib->isNative()) { @@ -27,41 +218,50 @@ QList > OneSixVersion::getActiveNativeLibs() return output; } - -QVariant OneSixVersion::data(const QModelIndex& index, int role) const +void OneSixVersion::externalUpdateStart() { - if(!index.isValid()) + beginResetModel(); +} + +void OneSixVersion::externalUpdateFinish() +{ + endResetModel(); +} + +QVariant OneSixVersion::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) return QVariant(); - + int row = index.row(); int column = index.column(); - - if(row < 0 || row >= libraries.size()) + + if (row < 0 || row >= libraries.size()) return QVariant(); - - if(role == Qt::DisplayRole) + + if (role == Qt::DisplayRole) { - switch(column) + switch (column) { - case 0: - return libraries[row]->name(); - case 1: - return libraries[row]->type(); - case 2: - return libraries[row]->version(); - default: - return QVariant(); + case 0: + return libraries[row]->name(); + case 1: + return libraries[row]->type(); + case 2: + return libraries[row]->version(); + default: + return QVariant(); } } return QVariant(); } -Qt::ItemFlags OneSixVersion::flags(const QModelIndex& index) const +Qt::ItemFlags OneSixVersion::flags(const QModelIndex &index) const { - if(!index.isValid()) + if (!index.isValid()) return Qt::NoItemFlags; int row = index.row(); - if(libraries[row]->isActive()) + if (libraries[row]->isActive()) { return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren; } @@ -69,11 +269,10 @@ Qt::ItemFlags OneSixVersion::flags(const QModelIndex& index) const { return Qt::ItemNeverHasChildren; } - //return QAbstractListModel::flags(index); + // return QAbstractListModel::flags(index); } - -QVariant OneSixVersion::headerData ( int section, Qt::Orientation orientation, int role ) const +QVariant OneSixVersion::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); @@ -90,12 +289,12 @@ QVariant OneSixVersion::headerData ( int section, Qt::Orientation orientation, i } } -int OneSixVersion::rowCount(const QModelIndex& parent) const +int OneSixVersion::rowCount(const QModelIndex &parent) const { return libraries.size(); } -int OneSixVersion::columnCount(const QModelIndex& parent) const +int OneSixVersion::columnCount(const QModelIndex &parent) const { - return 3; + return 3; } diff --git a/logic/OneSixVersion.h b/logic/OneSixVersion.h index 6a6a5b4b..69268ecf 100644 --- a/logic/OneSixVersion.h +++ b/logic/OneSixVersion.h @@ -4,13 +4,33 @@ class OneSixLibrary; class OneSixVersion : public QAbstractListModel { + // Things required to implement the Qt list model public: - virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const; - virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const; - virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; - virtual int columnCount ( const QModelIndex& parent ) const; - virtual Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + virtual int columnCount(const QModelIndex &parent) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + + // serialization/deserialization public: + bool toOriginalFile(); + static QSharedPointer fromJson(QJsonObject root); + static QSharedPointer fromFile(QString filepath); + +public: + QList> getActiveNormalLibs(); + QList> getActiveNativeLibs(); + // called when something starts/stops messing with the object + // FIXME: these are ugly in every possible way. + void externalUpdateStart(); + void externalUpdateFinish(); + + // data members +public: + /// file this was read from. blank, if none + QString original_file; /// the ID - determines which jar to use! ACTUALLY IMPORTANT! QString id; /// Last updated time - as a string @@ -23,26 +43,27 @@ public: * DEPRECATED: Old versions of the new vanilla launcher used this * ex: "username_session_version" */ - QString processArguments; + QString processArguments; /** * arguments that should be used for launching minecraft - * + * * ex: "--username ${auth_player_name} --session ${auth_session} * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" */ QString minecraftArguments; /** - * the minimum launcher version required by this version ... current is 4 (at point of writing) + * the minimum launcher version required by this version ... current is 4 (at point of + * writing) */ - int minimumLauncherVersion; + int minimumLauncherVersion = 0xDEADBEEF; /** * The main class to load first */ QString mainClass; - + /// the list of libs - both active and inactive, native and java - QList > libraries; - + QList> libraries; + /* FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. @@ -58,18 +79,11 @@ public: } } ], - "incompatibilityReason": "There is a bug in LWJGL which makes it incompatible with OSX 10.5.8. Please go to New Profile and use 1.5.2 for now. Sorry!" + "incompatibilityReason": "There is a bug in LWJGL which makes it incompatible with OSX + 10.5.8. Please go to New Profile and use 1.5.2 for now. Sorry!" } */ // QList rules; - -public: - - OneSixVersion() - { - minimumLauncherVersion = 0xDEADBEEF; - } - - QList > getActiveNormalLibs(); - QList > getActiveNativeLibs(); + + }; diff --git a/logic/OpSys.cpp b/logic/OpSys.cpp index 559479fd..f101fd08 100644 --- a/logic/OpSys.cpp +++ b/logic/OpSys.cpp @@ -9,4 +9,15 @@ OpSys OpSys_fromString(QString name) if(name == "osx") return Os_OSX; return Os_Other; +} + +QString OpSys_toString(OpSys name) +{ + switch(name) + { + case Os_Linux: return "linux"; + case Os_OSX: return "osx"; + case Os_Windows: return "windows"; + default: return "other"; + } } \ No newline at end of file diff --git a/logic/OpSys.h b/logic/OpSys.h index c68c437a..aaa2eb65 100644 --- a/logic/OpSys.h +++ b/logic/OpSys.h @@ -9,6 +9,7 @@ enum OpSys }; OpSys OpSys_fromString(QString); +QString OpSys_toString(OpSys); #ifdef Q_OS_WIN32 #define currentSystem Os_Windows diff --git a/logic/VersionFactory.cpp b/logic/VersionFactory.cpp deleted file mode 100644 index 4fa5ad3f..00000000 --- a/logic/VersionFactory.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "VersionFactory.h" -#include "OneSixVersion.h" -#include "OneSixRule.h" - -// Library rules (if any) -QList > FullVersionFactory::parse4rules(QJsonObject & baseObj) -{ - QList > rules; - auto rulesVal = baseObj.value("rules"); - if(rulesVal.isArray()) - { - QJsonArray ruleList = rulesVal.toArray(); - for(auto ruleVal : ruleList) - { - QSharedPointer rule; - if(!ruleVal.isObject()) - continue; - auto ruleObj = ruleVal.toObject(); - auto actionVal = ruleObj.value("action"); - if(!actionVal.isString()) - continue; - auto action = RuleAction_fromString(actionVal.toString()); - if(action == Defer) - continue; - - auto osVal = ruleObj.value("os"); - if(!osVal.isObject()) - { - // add a new implicit action rule - rules.append(ImplicitRule::create(action)); - } - else - { - auto osObj = osVal.toObject(); - auto osNameVal = osObj.value("name"); - if(!osNameVal.isString()) - continue; - OpSys requiredOs = OpSys_fromString(osNameVal.toString()); - QString versionRegex = osObj.value("version").toString(); - // add a new OS rule - rules.append(OsRule::create(action, requiredOs, versionRegex)); - } - } - } - return rules; -} - - -QSharedPointer FullVersionFactory::parse4(QJsonObject root, QSharedPointer fullVersion) -{ - fullVersion->id = root.value("id").toString(); - - fullVersion->mainClass = root.value("mainClass").toString(); - auto procArgsValue = root.value("processArguments"); - if(procArgsValue.isString()) - { - fullVersion->processArguments = procArgsValue.toString(); - QString toCompare = fullVersion->processArguments.toLower(); - if(toCompare == "legacy") - { - fullVersion->minecraftArguments = " ${auth_player_name} ${auth_session}"; - } - else if(toCompare == "username_session") - { - fullVersion->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}"; - } - else if(toCompare == "username_session_version") - { - fullVersion->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}"; - } - } - - auto minecraftArgsValue = root.value("minecraftArguments"); - if(minecraftArgsValue.isString()) - { - fullVersion->minecraftArguments = minecraftArgsValue.toString(); - } - - auto minecraftTypeValue = root.value("type"); - if(minecraftTypeValue.isString()) - { - fullVersion->type = minecraftTypeValue.toString(); - } - - fullVersion->releaseTime = root.value("releaseTime").toString(); - fullVersion->time = root.value("time").toString(); - - // Iterate through the list, if it's a list. - auto librariesValue = root.value("libraries"); - if(!librariesValue.isArray()) - return fullVersion; - - QJsonArray libList = root.value("libraries").toArray(); - for (auto libVal : libList) - { - if (!libVal.isObject()) - { - continue; - } - - QJsonObject libObj = libVal.toObject(); - - // Library name - auto nameVal = libObj.value("name"); - if(!nameVal.isString()) - continue; - QSharedPointer library(new OneSixLibrary(nameVal.toString())); - - auto urlVal = libObj.value("url"); - if(urlVal.isString()) - { - library->setBaseUrl(urlVal.toString()); - } - - // Extract excludes (if any) - auto extractVal = libObj.value("extract"); - if(extractVal.isObject()) - { - QStringList excludes; - auto extractObj = extractVal.toObject(); - auto excludesVal = extractObj.value("exclude"); - if(!excludesVal.isArray()) - goto SKIP_EXTRACTS; - auto excludesList = excludesVal.toArray(); - for(auto excludeVal : excludesList) - { - if(excludeVal.isString()) - excludes.append(excludeVal.toString()); - } - library->extract_excludes = excludes; - } - SKIP_EXTRACTS: - - auto nativesVal = libObj.value("natives"); - if(nativesVal.isObject()) - { - library->setIsNative(); - auto nativesObj = nativesVal.toObject(); - auto iter = nativesObj.begin(); - while(iter != nativesObj.end()) - { - auto osType = OpSys_fromString(iter.key()); - if(osType == Os_Other) - continue; - if(!iter.value().isString()) - continue; - library->addNative(osType, iter.value().toString()); - iter++; - } - } - library->setRules(parse4rules(libObj)); - library->finalize(); - fullVersion->libraries.append(library); - } - return fullVersion; -} - -QSharedPointer FullVersionFactory::parse(QByteArray data) -{ - QSharedPointer readVersion(new OneSixVersion()); - - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - - if (jsonError.error != QJsonParseError::NoError) - { - error_string = QString( "Error reading version file :") + " " + jsonError.errorString(); - m_error = FullVersionFactory::ParseError; - return QSharedPointer(); - } - - if(!jsonDoc.isObject()) - { - error_string = "Error reading version file."; - m_error = FullVersionFactory::ParseError; - return QSharedPointer(); - } - QJsonObject root = jsonDoc.object(); - - int launcher_ver = readVersion->minimumLauncherVersion = root.value("minimumLauncherVersion").toDouble(); - // ADD MORE HERE :D - if(launcher_ver > 0 && launcher_ver <= 7) - return parse4(root, readVersion); - else - { - error_string = "Version file was for an unrecognized launcher version. RIP"; - m_error = FullVersionFactory::UnsupportedVersion; - return QSharedPointer(); - } -} - - -FullVersionFactory::FullVersionFactory() -{ - m_error = FullVersionFactory::AllOK; -} diff --git a/logic/VersionFactory.h b/logic/VersionFactory.h deleted file mode 100644 index 0c0ee2d4..00000000 --- a/logic/VersionFactory.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include - -struct OneSixVersion; -class Rule; - -class FullVersionFactory -{ -public: - enum Error - { - AllOK, // all parsed OK - ParseError, // the file was corrupted somehow - UnsupportedVersion // the file was meant for a launcher version we don't support (yet) - } m_error; - QString error_string; - -public: - FullVersionFactory(); - QSharedPointer parse(QByteArray data); -private: - QSharedPointer parse4(QJsonObject root, QSharedPointer product); - QList > parse4rules(QJsonObject & baseObj); -}; \ No newline at end of file diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp index 492849ee..9205e70f 100644 --- a/logic/lists/ForgeVersionList.cpp +++ b/logic/lists/ForgeVersionList.cpp @@ -260,8 +260,10 @@ void ForgeListLoadTask::list_downloaded() fVersion->installer_url = installer_url; fVersion->jobbuildver = jobbuildver; fVersion->mcver = mcver; - fVersion->filename = filename; - fVersion->filename = installer_filename; + if(installer_filename.isEmpty()) + fVersion->filename = filename; + else + fVersion->filename = installer_filename; fVersion->m_buildnr = build_nr; tempList.append(fVersion); } @@ -271,3 +273,8 @@ void ForgeListLoadTask::list_downloaded() emitSucceeded(); return; } + + + + + diff --git a/logic/lists/ForgeVersionList.h b/logic/lists/ForgeVersionList.h index ca6b27bc..613de8a6 100644 --- a/logic/lists/ForgeVersionList.h +++ b/logic/lists/ForgeVersionList.h @@ -3,7 +3,7 @@ * 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 @@ -33,19 +33,22 @@ struct ForgeVersion : public BaseVersion virtual QString descriptor() { return filename; - }; + } + ; virtual QString name() { return "Forge " + jobbuildver; - }; + } + ; virtual QString typeString() const { - if(installer_url.isEmpty()) + if (installer_url.isEmpty()) return "Universal"; else return "Installer"; - }; - + } + ; + int m_buildnr = 0; QString universal_url; QString changelog_url; @@ -60,42 +63,45 @@ class ForgeVersionList : public BaseVersionList Q_OBJECT public: friend class ForgeListLoadTask; - + explicit ForgeVersionList(QObject *parent = 0); - + virtual Task *getLoadTask(); virtual bool isLoaded(); virtual const BaseVersionPtr at(int i) const; virtual int count() const; virtual void sort(); - + virtual BaseVersionPtr getLatestStable() const; - - virtual QVariant data(const QModelIndex& index, int role) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; - virtual int columnCount(const QModelIndex& parent) const; - + + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role) const; + virtual int columnCount(const QModelIndex &parent) const; + protected: QList m_vlist; - + bool m_loaded; - -protected slots: - virtual void updateListData(QList versions); + +protected +slots: + virtual void updateListData(QList versions); }; class ForgeListLoadTask : public Task { Q_OBJECT - + public: explicit ForgeListLoadTask(ForgeVersionList *vlist); - + virtual void executeTask(); - -protected slots: + +protected +slots: void list_downloaded(); - + protected: DownloadJobPtr listJob; ForgeVersionList *m_list; diff --git a/logic/tasks/LoginTask.cpp b/logic/tasks/LoginTask.cpp index 859827bc..222af618 100644 --- a/logic/tasks/LoginTask.cpp +++ b/logic/tasks/LoginTask.cpp @@ -30,7 +30,7 @@ void LoginTask::executeTask() { setStatus(tr("Logging in...")); auto worker = MMC->qnam(); - connect(worker, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); + connect(worker.data(), SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetReply(QNetworkReply*))); QUrl loginURL("https://login.minecraft.net/"); QNetworkRequest netRequest(loginURL);