summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2013-09-22 14:03:05 +0200
committerPetr Mrázek <peterix@gmail.com>2013-09-22 14:03:05 +0200
commit1bed5e4023f503cb95a914c1e6886e045b7f34e2 (patch)
tree6c2a2eb34b93bdd24e7db1f9378b231084c0b27a
parent930b07afd4229e952d0cd47ca62cd94235499a0c (diff)
parent9d03a9c1e3b9c24a4146adedb2971591d23b037a (diff)
downloadMultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar
MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.gz
MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.lz
MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.tar.xz
MultiMC-1bed5e4023f503cb95a914c1e6886e045b7f34e2.zip
Merge branch 'feature_onesix_forge' into develop
-rw-r--r--.clang-format24
-rw-r--r--CMakeLists.txt144
-rw-r--r--MultiMC.cpp70
-rw-r--r--MultiMC.h39
-rw-r--r--gui/IconPickerDialog.cpp4
-rw-r--r--gui/LegacyModEditDialog.cpp3
-rw-r--r--gui/OneSixModEditDialog.cpp226
-rw-r--r--gui/OneSixModEditDialog.h6
-rw-r--r--gui/OneSixModEditDialog.ui9
-rw-r--r--gui/instancedelegate.h2
-rw-r--r--gui/lwjglselectdialog.cpp6
-rw-r--r--gui/mainwindow.cpp6
-rw-r--r--gui/mainwindow.ui2
-rw-r--r--gui/newinstancedialog.cpp2
-rw-r--r--gui/settingsdialog.cpp4
-rw-r--r--logic/BaseInstance.cpp2
-rw-r--r--logic/BaseInstance.h2
-rw-r--r--logic/ForgeInstaller.cpp135
-rw-r--r--logic/ForgeInstaller.h25
-rw-r--r--logic/LegacyUpdate.cpp4
-rw-r--r--logic/ModList.h3
-rw-r--r--logic/NostalgiaInstance.h1
-rw-r--r--logic/OneSixInstance.cpp129
-rw-r--r--logic/OneSixInstance.h4
-rw-r--r--logic/OneSixLibrary.cpp98
-rw-r--r--logic/OneSixLibrary.h26
-rw-r--r--logic/OneSixRule.cpp66
-rw-r--r--logic/OneSixRule.h6
-rw-r--r--logic/OneSixUpdate.cpp85
-rw-r--r--logic/OneSixVersion.cpp261
-rw-r--r--logic/OneSixVersion.h60
-rw-r--r--logic/OpSys.cpp11
-rw-r--r--logic/OpSys.h1
-rw-r--r--logic/VersionFactory.cpp196
-rw-r--r--logic/VersionFactory.h24
-rw-r--r--logic/lists/ForgeVersionList.cpp118
-rw-r--r--logic/lists/ForgeVersionList.h52
-rw-r--r--logic/net/CacheDownload.cpp63
-rw-r--r--logic/net/HttpMetaCache.h19
-rw-r--r--logic/tasks/LoginTask.cpp2
40 files changed, 1200 insertions, 740 deletions
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/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/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.cpp
-logic/net/CacheDownload.cpp
-logic/net/DownloadJob.cpp
-logic/net/HttpMetaCache.cpp
-
-# legacy instances
-logic/LegacyInstance.cpp
-logic/LegacyUpdate.cpp
-logic/LegacyForge.cpp
-
-# 1.6 instances
-logic/OneSixAssets.cpp
-logic/OneSixInstance.cpp
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>("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<IconList> MultiMC::icons()
{
if ( !m_icons )
{
- m_icons = new IconList;
+ m_icons.reset(new IconList);
}
return m_icons;
}
-LWJGLVersionList* MultiMC::lwjgllist()
+QSharedPointer<LWJGLVersionList> MultiMC::lwjgllist()
{
if ( !m_lwjgllist )
{
- m_lwjgllist = new LWJGLVersionList();
+ m_lwjgllist.reset(new LWJGLVersionList());
}
return m_lwjgllist;
}
-ForgeVersionList* MultiMC::forgelist()
+
+QSharedPointer<ForgeVersionList> MultiMC::forgelist()
{
if ( !m_forgelist )
{
- m_forgelist = new ForgeVersionList();
+ m_forgelist.reset(new ForgeVersionList());
}
return m_forgelist;
}
-MinecraftVersionList* MultiMC::minecraftlist()
+QSharedPointer<MinecraftVersionList> 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 <QApplication>
+#include <QSharedPointer>
#include "MultiMCVersion.h"
#include "config.h"
@@ -33,17 +34,17 @@ public:
MultiMC ( int& argc, char** argv );
virtual ~MultiMC();
- SettingsObject * settings()
+ QSharedPointer<SettingsObject> settings()
{
return m_settings;
};
- InstanceList * instances()
+ QSharedPointer<InstanceList> instances()
{
return m_instances;
};
- IconList * icons();
+ QSharedPointer<IconList> icons();
Status status()
{
@@ -55,21 +56,21 @@ public:
return m_version;
}
- QNetworkAccessManager * qnam()
+ QSharedPointer<QNetworkAccessManager> qnam()
{
return m_qnam;
}
- HttpMetaCache * metacache()
+ QSharedPointer<HttpMetaCache> metacache()
{
return m_metacache;
}
- LWJGLVersionList * lwjgllist();
+ QSharedPointer<LWJGLVersionList> lwjgllist();
- ForgeVersionList * forgelist();
+ QSharedPointer<ForgeVersionList> forgelist();
- MinecraftVersionList * minecraftlist();
+ QSharedPointer<MinecraftVersionList> 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<QTranslator> m_qt_translator;
+ QSharedPointer<QTranslator> m_mmc_translator;
+ QSharedPointer<SettingsObject> m_settings;
+ QSharedPointer<InstanceList> m_instances;
+ QSharedPointer<IconList> m_icons;
+ QSharedPointer<QNetworkAccessManager> m_qnam;
+ QSharedPointer<HttpMetaCache> m_metacache;
+ QSharedPointer<LWJGLVersionList> m_lwjgllist;
+ QSharedPointer<ForgeVersionList> m_forgelist;
+ QSharedPointer<MinecraftVersionList> 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 ac7f7f25..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())
{
@@ -230,7 +230,6 @@ void LegacyModEditDialog::on_addForgeBtn_clicked()
m_jarmods->installMod(QFileInfo(entry->getFullPath()));
m_jarmods->startWatching();
}
- //m_selectedInstance->setIntendedVersionId(->descriptor());
}
}
void LegacyModEditDialog::on_addJarBtn_clicked()
diff --git a/gui/OneSixModEditDialog.cpp b/gui/OneSixModEditDialog.cpp
index fad9d2e2..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,36 +20,44 @@
#include "logic/OneSixVersion.h"
#include "logic/EnabledItemFilter.h"
#include "logic/lists/ForgeVersionList.h"
+#include <logic/ForgeInstaller.h>
#include "gui/versionselectdialog.h"
+#include "ProgressDialog.h"
#include <pathutils.h>
#include <QFileDialog>
+#include <QMessageBox>
#include <QDebug>
#include <QEvent>
#include <QKeyEvent>
-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();
-
- auto filter = new EnabledItemFilter(this);
- filter->setActive(true);
- filter->setSourceModel(m_version.data());
- ui->libraryTreeView->setModel(filter);
- ui->libraryTreeView->installEventFilter( this );
+ 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->mainClassEdit->setText(m_version->mainClass);
+ 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
@@ -57,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();
}
}
@@ -69,62 +77,164 @@ OneSixModEditDialog::~OneSixModEditDialog()
delete ui;
}
+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())
+ {
+ m_version = m_inst->getFullVersion();
+ main_model->setSourceModel(m_version.data());
+ 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);
+ if (reply == QMessageBox::Yes)
+ {
+ if (m_inst->revertCustomVersion())
+ {
+ m_version = m_inst->getFullVersion();
+ main_model->setSourceModel(m_version.data());
+ 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())
{
- //m_selectedInstance->setIntendedVersionId(vselect.selectedVersion()->descriptor());
+ 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);
+ if (reply == QMessageBox::Yes)
+ {
+ m_inst->revertCustomVersion();
+ m_inst->customizeVersion();
+ {
+ m_version = m_inst->getFullVersion();
+ main_model->setSourceModel(m_version.data());
+ updateVersionControls();
+ }
+ }
+ else
+ return;
+ }
+ else
+ {
+ m_inst->customizeVersion();
+ m_version = m_inst->getFullVersion();
+ main_model->setSourceModel(m_version.data());
+ updateVersionControls();
+ }
+ ForgeVersionPtr forgeVersion = vselect.selectedVersion().dynamicCast<ForgeVersion>();
+ 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)
+ {
+ // install
+ QString forgePath = entry->getFullPath();
+ ForgeInstaller forge(forgePath, forgeVersion->universal_url);
+ if (!forge.apply(m_version))
+ {
+ // failure notice
+ }
+ }
+ else
+ {
+ // failed to download forge :/
+ }
+ }
+ 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<QKeyEvent*>(ev);
- if(obj == ui->loaderModTreeView)
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(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()
@@ -134,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));
@@ -146,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);
@@ -158,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));
@@ -173,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);
@@ -184,4 +295,3 @@ void OneSixModEditDialog::on_viewResPackBtn_clicked()
{
openDirInDefaultProgram(m_inst->resourcePacksDir(), true);
}
-
diff --git a/gui/OneSixModEditDialog.h b/gui/OneSixModEditDialog.h
index d14c842c..e70bd73f 100644
--- a/gui/OneSixModEditDialog.h
+++ b/gui/OneSixModEditDialog.h
@@ -18,6 +18,7 @@
#include <logic/OneSixInstance.h>
+class EnabledItemFilter;
namespace Ui {
class OneSixModEditDialog;
}
@@ -41,6 +42,10 @@ private slots:
// Questionable: SettingsDialog doesn't need this for some reason?
void on_buttonBox_rejected();
void on_forgeBtn_clicked();
+ void on_customizeBtn_clicked();
+ void on_revertBtn_clicked();
+ void updateVersionControls();
+ void disableVersionControls();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
bool loaderListFilter( QKeyEvent* ev );
@@ -50,5 +55,6 @@ private:
QSharedPointer<OneSixVersion> m_version;
QSharedPointer<ModList> m_mods;
QSharedPointer<ModList> m_resourcepacks;
+ EnabledItemFilter * main_model;
OneSixInstance * m_inst;
};
diff --git a/gui/OneSixModEditDialog.ui b/gui/OneSixModEditDialog.ui
index aadaf3ae..527899ca 100644
--- a/gui/OneSixModEditDialog.ui
+++ b/gui/OneSixModEditDialog.ui
@@ -55,7 +55,11 @@
</widget>
</item>
<item>
- <widget class="QLineEdit" name="mainClassEdit"/>
+ <widget class="QLineEdit" name="mainClassEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
</item>
</layout>
</item>
@@ -85,6 +89,9 @@
</item>
<item>
<widget class="QPushButton" name="revertBtn">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="toolTip">
<string>Revert to original base version</string>
</property>
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 @@
<string>Meow</string>
</property>
<property name="toolTip">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0004;&quot;&gt;Catnatok!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Or just a cat with a ball of yarn?&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;WHO KNOWS?!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/icons/instances/tnt&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-weight:600; color:#ff0004;&quot;&gt;Catnarok!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Or just a cat with a ball of yarn?&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;WHO KNOWS?!&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;:/icons/instances/tnt&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</action>
</widget>
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<BaseVersionList> 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<BaseVersionList> 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..bcba00e9
--- /dev/null
+++ b/logic/ForgeInstaller.cpp
@@ -0,0 +1,135 @@
+#include "ForgeInstaller.h"
+#include "OneSixVersion.h"
+#include "OneSixLibrary.h"
+#include "net/HttpMetaCache.h"
+#include <quazip.h>
+#include <quazipfile.h>
+#include <pathutils.h>
+#include <QStringList>
+#include "MultiMC.h"
+
+ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
+{
+ QSharedPointer<OneSixVersion> 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();
+
+ auto cacheentry = MMC->metacache()->resolveEntry("libraries", lib.storagePath());
+ 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;
+ QCryptographicHash md5sum(QCryptographicHash::Md5);
+ md5sum.addData(data);
+
+ cacheentry->stale = false;
+ cacheentry->md5sum = md5sum.result().toHex().constData();
+ MMC->metacache()->updateEntry(cacheentry);
+ }
+ file.close();
+
+ m_forge_version = newVersion;
+ realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
+}
+
+bool ForgeInstaller::apply(QSharedPointer<OneSixVersion> 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<QString> 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 <QString>
+#include <QSharedPointer>
+
+class OneSixVersion;
+
+class ForgeInstaller
+{
+public:
+ ForgeInstaller(QString filename, QString universal_url);
+
+ bool apply(QSharedPointer<OneSixVersion> to);
+
+private:
+ // the version, read from the installer
+ QSharedPointer<OneSixVersion> 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<QNetworkReply> (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<QNetworkCookie> cookies = qvariant_cast<QList<QNetworkCookie>>(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<Mod> mods;
};
+
+
+
diff --git a/logic/NostalgiaInstance.h b/logic/NostalgiaInstance.h
index f2df1828..1436e48d 100644
--- a/logic/NostalgiaInstance.h
+++ b/logic/NostalgiaInstance.h
@@ -9,3 +9,4 @@ public:
explicit NostalgiaInstance(const QString &rootDir, SettingsObject * settings, QObject *parent = 0);
virtual QString getStatusbarDescription();
};
+
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index 7b038c46..e22a8890 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 <setting.h>
#include <pathutils.h>
@@ -10,8 +10,9 @@
#include <JlCompress.h>
#include <gui/OneSixModEditDialog.h>
-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<QString, QString> 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<QString, QString> 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<QString, QString> 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<ModList> 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<ModList> 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();
}
@@ -226,34 +227,53 @@ QString OneSixInstance::currentVersionId() const
return intendedVersionId();
}
+bool OneSixInstance::customizeVersion()
+{
+ if (!versionIsCustom())
+ {
+ auto pathCustom = PathCombine(instanceRoot(), "custom.json");
+ auto pathOrig = PathCombine(instanceRoot(), "version.json");
+ QFile::copy(pathOrig, pathCustom);
+ return reloadFullVersion();
+ }
+ else
+ return true;
+}
+
+bool OneSixInstance::revertCustomVersion()
+{
+ if (versionIsCustom())
+ {
+ auto path = PathCombine(instanceRoot(), "custom.json");
+ QFile::remove(path);
+ return reloadFullVersion();
+ }
+ 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<OneSixVersion> OneSixInstance::getFullVersion()
{
I_D(OneSixInstance);
return d->version;
@@ -269,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;
}
@@ -279,7 +299,7 @@ bool OneSixInstance::menuActionEnabled ( QString action_name ) const
QString OneSixInstance::getStatusbarDescription()
{
QString descr = "One Six : " + intendedVersionId();
- if(versionIsCustom())
+ if (versionIsCustom())
{
descr + " (custom)";
}
@@ -300,3 +320,4 @@ QString OneSixInstance::instanceConfigFolder() const
{
return PathCombine(minecraftRoot(), "config");
}
+
diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h
index 72bde630..0139b645 100644
--- a/logic/OneSixInstance.h
+++ b/logic/OneSixInstance.h
@@ -41,6 +41,10 @@ public:
bool reloadFullVersion();
/// get the current full version info
QSharedPointer<OneSixVersion> getFullVersion();
+ /// revert the current custom version back to base
+ bool revertCustomVersion();
+ /// customize the current base version
+ bool customizeVersion();
/// is the current version original, or custom?
bool versionIsCustom();
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 <QJsonArray>
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<QSharedPointer<Rule>> 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 <QStringList>
#include <QMap>
#include <QSharedPointer>
+#include <QJsonObject>
#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<QSharedPointer<Rule> > 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<OpSys, QString> 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 <QJsonObject>
+#include <QJsonArray>
+
+QList<QSharedPointer<Rule>> rulesFromJsonV4(QJsonObject &objectWithRules)
+{
+ QList<QSharedPointer<Rule>> rules;
+ auto rulesVal = objectWithRules.value("rules");
+ if (!rulesVal.isArray())
+ return rules;
+
+ QJsonArray ruleList = rulesVal.toArray();
+ for (auto ruleVal : ruleList)
+ {
+ QSharedPointer<Rule> 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 <QString>
#include <QSharedPointer>
-
-class OneSixLibrary;
#include "OneSixLibrary.h"
enum RuleAction
@@ -13,6 +11,7 @@ enum RuleAction
};
RuleAction RuleAction_fromString(QString);
+QList<QSharedPointer<Rule>> 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<OsRule> create(RuleAction result, OpSys system, QString version_regexp)
{
return QSharedPointer<OsRule> (new OsRule(result, system, version_regexp));
@@ -63,6 +64,7 @@ protected:
ImplicitRule(RuleAction result)
: Rule(result) {}
public:
+ virtual QJsonObject toJson();
static QSharedPointer<ImplicitRule> create(RuleAction result)
{
return QSharedPointer<ImplicitRule> (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<MinecraftVersion>();
- if(targetVersion == nullptr)
+ targetVersion =
+ MMC->minecraftlist()->findVersion(intendedVersion).dynamicCast<MinecraftVersion>();
+ 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<ByteArrayDownload>()->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<OneSixVersion> 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<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNormalLibs()
+QSharedPointer<OneSixVersion> fromJsonV4(QJsonObject root,
+ QSharedPointer<OneSixVersion> fullVersion)
{
- QList<QSharedPointer<OneSixLibrary> > 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<OneSixLibrary> 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> OneSixVersion::fromJson(QJsonObject root)
+{
+ QSharedPointer<OneSixVersion> 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<OneSixVersion>();
+ }
+}
+
+QSharedPointer<OneSixVersion> OneSixVersion::fromFile(QString filepath)
+{
+ QFile file(filepath);
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ return QSharedPointer<OneSixVersion>();
+ }
+
+ auto data = file.readAll();
+ QJsonParseError jsonError;
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
+
+ if (jsonError.error != QJsonParseError::NoError)
+ {
+ return QSharedPointer<OneSixVersion>();
+ }
+
+ if (!jsonDoc.isObject())
+ {
+ return QSharedPointer<OneSixVersion>();
+ }
+ 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<QSharedPointer<OneSixLibrary>> OneSixVersion::getActiveNormalLibs()
+{
+ QList<QSharedPointer<OneSixLibrary>> output;
+ for (auto lib : libraries)
{
if (lib->isActive() && !lib->isNative())
{
@@ -14,10 +205,10 @@ QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNormalLibs()
return output;
}
-QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNativeLibs()
+QList<QSharedPointer<OneSixLibrary>> OneSixVersion::getActiveNativeLibs()
{
- QList<QSharedPointer<OneSixLibrary> > output;
- for ( auto lib: libraries )
+ QList<QSharedPointer<OneSixLibrary>> output;
+ for (auto lib : libraries)
{
if (lib->isActive() && lib->isNative())
{
@@ -27,41 +218,50 @@ QList<QSharedPointer<OneSixLibrary> > OneSixVersion::getActiveNativeLibs()
return output;
}
+void OneSixVersion::externalUpdateStart()
+{
+ beginResetModel();
+}
+
+void OneSixVersion::externalUpdateFinish()
+{
+ endResetModel();
+}
-QVariant OneSixVersion::data(const QModelIndex& index, int role) const
+QVariant OneSixVersion::data(const QModelIndex &index, int role) const
{
- if(!index.isValid())
+ 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<OneSixVersion> fromJson(QJsonObject root);
+ static QSharedPointer<OneSixVersion> fromFile(QString filepath);
+
public:
+ QList<QSharedPointer<OneSixLibrary>> getActiveNormalLibs();
+ QList<QSharedPointer<OneSixLibrary>> 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<QSharedPointer<OneSixLibrary> > libraries;
-
+ QList<QSharedPointer<OneSixLibrary>> 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<Rule> rules;
-
-public:
-
- OneSixVersion()
- {
- minimumLauncherVersion = 0xDEADBEEF;
- }
-
- QList<QSharedPointer<OneSixLibrary> > getActiveNormalLibs();
- QList<QSharedPointer<OneSixLibrary> > 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<QSharedPointer<Rule> > FullVersionFactory::parse4rules(QJsonObject & baseObj)
-{
- QList<QSharedPointer<Rule> > rules;
- auto rulesVal = baseObj.value("rules");
- if(rulesVal.isArray())
- {
- QJsonArray ruleList = rulesVal.toArray();
- for(auto ruleVal : ruleList)
- {
- QSharedPointer<Rule> 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<OneSixVersion> FullVersionFactory::parse4(QJsonObject root, QSharedPointer<OneSixVersion> 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<OneSixLibrary> 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<OneSixVersion> FullVersionFactory::parse(QByteArray data)
-{
- QSharedPointer<OneSixVersion> 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<OneSixVersion>();
- }
-
- if(!jsonDoc.isObject())
- {
- error_string = "Error reading version file.";
- m_error = FullVersionFactory::ParseError;
- return QSharedPointer<OneSixVersion>();
- }
- 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<OneSixVersion>();
- }
-}
-
-
-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 <QtCore>
-
-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<OneSixVersion> parse(QByteArray data);
-private:
- QSharedPointer<OneSixVersion> parse4(QJsonObject root, QSharedPointer<OneSixVersion> product);
- QList<QSharedPointer<Rule> > parse4rules(QJsonObject & baseObj);
-}; \ No newline at end of file
diff --git a/logic/lists/ForgeVersionList.cpp b/logic/lists/ForgeVersionList.cpp
index 412c04fe..721f2c0a 100644
--- a/logic/lists/ForgeVersionList.cpp
+++ b/logic/lists/ForgeVersionList.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
@@ -25,10 +25,8 @@
#define JSON_URL "http://files.minecraftforge.net/minecraftforge/json"
-
-ForgeVersionList::ForgeVersionList(QObject* parent): BaseVersionList(parent)
+ForgeVersionList::ForgeVersionList(QObject *parent) : BaseVersionList(parent)
{
-
}
Task *ForgeVersionList::getLoadTask()
@@ -51,19 +49,19 @@ int ForgeVersionList::count() const
return m_vlist.count();
}
-int ForgeVersionList::columnCount(const QModelIndex& parent) const
+int ForgeVersionList::columnCount(const QModelIndex &parent) const
{
- return 3;
+ return 3;
}
QVariant ForgeVersionList::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
-
+
if (index.row() > count())
return QVariant();
-
+
auto version = m_vlist[index.row()].dynamicCast<ForgeVersion>();
switch (role)
{
@@ -72,22 +70,22 @@ QVariant ForgeVersionList::data(const QModelIndex &index, int role) const
{
case 0:
return version->name();
-
+
case 1:
return version->mcver;
-
+
case 2:
return version->typeString();
default:
return QVariant();
}
-
+
case Qt::ToolTipRole:
return version->descriptor();
-
+
case VersionPointerRole:
return qVariantFromValue(m_vlist[index.row()]);
-
+
default:
return QVariant();
}
@@ -102,33 +100,33 @@ QVariant ForgeVersionList::headerData(int section, Qt::Orientation orientation,
{
case 0:
return "Version";
-
+
case 1:
return "Minecraft";
-
+
case 2:
return "Type";
-
+
default:
return QVariant();
}
-
+
case Qt::ToolTipRole:
switch (section)
{
case 0:
return "The name of the version.";
-
+
case 1:
return "Minecraft version";
-
+
case 2:
return "The version's type.";
-
+
default:
return QVariant();
}
-
+
default:
return QVariant();
}
@@ -139,7 +137,7 @@ BaseVersionPtr ForgeVersionList::getLatestStable() const
return BaseVersionPtr();
}
-void ForgeVersionList::updateListData(QList<BaseVersionPtr > versions)
+void ForgeVersionList::updateListData(QList<BaseVersionPtr> versions)
{
beginResetModel();
m_vlist = versions;
@@ -154,101 +152,112 @@ void ForgeVersionList::sort()
// NO-OP for now
}
-
-ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList* vlist): Task()
+ForgeListLoadTask::ForgeListLoadTask(ForgeVersionList *vlist) : Task()
{
m_list = vlist;
}
-
void ForgeListLoadTask::executeTask()
{
auto job = new DownloadJob("Version index");
- job->add(QUrl(JSON_URL));
+ // we do not care if the version is stale or not.
+ auto forgeListEntry = MMC->metacache()->resolveEntry("minecraftforge", "list.json");
+ job->add(QUrl(JSON_URL), forgeListEntry);
listJob.reset(job);
connect(listJob.data(), SIGNAL(succeeded()), SLOT(list_downloaded()));
connect(listJob.data(), SIGNAL(failed()), SLOT(versionFileFailed()));
- connect(listJob.data(), SIGNAL(progress(qint64,qint64)), SIGNAL(progress(qint64,qint64)));
+ connect(listJob.data(), SIGNAL(progress(qint64, qint64)), SIGNAL(progress(qint64, qint64)));
listJob->start();
}
void ForgeListLoadTask::list_downloaded()
{
- auto DlJob = listJob->first();
- auto data = DlJob.dynamicCast<ByteArrayDownload>()->m_data;
-
-
+ QByteArray data;
+ {
+ auto DlJob = listJob->first();
+ auto filename = DlJob.dynamicCast<CacheDownload>()->m_target_path;
+ QFile listFile(filename);
+ if(!listFile.open(QIODevice::ReadOnly))
+ return;
+ data = listFile.readAll();
+ DlJob.reset();
+ }
+
QJsonParseError jsonError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
- DlJob.reset();
-
+
+
if (jsonError.error != QJsonParseError::NoError)
{
emitFailed("Error parsing version list JSON:" + jsonError.errorString());
return;
}
- if(!jsonDoc.isObject())
+ if (!jsonDoc.isObject())
{
emitFailed("Error parsing version list JSON: jsonDoc is not an object");
return;
}
-
+
QJsonObject root = jsonDoc.object();
-
+
// Now, get the array of versions.
- if(!root.value("builds").isArray())
+ if (!root.value("builds").isArray())
{
- emitFailed("Error parsing version list JSON: version list object is missing 'builds' array");
+ emitFailed(
+ "Error parsing version list JSON: version list object is missing 'builds' array");
return;
}
QJsonArray builds = root.value("builds").toArray();
-
- QList<BaseVersionPtr > tempList;
+
+ QList<BaseVersionPtr> tempList;
for (int i = 0; i < builds.count(); i++)
{
// Load the version info.
- if(!builds[i].isObject())
+ if (!builds[i].isObject())
{
- //FIXME: log this somewhere
+ // FIXME: log this somewhere
continue;
}
QJsonObject obj = builds[i].toObject();
int build_nr = obj.value("build").toDouble(0);
- if(!build_nr)
+ if (!build_nr)
continue;
QJsonArray files = obj.value("files").toArray();
QString url, jobbuildver, mcver, buildtype, filename;
QString changelog_url, installer_url;
+ QString installer_filename;
bool valid = false;
- for(int j = 0; j < files.count(); j++)
+ for (int j = 0; j < files.count(); j++)
{
- if(!files[j].isObject())
+ if (!files[j].isObject())
continue;
QJsonObject file = files[j].toObject();
buildtype = file.value("buildtype").toString();
- if((buildtype == "client" || buildtype == "universal") && !valid)
+ if ((buildtype == "client" || buildtype == "universal") && !valid)
{
mcver = file.value("mcver").toString();
url = file.value("url").toString();
jobbuildver = file.value("jobbuildver").toString();
int lastSlash = url.lastIndexOf('/');
- filename = url.mid(lastSlash+1);
+ filename = url.mid(lastSlash + 1);
valid = true;
}
- else if(buildtype == "changelog")
+ else if (buildtype == "changelog")
{
QString ext = file.value("ext").toString();
- if(ext.isEmpty())
+ if (ext.isEmpty())
continue;
changelog_url = file.value("url").toString();
}
- else if(buildtype == "installer")
+ else if (buildtype == "installer")
{
installer_url = file.value("url").toString();
+ int lastSlash = installer_url.lastIndexOf('/');
+ installer_filename = installer_url.mid(lastSlash + 1);
}
}
- if(valid)
+ if (valid)
{
// Now, we construct the version object and add it to the list.
QSharedPointer<ForgeVersion> fVersion(new ForgeVersion());
@@ -257,13 +266,16 @@ void ForgeListLoadTask::list_downloaded()
fVersion->installer_url = installer_url;
fVersion->jobbuildver = jobbuildver;
fVersion->mcver = mcver;
- fVersion->filename = filename;
+ if (installer_filename.isEmpty())
+ fVersion->filename = filename;
+ else
+ fVersion->filename = installer_filename;
fVersion->m_buildnr = build_nr;
tempList.append(fVersion);
}
}
m_list->updateListData(tempList);
-
+
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<BaseVersionPtr> m_vlist;
-
+
bool m_loaded;
-
-protected slots:
- virtual void updateListData(QList<BaseVersionPtr > versions);
+
+protected
+slots:
+ virtual void updateListData(QList<BaseVersionPtr> 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/net/CacheDownload.cpp b/logic/net/CacheDownload.cpp
index c0074574..dc2e0448 100644
--- a/logic/net/CacheDownload.cpp
+++ b/logic/net/CacheDownload.cpp
@@ -7,8 +7,8 @@
#include <QDateTime>
#include <QDebug>
-CacheDownload::CacheDownload (QUrl url, MetaEntryPtr entry )
- :Download(), md5sum(QCryptographicHash::Md5)
+CacheDownload::CacheDownload(QUrl url, MetaEntryPtr entry)
+ : Download(), md5sum(QCryptographicHash::Md5)
{
m_url = url;
m_entry = entry;
@@ -19,38 +19,40 @@ CacheDownload::CacheDownload (QUrl url, MetaEntryPtr entry )
void CacheDownload::start()
{
- if(!m_entry->stale)
+ if (!m_entry->stale)
{
emit succeeded(index_within_job);
return;
}
m_output_file.setFileName(m_target_path);
// if there already is a file and md5 checking is in effect and it can be opened
- if(!ensureFilePathExists(m_target_path))
+ if (!ensureFilePathExists(m_target_path))
{
emit failed(index_within_job);
return;
}
qDebug() << "Downloading " << m_url.toString();
- QNetworkRequest request ( m_url );
- request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
-
+ QNetworkRequest request(m_url);
+ request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->etag.toLatin1());
+
auto worker = MMC->qnam();
- QNetworkReply * rep = worker->get ( request );
-
- m_reply = QSharedPointer<QNetworkReply> ( rep, &QObject::deleteLater );
- connect ( rep, SIGNAL ( downloadProgress ( qint64,qint64 ) ), SLOT ( downloadProgress ( qint64,qint64 ) ) );
- connect ( rep, SIGNAL ( finished() ), SLOT ( downloadFinished() ) );
- connect ( rep, SIGNAL ( error ( QNetworkReply::NetworkError ) ), SLOT ( downloadError ( QNetworkReply::NetworkError ) ) );
- connect ( rep, SIGNAL ( readyRead() ), SLOT ( downloadReadyRead() ) );
+ QNetworkReply *rep = worker->get(request);
+
+ m_reply = QSharedPointer<QNetworkReply>(rep, &QObject::deleteLater);
+ connect(rep, SIGNAL(downloadProgress(qint64, qint64)),
+ SLOT(downloadProgress(qint64, qint64)));
+ connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
+ connect(rep, SIGNAL(error(QNetworkReply::NetworkError)),
+ SLOT(downloadError(QNetworkReply::NetworkError)));
+ connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
}
-void CacheDownload::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal )
+void CacheDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
- emit progress (index_within_job, bytesReceived, bytesTotal );
+ emit progress(index_within_job, bytesReceived, bytesTotal);
}
-void CacheDownload::downloadError ( QNetworkReply::NetworkError error )
+void CacheDownload::downloadError(QNetworkReply::NetworkError error)
{
// error happened during download.
// TODO: log the reason why
@@ -59,12 +61,12 @@ void CacheDownload::downloadError ( QNetworkReply::NetworkError error )
void CacheDownload::downloadFinished()
{
// if the download succeeded
- if ( m_status != Job_Failed )
+ if (m_status != Job_Failed)
{
-
+
// nothing went wrong...
m_status = Job_Finished;
- if(m_opened_for_saving)
+ if (m_opened_for_saving)
{
// save the data to the downloadable if we aren't saving to file
m_output_file.close();
@@ -72,20 +74,23 @@ void CacheDownload::downloadFinished()
}
else
{
- if ( m_output_file.open ( QIODevice::ReadOnly ) )
+ if (m_output_file.open(QIODevice::ReadOnly))
{
- m_entry->md5sum = QCryptographicHash::hash ( m_output_file.readAll(), QCryptographicHash::Md5 ).toHex().constData();
+ m_entry->md5sum =
+ QCryptographicHash::hash(m_output_file.readAll(), QCryptographicHash::Md5)
+ .toHex()
+ .constData();
m_output_file.close();
}
}
QFileInfo output_file_info(m_target_path);
-
-
+
m_entry->etag = m_reply->rawHeader("ETag").constData();
- m_entry->last_changed_timestamp = output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
+ m_entry->last_changed_timestamp =
+ output_file_info.lastModified().toUTC().toMSecsSinceEpoch();
m_entry->stale = false;
MMC->metacache()->updateEntry(m_entry);
-
+
m_reply.clear();
emit succeeded(index_within_job);
return;
@@ -103,9 +108,9 @@ void CacheDownload::downloadFinished()
void CacheDownload::downloadReadyRead()
{
- if(!m_opened_for_saving)
+ if (!m_opened_for_saving)
{
- if ( !m_output_file.open ( QIODevice::WriteOnly ) )
+ if (!m_output_file.open(QIODevice::WriteOnly))
{
/*
* Can't open the file... the job failed
@@ -118,5 +123,5 @@ void CacheDownload::downloadReadyRead()
}
QByteArray ba = m_reply->readAll();
md5sum.addData(ba);
- m_output_file.write ( ba );
+ m_output_file.write(ba);
}
diff --git a/logic/net/HttpMetaCache.h b/logic/net/HttpMetaCache.h
index fac6bec3..daf6c43f 100644
--- a/logic/net/HttpMetaCache.h
+++ b/logic/net/HttpMetaCache.h
@@ -24,25 +24,28 @@ public:
// supply path to the cache index file
HttpMetaCache(QString path);
~HttpMetaCache();
-
+
// get the entry solely from the cache
// you probably don't want this, unless you have some specific caching needs.
MetaEntryPtr getEntry(QString base, QString resource_path);
-
+
// get the entry from cache and verify that it isn't stale (within reason)
- MetaEntryPtr resolveEntry(QString base, QString resource_path, QString expected_etag = QString());
-
+ MetaEntryPtr resolveEntry(QString base, QString resource_path,
+ QString expected_etag = QString());
+
// add a previously resolved stale entry
bool updateEntry(MetaEntryPtr stale_entry);
-
+
void addBase(QString base, QString base_root);
-
+
// (re)start a timer that calls SaveNow later.
void SaveEventually();
void Load();
- QString getBasePath ( QString base );
-public slots:
+ QString getBasePath(QString base);
+public
+slots:
void SaveNow();
+
private:
// create a new stale entry, given the parameters
MetaEntryPtr staleEntry(QString base, QString resource_path);
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);