summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--gui/dialogs/OneSixModEditDialog.cpp94
-rw-r--r--gui/dialogs/OneSixModEditDialog.h2
-rw-r--r--gui/dialogs/OneSixModEditDialog.ui23
-rw-r--r--logic/BaseInstaller.cpp66
-rw-r--r--logic/BaseInstaller.h39
-rw-r--r--logic/ForgeInstaller.cpp52
-rw-r--r--logic/ForgeInstaller.h9
-rw-r--r--logic/InstanceFactory.cpp10
-rw-r--r--logic/LiteLoaderInstaller.cpp96
-rw-r--r--logic/LiteLoaderInstaller.h20
-rw-r--r--logic/OneSixFTBInstance.cpp4
-rw-r--r--logic/OneSixInstance.cpp101
-rw-r--r--logic/OneSixInstance.h23
-rw-r--r--logic/OneSixInstance_p.h11
-rw-r--r--logic/OneSixLibrary.cpp22
-rw-r--r--logic/OneSixLibrary.h30
-rw-r--r--logic/OneSixRule.cpp4
-rw-r--r--logic/OneSixRule.h2
-rw-r--r--logic/OneSixUpdate.cpp8
-rw-r--r--logic/OneSixVersion.cpp282
-rw-r--r--logic/OneSixVersion.h37
-rw-r--r--logic/OneSixVersionBuilder.cpp446
-rw-r--r--logic/OneSixVersionBuilder.h53
24 files changed, 908 insertions, 538 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 047b9edf..0acebacf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -405,10 +405,7 @@ logic/LegacyUpdate.cpp
logic/LegacyForge.h
logic/LegacyForge.cpp
-# 1.6 instances
-logic/OneSixInstance.h
-logic/OneSixInstance.cpp
-logic/OneSixInstance_p.h
+# OneSix instances
logic/OneSixUpdate.h
logic/OneSixUpdate.cpp
logic/OneSixVersion.h
@@ -419,10 +416,17 @@ logic/OneSixRule.h
logic/OneSixRule.cpp
logic/OpSys.h
logic/OpSys.cpp
+logic/BaseInstaller.h
+logic/BaseInstaller.cpp
logic/ForgeInstaller.h
logic/ForgeInstaller.cpp
logic/LiteLoaderInstaller.h
logic/LiteLoaderInstaller.cpp
+logic/OneSixInstance.h
+logic/OneSixInstance.cpp
+logic/OneSixInstance_p.h
+logic/OneSixVersionBuilder.h
+logic/OneSixVersionBuilder.cpp
# Nostalgia
logic/NostalgiaInstance.h
diff --git a/gui/dialogs/OneSixModEditDialog.cpp b/gui/dialogs/OneSixModEditDialog.cpp
index 3982f17d..625a7c91 100644
--- a/gui/dialogs/OneSixModEditDialog.cpp
+++ b/gui/dialogs/OneSixModEditDialog.cpp
@@ -55,7 +55,6 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent)
main_model->setSourceModel(m_version.get());
ui->libraryTreeView->setModel(main_model);
ui->libraryTreeView->installEventFilter(this);
- ui->mainClassEdit->setText(m_version->mainClass);
updateVersionControls();
}
else
@@ -81,6 +80,8 @@ OneSixModEditDialog::OneSixModEditDialog(OneSixInstance *inst, QWidget *parent)
ui->resPackTreeView->installEventFilter(this);
m_resourcepacks->startWatching();
}
+
+ connect(m_inst, &OneSixInstance::versionReloaded, this, &OneSixModEditDialog::updateVersionControls);
}
OneSixModEditDialog::~OneSixModEditDialog()
@@ -93,52 +94,23 @@ OneSixModEditDialog::~OneSixModEditDialog()
void OneSixModEditDialog::updateVersionControls()
{
bool customVersion = m_inst->versionIsCustom();
- ui->customizeBtn->setEnabled(!customVersion);
- ui->revertBtn->setEnabled(customVersion);
ui->forgeBtn->setEnabled(true);
- ui->liteloaderBtn->setEnabled(LiteLoaderInstaller(m_inst->intendedVersionId()).canApply());
+ ui->liteloaderBtn->setEnabled(LiteLoaderInstaller().canApply(m_inst));
ui->customEditorBtn->setEnabled(customVersion);
+ ui->mainClassEdit->setText(m_version->mainClass);
}
void OneSixModEditDialog::disableVersionControls()
{
- ui->customizeBtn->setEnabled(false);
- ui->revertBtn->setEnabled(false);
ui->forgeBtn->setEnabled(false);
ui->liteloaderBtn->setEnabled(false);
ui->customEditorBtn->setEnabled(false);
-}
-
-void OneSixModEditDialog::on_customizeBtn_clicked()
-{
- if (m_inst->customizeVersion())
- {
- m_version = m_inst->getFullVersion();
- main_model->setSourceModel(m_version.get());
- updateVersionControls();
- }
-}
-
-void OneSixModEditDialog::on_revertBtn_clicked()
-{
- auto response = CustomMessageBox::selectable(
- this, tr("Revert?"), tr("Do you want to revert the "
- "version of this instance to its original configuration?"),
- QMessageBox::Question, QMessageBox::Yes | QMessageBox::No)->exec();
- if (response == QMessageBox::Yes)
- {
- if (m_inst->revertCustomVersion())
- {
- m_version = m_inst->getFullVersion();
- main_model->setSourceModel(m_version.get());
- updateVersionControls();
- }
- }
+ ui->mainClassEdit->setText("");
}
void OneSixModEditDialog::on_customEditorBtn_clicked()
{
- if (m_inst->versionIsCustom())
+ if (QDir(m_inst->instanceRoot()).exists("custom.json"))
{
if (!MMC->openJsonEditor(m_inst->instanceRoot() + "/custom.json"))
{
@@ -153,34 +125,6 @@ void OneSixModEditDialog::on_forgeBtn_clicked()
vselect.setFilter(1, m_inst->currentVersionId());
if (vselect.exec() && vselect.selectedVersion())
{
- 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.get());
- updateVersionControls();
- }
- }
- else
- return;
- }
- else
- {
- m_inst->customizeVersion();
- m_version = m_inst->getFullVersion();
- main_model->setSourceModel(m_version.get());
- updateVersionControls();
- }
ForgeVersionPtr forgeVersion =
std::dynamic_pointer_cast<ForgeVersion>(vselect.selectedVersion());
if (!forgeVersion)
@@ -197,9 +141,9 @@ void OneSixModEditDialog::on_forgeBtn_clicked()
// install
QString forgePath = entry->getFullPath();
ForgeInstaller forge(forgePath, forgeVersion->universal_url);
- if (!forge.apply(m_version))
+ if (!forge.add(m_inst))
{
- // failure notice
+ QLOG_ERROR() << "Failure installing forge";
}
}
else
@@ -212,18 +156,19 @@ void OneSixModEditDialog::on_forgeBtn_clicked()
// install
QString forgePath = entry->getFullPath();
ForgeInstaller forge(forgePath, forgeVersion->universal_url);
- if (!forge.apply(m_version))
+ if (!forge.add(m_inst))
{
- // failure notice
+ QLOG_ERROR() << "Failure installing forge";
}
}
}
+ m_inst->reloadFullVersion(this);
}
void OneSixModEditDialog::on_liteloaderBtn_clicked()
{
- LiteLoaderInstaller liteloader(m_inst->intendedVersionId());
- if (!liteloader.canApply())
+ LiteLoaderInstaller liteloader;
+ if (!liteloader.canApply(m_inst))
{
QMessageBox::critical(
this, tr("LiteLoader"),
@@ -231,19 +176,16 @@ void OneSixModEditDialog::on_liteloaderBtn_clicked()
"into this version of Minecraft"));
return;
}
- if (!m_inst->versionIsCustom())
- {
- m_inst->customizeVersion();
- m_version = m_inst->getFullVersion();
- main_model->setSourceModel(m_version.get());
- updateVersionControls();
- }
- if (!liteloader.apply(m_version))
+ if (!liteloader.add(m_inst))
{
QMessageBox::critical(
this, tr("LiteLoader"),
tr("For reasons unknown, the LiteLoader installation failed. Check your MultiMC log files for details."));
}
+ else
+ {
+ m_inst->reloadFullVersion(this);
+ }
}
bool OneSixModEditDialog::loaderListFilter(QKeyEvent *keyEvent)
diff --git a/gui/dialogs/OneSixModEditDialog.h b/gui/dialogs/OneSixModEditDialog.h
index 2510c59c..161604c9 100644
--- a/gui/dialogs/OneSixModEditDialog.h
+++ b/gui/dialogs/OneSixModEditDialog.h
@@ -45,8 +45,6 @@ slots:
void on_buttonBox_rejected();
void on_forgeBtn_clicked();
void on_liteloaderBtn_clicked();
- void on_customizeBtn_clicked();
- void on_revertBtn_clicked();
void on_customEditorBtn_clicked();
void updateVersionControls();
void disableVersionControls();
diff --git a/gui/dialogs/OneSixModEditDialog.ui b/gui/dialogs/OneSixModEditDialog.ui
index 899e0cbf..d57d0f85 100644
--- a/gui/dialogs/OneSixModEditDialog.ui
+++ b/gui/dialogs/OneSixModEditDialog.ui
@@ -85,29 +85,6 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="customizeBtn">
- <property name="toolTip">
- <string>Create an customized copy of the base version</string>
- </property>
- <property name="text">
- <string>Customize</string>
- </property>
- </widget>
- </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>
- <property name="text">
- <string>Revert</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="Line" name="line">
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
diff --git a/logic/BaseInstaller.cpp b/logic/BaseInstaller.cpp
new file mode 100644
index 00000000..92aa0c92
--- /dev/null
+++ b/logic/BaseInstaller.cpp
@@ -0,0 +1,66 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BaseInstaller.h"
+
+#include <QFile>
+
+#include "OneSixVersion.h"
+#include "OneSixLibrary.h"
+#include "OneSixInstance.h"
+
+#include "cmdutils.h"
+
+BaseInstaller::BaseInstaller()
+{
+
+}
+
+bool BaseInstaller::isApplied(OneSixInstance *on)
+{
+ return QFile::exists(filename(on->instanceRoot()));
+}
+
+bool BaseInstaller::add(OneSixInstance *to)
+{
+ if (!patchesDir(to->instanceRoot()).exists())
+ {
+ QDir(to->instanceRoot()).mkdir("patches");
+ }
+
+ if (isApplied(to))
+ {
+ if (!remove(to))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool BaseInstaller::remove(OneSixInstance *from)
+{
+ return QFile::remove(filename(from->instanceRoot()));
+}
+
+QString BaseInstaller::filename(const QString &root) const
+{
+ return patchesDir(root).absoluteFilePath(id() + ".json");
+}
+QDir BaseInstaller::patchesDir(const QString &root) const
+{
+ return QDir(root + "/patches/");
+}
diff --git a/logic/BaseInstaller.h b/logic/BaseInstaller.h
new file mode 100644
index 00000000..df7eab89
--- /dev/null
+++ b/logic/BaseInstaller.h
@@ -0,0 +1,39 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+class OneSixInstance;
+class QDir;
+class QString;
+
+class BaseInstaller
+{
+public:
+ BaseInstaller();
+
+ virtual bool canApply(OneSixInstance *instance) const { return true; }
+ bool isApplied(OneSixInstance *on);
+
+ virtual bool add(OneSixInstance *to);
+ virtual bool remove(OneSixInstance *from);
+
+protected:
+ virtual QString id() const = 0;
+ QString filename(const QString &root) const;
+ QDir patchesDir(const QString &root) const;
+};
diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp
index 8d4c5b41..863c3dfd 100644
--- a/logic/ForgeInstaller.cpp
+++ b/logic/ForgeInstaller.cpp
@@ -22,6 +22,12 @@
#include <pathutils.h>
#include <QStringList>
#include "MultiMC.h"
+#include "OneSixInstance.h"
+
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QSaveFile>
+#include <QCryptographicHash>
ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
{
@@ -103,13 +109,22 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
}
-bool ForgeInstaller::apply(std::shared_ptr<OneSixVersion> to)
+bool ForgeInstaller::add(OneSixInstance *to)
{
+ if (!BaseInstaller::add(to))
+ {
+ return false;
+ }
+
+ QJsonObject obj;
+ obj.insert("order", 5);
+
if (!m_forge_version)
return false;
- to->externalUpdateStart();
int sliding_insert_window = 0;
{
+ QJsonArray librariesPlus;
+
// 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)
@@ -128,28 +143,43 @@ bool ForgeInstaller::apply(std::shared_ptr<OneSixVersion> to)
if (blacklist.contains(libName))
continue;
- // find an entry that matches this one
+ QJsonObject libObj = lib->toJson();
+
bool found = false;
- for (auto tolib : to->libraries)
+ // find an entry that matches this one
+ for (auto tolib : to->getFullVersion()->libraries)
{
if (tolib->name() != libName)
continue;
found = true;
// replace lib
- tolib = lib;
+ libObj.insert("insert", QString("apply"));
break;
}
if (!found)
{
// add lib
- to->libraries.insert(sliding_insert_window, lib);
+ QJsonObject insertObj;
+ insertObj.insert("before", to->getFullVersion()->libraries.at(sliding_insert_window)->rawName());
+ libObj.insert("insert", insertObj);
sliding_insert_window++;
}
+ librariesPlus.append(libObj);
}
- to->mainClass = m_forge_version->mainClass;
- to->minecraftArguments = m_forge_version->minecraftArguments;
- to->processArguments = m_forge_version->processArguments;
+ obj.insert("+libraries", librariesPlus);
+ obj.insert("mainClass", m_forge_version->mainClass);
+ obj.insert("minecraftArguments", m_forge_version->minecraftArguments);
+ obj.insert("processArguments", m_forge_version->processArguments);
+ }
+
+ QFile file(filename(to->instanceRoot()));
+ if (!file.open(QFile::WriteOnly))
+ {
+ QLOG_ERROR() << "Error opening" << file.fileName() << "for reading:" << file.errorString();
+ return false;
}
- to->externalUpdateFinish();
- return to->toOriginalFile();
+ file.write(QJsonDocument(obj).toJson());
+ file.close();
+
+ return true;
}
diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h
index 0b9f9c77..eb8ecd79 100644
--- a/logic/ForgeInstaller.h
+++ b/logic/ForgeInstaller.h
@@ -14,17 +14,22 @@
*/
#pragma once
+
+#include "BaseInstaller.h"
+
#include <QString>
#include <memory>
class OneSixVersion;
-class ForgeInstaller
+class ForgeInstaller : public BaseInstaller
{
public:
ForgeInstaller(QString filename, QString universal_url);
- bool apply(std::shared_ptr<OneSixVersion> to);
+ bool add(OneSixInstance *to) override;
+
+ QString id() const override { return "net.minecraftforge"; }
private:
// the version, read from the installer
diff --git a/logic/InstanceFactory.cpp b/logic/InstanceFactory.cpp
index 1f1a5879..807bccd0 100644
--- a/logic/InstanceFactory.cpp
+++ b/logic/InstanceFactory.cpp
@@ -24,6 +24,7 @@
#include "OneSixInstance.h"
#include "OneSixFTBInstance.h"
#include "NostalgiaInstance.h"
+#include "OneSixInstance.h"
#include "BaseVersion.h"
#include "MinecraftVersion.h"
@@ -50,13 +51,13 @@ InstanceFactory::InstLoadError InstanceFactory::loadInstance(BaseInstance *&inst
QString inst_type = m_settings->get("InstanceType").toString();
// FIXME: replace with a map lookup, where instance classes register their types
- if (inst_type == "Legacy")
+ if (inst_type == "OneSix")
{
- inst = new LegacyInstance(instDir, m_settings, this);
+ inst = new OneSixInstance(instDir, m_settings, this);
}
- else if (inst_type == "OneSix")
+ else if (inst_type == "Legacy")
{
- inst = new OneSixInstance(instDir, m_settings, this);
+ inst = new LegacyInstance(instDir, m_settings, this);
}
else if (inst_type == "Nostalgia")
{
@@ -101,6 +102,7 @@ InstanceFactory::InstCreateError InstanceFactory::createInstance(BaseInstance *&
switch (mcVer->type)
{
case MinecraftVersion::Legacy:
+ // TODO new instance type
m_settings->set("InstanceType", "Legacy");
inst = new LegacyInstance(instDir, m_settings, this);
inst->setIntendedVersionId(version->descriptor());
diff --git a/logic/LiteLoaderInstaller.cpp b/logic/LiteLoaderInstaller.cpp
index 07fffff3..1ce9d3f4 100644
--- a/logic/LiteLoaderInstaller.cpp
+++ b/logic/LiteLoaderInstaller.cpp
@@ -15,12 +15,19 @@
#include "LiteLoaderInstaller.h"
+#include <QJsonArray>
+#include <QJsonDocument>
+
+#include "logger/QsLog.h"
+
#include "OneSixVersion.h"
#include "OneSixLibrary.h"
+#include "OneSixInstance.h"
QMap<QString, QString> LiteLoaderInstaller::m_launcherWrapperVersionMapping;
-LiteLoaderInstaller::LiteLoaderInstaller(const QString &mcVersion) : m_mcVersion(mcVersion)
+LiteLoaderInstaller::LiteLoaderInstaller()
+ : BaseInstaller()
{
if (m_launcherWrapperVersionMapping.isEmpty())
{
@@ -31,72 +38,55 @@ LiteLoaderInstaller::LiteLoaderInstaller(const QString &mcVersion) : m_mcVersion
}
}
-bool LiteLoaderInstaller::canApply() const
+bool LiteLoaderInstaller::canApply(OneSixInstance *instance) const
{
- return m_launcherWrapperVersionMapping.contains(m_mcVersion);
+ return m_launcherWrapperVersionMapping.contains(instance->intendedVersionId());
}
-bool LiteLoaderInstaller::apply(std::shared_ptr<OneSixVersion> to)
+bool LiteLoaderInstaller::add(OneSixInstance *to)
{
- to->externalUpdateStart();
-
- applyLaunchwrapper(to);
- applyLiteLoader(to);
-
- to->mainClass = "net.minecraft.launchwrapper.Launch";
- if (!to->minecraftArguments.contains(
- " --tweakClass com.mumfrey.liteloader.launch.LiteLoaderTweaker"))
+ if (!BaseInstaller::add(to))
{
- to->minecraftArguments.append(
- " --tweakClass com.mumfrey.liteloader.launch.LiteLoaderTweaker");
+ return false;
}
- to->externalUpdateFinish();
- return to->toOriginalFile();
-}
+ QJsonObject obj;
-void LiteLoaderInstaller::applyLaunchwrapper(std::shared_ptr<OneSixVersion> to)
-{
- const QString intendedVersion = m_launcherWrapperVersionMapping[m_mcVersion];
+ obj.insert("mainClass", QString("net.minecraft.launchwrapper.Launch"));
+ obj.insert("+minecraftArguments", QString(" --tweakClass com.mumfrey.liteloader.launch.LiteLoaderTweaker"));
+ obj.insert("order", 10);
- QMutableListIterator<std::shared_ptr<OneSixLibrary>> it(to->libraries);
- while (it.hasNext())
+ QJsonArray libraries;
+
+ // launchwrapper
{
- it.next();
- if (it.value()->rawName().startsWith("net.minecraft:launchwrapper:"))
- {
- if (it.value()->version() >= intendedVersion)
- {
- return;
- }
- else
- {
- it.remove();
- }
- }
+ OneSixLibrary launchwrapperLib("net.minecraft:launchwrapper:" + m_launcherWrapperVersionMapping[to->intendedVersionId()]);
+ launchwrapperLib.finalize();
+ QJsonObject lwLibObj = launchwrapperLib.toJson();
+ lwLibObj.insert("insert", QString("prepend"));
+ libraries.append(lwLibObj);
}
- std::shared_ptr<OneSixLibrary> lib(new OneSixLibrary(
- "net.minecraft:launchwrapper:" + m_launcherWrapperVersionMapping[m_mcVersion]));
- lib->finalize();
- to->libraries.prepend(lib);
-}
+ // liteloader
+ {
+ OneSixLibrary liteloaderLib("com.mumfrey:liteloader:" + to->intendedVersionId());
+ liteloaderLib.setBaseUrl("http://dl.liteloader.com/versions/");
+ liteloaderLib.finalize();
+ QJsonObject llLibObj = liteloaderLib.toJson();
+ llLibObj.insert("insert", QString("prepend"));
+ libraries.append(llLibObj);
+ }
-void LiteLoaderInstaller::applyLiteLoader(std::shared_ptr<OneSixVersion> to)
-{
- QMutableListIterator<std::shared_ptr<OneSixLibrary>> it(to->libraries);
- while (it.hasNext())
+ obj.insert("+libraries", libraries);
+
+ QFile file(filename(to->instanceRoot()));
+ if (!file.open(QFile::WriteOnly))
{
- it.next();
- if (it.value()->rawName().startsWith("com.mumfrey:liteloader:"))
- {
- it.remove();
- }
+ QLOG_ERROR() << "Error opening" << file.fileName() << "for reading:" << file.errorString();
+ return false;
}
+ file.write(QJsonDocument(obj).toJson());
+ file.close();
- std::shared_ptr<OneSixLibrary> lib(
- new OneSixLibrary("com.mumfrey:liteloader:" + m_mcVersion));
- lib->setBaseUrl("http://dl.liteloader.com/versions/");
- lib->finalize();
- to->libraries.prepend(lib);
+ return true;
}
diff --git a/logic/LiteLoaderInstaller.h b/logic/LiteLoaderInstaller.h
index 44b306d6..5e01b16c 100644
--- a/logic/LiteLoaderInstaller.h
+++ b/logic/LiteLoaderInstaller.h
@@ -14,26 +14,22 @@
*/
#pragma once
+
+#include "BaseInstaller.h"
+
#include <QString>
#include <QMap>
-#include <memory>
-
-class OneSixVersion;
-class LiteLoaderInstaller
+class LiteLoaderInstaller : public BaseInstaller
{
public:
- LiteLoaderInstaller(const QString &mcVersion);
+ LiteLoaderInstaller();
- bool canApply() const;
-
- bool apply(std::shared_ptr<OneSixVersion> to);
+ bool canApply(OneSixInstance *instance) const override;
+ bool add(OneSixInstance *to) override;
private:
- QString m_mcVersion;
-
- void applyLaunchwrapper(std::shared_ptr<OneSixVersion> to);
- void applyLiteLoader(std::shared_ptr<OneSixVersion> to);
+ virtual QString id() const override { return "com.mumfrey.liteloader"; }
static QMap<QString, QString> m_launcherWrapperVersionMapping;
};
diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp
index e50a5b53..71bc1470 100644
--- a/logic/OneSixFTBInstance.cpp
+++ b/logic/OneSixFTBInstance.cpp
@@ -60,10 +60,8 @@ slots:
emitFailed(tr("Couldn't load the version config"));
return;
}
- instance->revertCustomVersion();
- instance->customizeVersion();
auto version = instance->getFullVersion();
- if (!forge.apply(version))
+ if (!forge.add(instance))
{
emitFailed(tr("Couldn't install Forge"));
return;
diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp
index ab87a1db..c43a5187 100644
--- a/logic/OneSixInstance.cpp
+++ b/logic/OneSixInstance.cpp
@@ -13,32 +13,36 @@
* limitations under the License.
*/
-#include "MultiMC.h"
#include "OneSixInstance.h"
+
+#include <QIcon>
+
#include "OneSixInstance_p.h"
#include "OneSixUpdate.h"
-#include "MinecraftProcess.h"
#include "OneSixVersion.h"
-#include "JavaChecker.h"
-#include "logic/icons/IconList.h"
-
-#include <setting.h>
-#include <pathutils.h>
-#include <cmdutils.h>
-#include <JlCompress.h>
-#include "gui/dialogs/OneSixModEditDialog.h"
+#include "pathutils.h"
#include "logger/QsLog.h"
-#include "logic/assets/AssetsUtils.h"
-#include <QIcon>
+#include "assets/AssetsUtils.h"
+#include "MultiMC.h"
+#include "icons/IconList.h"
+#include "MinecraftProcess.h"
+#include "gui/dialogs/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 *settings, QObject *parent)
+ : BaseInstance(new OneSixInstancePrivate(), rootDir, settings, parent)
{
I_D(OneSixInstance);
d->m_settings->registerSetting("IntendedVersion", "");
d->m_settings->registerSetting("ShouldUpdate", false);
- reloadFullVersion();
+ d->version.reset(new OneSixVersion(this, this));
+ if (QDir(instanceRoot()).exists("version.json"))
+ {
+ reloadFullVersion();
+ }
+ else
+ {
+ clearFullVersion();
+ }
}
std::shared_ptr<Task> OneSixInstance::doUpdate(bool only_prepare)
@@ -282,11 +286,8 @@ bool OneSixInstance::setIntendedVersionId(QString version)
{
settings().set("IntendedVersion", version);
setShouldUpdate(true);
- auto pathCustom = PathCombine(instanceRoot(), "custom.json");
- auto pathOrig = PathCombine(instanceRoot(), "version.json");
- QFile::remove(pathCustom);
- QFile::remove(pathOrig);
- reloadFullVersion();
+ QFile::remove(PathCombine(instanceRoot(), "version.json"));
+ clearFullVersion();
return true;
}
@@ -312,9 +313,9 @@ bool OneSixInstance::shouldUpdate() const
bool OneSixInstance::versionIsCustom()
{
- QString verpath_custom = PathCombine(instanceRoot(), "custom.json");
- QFile versionfile(verpath_custom);
- return versionfile.exists();
+ QDir patches(PathCombine(instanceRoot(), "patches/"));
+ return QFile::exists(PathCombine(instanceRoot(), "custom.json"))
+ || (patches.exists() && patches.count() >= 0);
}
QString OneSixInstance::currentVersionId() const
@@ -322,54 +323,20 @@ QString OneSixInstance::currentVersionId() const
return intendedVersionId();
}
-bool OneSixInstance::customizeVersion()
+bool OneSixInstance::reloadFullVersion(QWidget *widgetParent)
{
- if (!versionIsCustom())
- {
- auto pathCustom = PathCombine(instanceRoot(), "custom.json");
- auto pathOrig = PathCombine(instanceRoot(), "version.json");
- QFile::copy(pathOrig, pathCustom);
- return reloadFullVersion();
- }
- else
- return true;
-}
+ I_D(OneSixInstance);
-bool OneSixInstance::revertCustomVersion()
-{
- if (versionIsCustom())
- {
- auto path = PathCombine(instanceRoot(), "custom.json");
- QFile::remove(path);
- return reloadFullVersion();
- }
- else
- return true;
+ bool ret = d->version->reload(widgetParent);
+ emit versionReloaded();
+ return ret;
}
-bool OneSixInstance::reloadFullVersion()
+void OneSixInstance::clearFullVersion()
{
I_D(OneSixInstance);
-
- QString verpath = PathCombine(instanceRoot(), "version.json");
- {
- QString verpath_custom = PathCombine(instanceRoot(), "custom.json");
- QFile versionfile(verpath_custom);
- if (versionfile.exists())
- verpath = verpath_custom;
- }
-
- auto version = OneSixVersion::fromFile(verpath);
- if (version)
- {
- d->version = version;
- return true;
- }
- else
- {
- d->version.reset();
- return false;
- }
+ d->version->clear();
+ emit versionReloaded();
}
std::shared_ptr<OneSixVersion> OneSixInstance::getFullVersion()
@@ -397,7 +364,7 @@ bool OneSixInstance::menuActionEnabled(QString action_name) const
QString OneSixInstance::getStatusbarDescription()
{
- QString descr = "One Six : " + intendedVersionId();
+ QString descr = "OneSix : " + intendedVersionId();
if (versionIsCustom())
{
descr + " (custom)";
diff --git a/logic/OneSixInstance.h b/logic/OneSixInstance.h
index f869e345..94577828 100644
--- a/logic/OneSixInstance.h
+++ b/logic/OneSixInstance.h
@@ -15,21 +15,17 @@
#pragma once
-#include <QStringList>
-#include <QDir>
-
#include "BaseInstance.h"
-class OneSixVersion;
-class Task;
-class ModList;
+#include "OneSixVersion.h"
+#include "ModList.h"
class OneSixInstance : public BaseInstance
{
Q_OBJECT
public:
explicit OneSixInstance(const QString &rootDir, SettingsObject *settings,
- QObject *parent = 0);
+ QObject *parent = 0);
////// Mod Lists //////
std::shared_ptr<ModList> loaderModList();
@@ -55,14 +51,12 @@ public:
virtual QDialog *createModEditDialog(QWidget *parent) override;
- /// reload the full version json file. return true on success!
- bool reloadFullVersion();
+ /// reload the full version json files. return true on success!
+ bool reloadFullVersion(QWidget *widgetParent = 0);
+ /// clears all version information in preparation for an update
+ void clearFullVersion();
/// get the current full version info
std::shared_ptr<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?
virtual bool versionIsCustom() override;
@@ -72,6 +66,9 @@ public:
virtual bool menuActionEnabled(QString action_name) const override;
virtual QString getStatusbarDescription() override;
+signals:
+ void versionReloaded();
+
private:
QStringList processMinecraftArgs(MojangAccountPtr account);
QDir reconstructAssets(std::shared_ptr<OneSixVersion> version);
diff --git a/logic/OneSixInstance_p.h b/logic/OneSixInstance_p.h
index 6b7ea431..a2b70ac9 100644
--- a/logic/OneSixInstance_p.h
+++ b/logic/OneSixInstance_p.h
@@ -15,16 +15,13 @@
#pragma once
-#include <memory>
-
-#include "logic/BaseInstance_p.h"
-#include "logic/OneSixVersion.h"
-#include "logic/OneSixLibrary.h"
-#include "logic/ModList.h"
+#include "BaseInstance_p.h"
+#include "OneSixVersion.h"
+#include "ModList.h"
struct OneSixInstancePrivate : public BaseInstancePrivate
{
std::shared_ptr<OneSixVersion> version;
std::shared_ptr<ModList> loader_mod_list;
std::shared_ptr<ModList> resource_pack_list;
-}; \ No newline at end of file
+};
diff --git a/logic/OneSixLibrary.cpp b/logic/OneSixLibrary.cpp
index 7b80d5e7..4d892d53 100644
--- a/logic/OneSixLibrary.cpp
+++ b/logic/OneSixLibrary.cpp
@@ -76,11 +76,11 @@ void OneSixLibrary::finalize()
}
}
-void OneSixLibrary::setName(QString name)
+void OneSixLibrary::setName(const QString &name)
{
m_name = name;
}
-void OneSixLibrary::setBaseUrl(QString base_url)
+void OneSixLibrary::setBaseUrl(const QString &base_url)
{
m_base_url = base_url;
}
@@ -88,7 +88,7 @@ void OneSixLibrary::setIsNative()
{
m_is_native = true;
}
-void OneSixLibrary::addNative(OpSys os, QString suffix)
+void OneSixLibrary::addNative(OpSys os, const QString &suffix)
{
m_is_native = true;
m_native_suffixes[os] = suffix;
@@ -97,41 +97,41 @@ void OneSixLibrary::setRules(QList<std::shared_ptr<Rule>> rules)
{
m_rules = rules;
}
-bool OneSixLibrary::isActive()
+bool OneSixLibrary::isActive() const
{
return m_is_active;
}
-bool OneSixLibrary::isNative()
+bool OneSixLibrary::isNative() const
{
return m_is_native;
}
-QString OneSixLibrary::downloadUrl()
+QString OneSixLibrary::downloadUrl() const
{
if (m_absolute_url.size())
return m_absolute_url;
return m_download_url;
}
-QString OneSixLibrary::storagePath()
+QString OneSixLibrary::storagePath() const
{
return m_storage_path;
}
-void OneSixLibrary::setAbsoluteUrl(QString absolute_url)
+void OneSixLibrary::setAbsoluteUrl(const QString &absolute_url)
{
m_absolute_url = absolute_url;
}
-QString OneSixLibrary::absoluteUrl()
+QString OneSixLibrary::absoluteUrl() const
{
return m_absolute_url;
}
-void OneSixLibrary::setHint(QString hint)
+void OneSixLibrary::setHint(const QString &hint)
{
m_hint = hint;
}
-QString OneSixLibrary::hint()
+QString OneSixLibrary::hint() const
{
return m_hint;
}
diff --git a/logic/OneSixLibrary.h b/logic/OneSixLibrary.h
index 227cdbef..52f89969 100644
--- a/logic/OneSixLibrary.h
+++ b/logic/OneSixLibrary.h
@@ -63,7 +63,7 @@ public:
public:
/// Constructor
- OneSixLibrary(QString name)
+ OneSixLibrary(const QString &name)
{
m_name = name;
}
@@ -84,48 +84,48 @@ public:
void finalize();
/// Set the library composite name
- void setName(QString name);
+ void setName(const QString &name);
/// get a decent-looking name
- QString name()
+ QString name() const
{
return m_decentname;
}
/// get a decent-looking version
- QString version()
+ QString version() const
{
return m_decentversion;
}
/// what kind of library is it? (for display)
- QString type()
+ QString type() const
{
return m_decenttype;
}
/// Set the url base for downloads
- void setBaseUrl(QString base_url);
+ void setBaseUrl(const QString &base_url);
/// Call this to mark the library as 'native' (it's a zip archive with DLLs)
void setIsNative();
/// Attach a name suffix to the specified OS native
- void addNative(OpSys os, QString suffix);
+ void addNative(OpSys os, const QString &suffix);
/// Set the load rules
void setRules(QList<std::shared_ptr<Rule>> rules);
/// Returns true if the library should be loaded (or extracted, in case of natives)
- bool isActive();
+ bool isActive() const;
/// Returns true if the library is native
- bool isNative();
+ bool isNative() const;
/// Get the URL to download the library from
- QString downloadUrl();
+ QString downloadUrl() const;
/// Get the relative path where the library should be saved
- QString storagePath();
+ QString storagePath() const;
/// set an absolute URL for the library. This is an MMC extension.
- void setAbsoluteUrl(QString absolute_url);
- QString absoluteUrl();
+ void setAbsoluteUrl(const QString &absolute_url);
+ QString absoluteUrl() const;
/// set a hint about how to treat the library. This is an MMC extension.
- void setHint(QString hint);
- QString hint();
+ void setHint(const QString &hint);
+ QString hint() const;
bool extractTo(QString target_dir);
bool filesExist();
diff --git a/logic/OneSixRule.cpp b/logic/OneSixRule.cpp
index 392b1dd1..d8d13b50 100644
--- a/logic/OneSixRule.cpp
+++ b/logic/OneSixRule.cpp
@@ -18,7 +18,7 @@
#include "OneSixRule.h"
-QList<std::shared_ptr<Rule>> rulesFromJsonV4(QJsonObject &objectWithRules)
+QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules)
{
QList<std::shared_ptr<Rule>> rules;
auto rulesVal = objectWithRules.value("rules");
@@ -86,4 +86,4 @@ RuleAction RuleAction_fromString(QString name)
if (name == "disallow")
return Disallow;
return Defer;
-} \ No newline at end of file
+}
diff --git a/logic/OneSixRule.h b/logic/OneSixRule.h
index 5a13cbd9..426e2886 100644
--- a/logic/OneSixRule.h
+++ b/logic/OneSixRule.h
@@ -27,7 +27,7 @@ enum RuleAction
};
RuleAction RuleAction_fromString(QString);
-QList<std::shared_ptr<Rule>> rulesFromJsonV4(QJsonObject &objectWithRules);
+QList<std::shared_ptr<Rule>> rulesFromJsonV4(const QJsonObject &objectWithRules);
class Rule
{
diff --git a/logic/OneSixUpdate.cpp b/logic/OneSixUpdate.cpp
index ae647bfe..f51b6c23 100644
--- a/logic/OneSixUpdate.cpp
+++ b/logic/OneSixUpdate.cpp
@@ -335,13 +335,13 @@ void OneSixUpdate::prepareForLaunch()
{
setStatus(tr("Preparing for launch..."));
QLOG_INFO() << m_inst->name() << ": preparing for launch";
- auto onesix_inst = (OneSixInstance *)m_inst;
+ auto OneSix_inst = (OneSixInstance *)m_inst;
// delete any leftovers, if they are present.
- onesix_inst->cleanupAfterRun();
+ OneSix_inst->cleanupAfterRun();
- QString natives_dir_raw = PathCombine(onesix_inst->instanceRoot(), "natives/");
- auto version = onesix_inst->getFullVersion();
+ QString natives_dir_raw = PathCombine(OneSix_inst->instanceRoot(), "natives/");
+ auto version = OneSix_inst->getFullVersion();
if (!version)
{
emitFailed("The version information for this instance is not complete. Try re-creating "
diff --git a/logic/OneSixVersion.cpp b/logic/OneSixVersion.cpp
index 8ae685f0..3db3bd77 100644
--- a/logic/OneSixVersion.cpp
+++ b/logic/OneSixVersion.cpp
@@ -13,228 +13,60 @@
* limitations under the License.
*/
-#include "logic/OneSixVersion.h"
-#include "logic/OneSixLibrary.h"
-#include "logic/OneSixRule.h"
+#include "OneSixVersion.h"
-#include "logger/QsLog.h"
+#include <QDebug>
-std::shared_ptr<OneSixVersion> fromJsonV4(QJsonObject root,
- std::shared_ptr<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();
-
- auto assetsID = root.value("assets");
- if (assetsID.isString())
- {
- fullVersion->assets = assetsID.toString();
- }
- else
- {
- fullVersion->assets = "legacy";
- }
-
- QLOG_DEBUG() << "Assets version:" << fullVersion->assets;
-
- // 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;
- std::shared_ptr<OneSixLibrary> library(new OneSixLibrary(nameVal.toString()));
-
- auto urlVal = libObj.value("url");
- if (urlVal.isString())
- {
- library->setBaseUrl(urlVal.toString());
- }
- auto hintVal = libObj.value("MMC-hint");
- if (hintVal.isString())
- {
- library->setHint(hintVal.toString());
- }
- auto urlAbsVal = libObj.value("MMC-absoluteUrl");
- auto urlAbsuVal = libObj.value("MMC-absulute_url"); // compatibility
- if (urlAbsVal.isString())
- {
- library->setAbsoluteUrl(urlAbsVal.toString());
- }
- else if (urlAbsuVal.isString())
- {
- library->setAbsoluteUrl(urlAbsuVal.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;
- }
- }
+#include "OneSixVersionBuilder.h"
- 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;
+OneSixVersion::OneSixVersion(OneSixInstance *instance, QObject *parent)
+ : QAbstractListModel(parent), m_instance(instance)
+{
+ clear();
}
-std::shared_ptr<OneSixVersion> OneSixVersion::fromJson(QJsonObject root)
+bool OneSixVersion::reload(QWidget *widgetParent)
{
- std::shared_ptr<OneSixVersion> readVersion(new OneSixVersion());
- int launcher_ver = readVersion->minimumLauncherVersion =
- root.value("minimumLauncherVersion").toDouble();
-
- // ADD MORE HERE :D
- if (launcher_ver > 0 && launcher_ver <= 13)
- return fromJsonV4(root, readVersion);
- else
- {
- return std::shared_ptr<OneSixVersion>();
- }
+ return OneSixVersionBuilder::build(this, m_instance, widgetParent);
}
-std::shared_ptr<OneSixVersion> OneSixVersion::fromFile(QString filepath)
+void OneSixVersion::clear()
{
- QFile file(filepath);
- if (!file.open(QIODevice::ReadOnly))
- {
- return std::shared_ptr<OneSixVersion>();
- }
-
- auto data = file.readAll();
- QJsonParseError jsonError;
- QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
-
- if (jsonError.error != QJsonParseError::NoError)
- {
- return std::shared_ptr<OneSixVersion>();
- }
-
- if (!jsonDoc.isObject())
- {
- return std::shared_ptr<OneSixVersion>();
- }
- QJsonObject root = jsonDoc.object();
- auto version = fromJson(root);
- if (version)
- version->original_file = filepath;
- return version;
+ id.clear();
+ time.clear();
+ releaseTime.clear();
+ type.clear();
+ assets.clear();
+ processArguments.clear();
+ minecraftArguments.clear();
+ minimumLauncherVersion = 0xDEADBEAF;
+ mainClass.clear();
+ libraries.clear();
}
-bool OneSixVersion::toOriginalFile()
+void OneSixVersion::dump() const
{
- 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)
+ qDebug().nospace() << "OneSixVersion("
+ << "\n\tid=" << id
+ << "\n\ttime=" << time
+ << "\n\treleaseTime=" << releaseTime
+ << "\n\ttype=" << type
+ << "\n\tassets=" << assets
+ << "\n\tprocessArguments=" << processArguments
+ << "\n\tminecraftArguments=" << minecraftArguments
+ << "\n\tminimumLauncherVersion=" << minimumLauncherVersion
+ << "\n\tmainClass=" << mainClass
+ << "\n\tlibraries=";
+ for (auto lib : libraries)
{
- libarray.append(lib->toJson());
+ qDebug().nospace() << "\n\t\t" << lib.get();
}
- if (libarray.count())
- root.insert("libraries", libarray);
- QJsonDocument doc(root);
- file.write(doc.toJson());
- return file.commit();
+ qDebug().nospace() << "\n)";
}
-QList<std::shared_ptr<OneSixLibrary>> OneSixVersion::getActiveNormalLibs()
+QList<std::shared_ptr<OneSixLibrary> > OneSixVersion::getActiveNormalLibs()
{
- QList<std::shared_ptr<OneSixLibrary>> output;
+ QList<std::shared_ptr<OneSixLibrary> > output;
for (auto lib : libraries)
{
if (lib->isActive() && !lib->isNative())
@@ -245,9 +77,9 @@ QList<std::shared_ptr<OneSixLibrary>> OneSixVersion::getActiveNormalLibs()
return output;
}
-QList<std::shared_ptr<OneSixLibrary>> OneSixVersion::getActiveNativeLibs()
+QList<std::shared_ptr<OneSixLibrary> > OneSixVersion::getActiveNativeLibs()
{
- QList<std::shared_ptr<OneSixLibrary>> output;
+ QList<std::shared_ptr<OneSixLibrary> > output;
for (auto lib : libraries)
{
if (lib->isActive() && lib->isNative())
@@ -258,14 +90,14 @@ QList<std::shared_ptr<OneSixLibrary>> OneSixVersion::getActiveNativeLibs()
return output;
}
-void OneSixVersion::externalUpdateStart()
-{
- beginResetModel();
-}
-
-void OneSixVersion::externalUpdateFinish()
+std::shared_ptr<OneSixVersion> OneSixVersion::fromJson(const QJsonObject &obj)
{
- endResetModel();
+ std::shared_ptr<OneSixVersion> version(new OneSixVersion(0));
+ if (OneSixVersionBuilder::read(version.get(), obj))
+ {
+ return version;
+ }
+ return 0;
}
QVariant OneSixVersion::data(const QModelIndex &index, int role) const
@@ -338,3 +170,25 @@ int OneSixVersion::columnCount(const QModelIndex &parent) const
{
return 3;
}
+
+QDebug operator<<(QDebug &dbg, const OneSixVersion *version)
+{
+ version->dump();
+ return dbg.maybeSpace();
+}
+QDebug operator<<(QDebug &dbg, const OneSixLibrary *library)
+{
+ dbg.nospace() << "OneSixLibrary("
+ << "\n\t\t\trawName=" << library->rawName()
+ << "\n\t\t\tname=" << library->name()
+ << "\n\t\t\tversion=" << library->version()
+ << "\n\t\t\ttype=" << library->type()
+ << "\n\t\t\tisActive=" << library->isActive()
+ << "\n\t\t\tisNative=" << library->isNative()
+ << "\n\t\t\tdownloadUrl=" << library->downloadUrl()
+ << "\n\t\t\tstoragePath=" << library->storagePath()
+ << "\n\t\t\tabsolutePath=" << library->absoluteUrl()
+ << "\n\t\t\thint=" << library->hint();
+ dbg.nospace() << "\n\t\t)";
+ return dbg.maybeSpace();
+}
diff --git a/logic/OneSixVersion.h b/logic/OneSixVersion.h
index 036f3d53..00afd010 100644
--- a/logic/OneSixVersion.h
+++ b/logic/OneSixVersion.h
@@ -14,15 +14,23 @@
*/
#pragma once
-#include <QtCore>
+
+#include <QAbstractListModel>
+
+#include <QString>
+#include <QList>
#include <memory>
-class OneSixLibrary;
+#include "OneSixLibrary.h"
+
+class OneSixInstance;
class OneSixVersion : public QAbstractListModel
{
- // Things required to implement the Qt list model
+ Q_OBJECT
public:
+ explicit OneSixVersion(OneSixInstance *instance, QObject *parent = 0);
+
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,
@@ -30,24 +38,19 @@ public:
virtual int columnCount(const QModelIndex &parent) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
- // serialization/deserialization
-public:
- bool toOriginalFile();
- static std::shared_ptr<OneSixVersion> fromJson(QJsonObject root);
- static std::shared_ptr<OneSixVersion> fromFile(QString filepath);
+ bool reload(QWidget *widgetParent);
+ void clear();
+
+ void dump() const;
public:
QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs();
QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs();
- // called when something starts/stops messing with the object
- // FIXME: these are ugly in every possible way.
- void externalUpdateStart();
- void externalUpdateFinish();
+
+ static std::shared_ptr<OneSixVersion> fromJson(const QJsonObject &obj);
// 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
@@ -103,4 +106,10 @@ public:
}
*/
// QList<Rule> rules;
+
+private:
+ OneSixInstance *m_instance;
};
+
+QDebug operator<<(QDebug &dbg, const OneSixVersion *version);
+QDebug operator<<(QDebug &dbg, const OneSixLibrary *library);
diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp
new file mode 100644
index 00000000..85f55a52
--- /dev/null
+++ b/logic/OneSixVersionBuilder.cpp
@@ -0,0 +1,446 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "OneSixVersionBuilder.h"
+
+#include <QList>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QFile>
+#include <QFileInfo>
+#include <QMessageBox>
+#include <QObject>
+#include <QDir>
+#include <QDebug>
+
+#include "OneSixVersion.h"
+#include "OneSixInstance.h"
+#include "OneSixRule.h"
+#include "logger/QsLog.h"
+
+OneSixVersionBuilder::OneSixVersionBuilder()
+{
+
+}
+
+bool OneSixVersionBuilder::build(OneSixVersion *version, OneSixInstance *instance, QWidget *widgetParent)
+{
+ OneSixVersionBuilder builder;
+ builder.m_version = version;
+ builder.m_instance = instance;
+ builder.m_widgetParent = widgetParent;
+ return builder.build();
+}
+
+bool OneSixVersionBuilder::read(OneSixVersion *version, const QJsonObject &obj)
+{
+ OneSixVersionBuilder builder;
+ builder.m_version = version;
+ builder.m_instance = 0;
+ builder.m_widgetParent = 0;
+ return builder.read(obj);
+}
+
+bool OneSixVersionBuilder::build()
+{
+ m_version->clear();
+
+ QDir root(m_instance->instanceRoot());
+ QDir patches(root.absoluteFilePath("patches/"));
+
+ // version.json -> patches/*.json -> custom.json
+
+ // version.json
+ {
+ QLOG_INFO() << "Reading version.json";
+ QJsonObject obj;
+ if (!read(QFileInfo(root.absoluteFilePath("version.json")), &obj))
+ {
+ return false;
+ }
+ if (!apply(obj))
+ {
+ return false;
+ }
+ }
+
+ // patches/
+ {
+ // load all, put into map for ordering, apply in the right order
+
+ QMap<int, QJsonObject> objects;
+ for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
+ {
+ QLOG_INFO() << "Reading" << info.fileName();
+ QJsonObject obj;
+ if (!read(info, &obj))
+ {
+ return false;
+ }
+ if (!obj.contains("order") || !obj.value("order").isDouble())
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Missing or invalid 'order' in %1").arg(info.absoluteFilePath()));
+ return false;
+ }
+ objects.insert(obj.value("order").toDouble(), obj);
+ }
+ for (auto object : objects.values())
+ {
+ qDebug() << "Applying object with order" << objects.key(object);
+ if (!apply(object))
+ {
+ return false;
+ }
+ }
+ }
+
+ // custom.json
+ {
+ if (QFile::exists(root.absoluteFilePath("custom.json")))
+ {
+ QLOG_INFO() << "Reading custom.json";
+ QJsonObject obj;
+ if (!read(QFileInfo(root.absoluteFilePath("custom.json")), &obj))
+ {
+ return false;
+ }
+ if (!apply(obj))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool OneSixVersionBuilder::read(const QJsonObject &obj)
+{
+ m_version->clear();
+
+ return apply(obj);
+}
+
+void applyString(const QJsonObject &obj, const QString &key, QString &out, const bool onlyOverride = true)
+{
+ if (obj.contains(key) && obj.value(key).isString())
+ {
+ out = obj.value(key).toString();
+ }
+ else if (!onlyOverride)
+ {
+ if (obj.contains("+" + key) && obj.value("+" + key).isString())
+ {
+ out += obj.value("+" + key).toString();
+ }
+ else if (obj.contains("-" + key) && obj.value("-" + key).isString())
+ {
+ out.remove(obj.value("-" + key).toString());
+ }
+ }
+}
+void applyString(const QJsonObject &obj, const QString &key, std::shared_ptr<OneSixLibrary> lib, void(OneSixLibrary::*func)(const QString &val))
+{
+ if (obj.contains(key) && obj.value(key).isString())
+ {
+ (lib.get()->*func)(obj.value(key).toString());
+ }
+}
+bool OneSixVersionBuilder::apply(const QJsonObject &object)
+{
+ applyString(object, "id", m_version->id);
+ applyString(object, "mainClass", m_version->mainClass);
+ applyString(object, "minecraftArguments", m_version->minecraftArguments, false);
+ applyString(object, "processArguments", m_version->processArguments, false);
+ if (m_version->minecraftArguments.isEmpty())
+ {
+ const QString toCompare = m_version->processArguments.toLower();
+ if (toCompare == "legacy")
+ {
+ m_version->minecraftArguments = " ${auth_player_name} ${auth_session}";
+ }
+ else if (toCompare == "username_session")
+ {
+ m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session}";
+ }
+ else if (toCompare == "username_session_version")
+ {
+ m_version->minecraftArguments = "--username ${auth_player_name} --session ${auth_session} --version ${profile_name}";
+ }
+ }
+ applyString(object, "type", m_version->type);
+ applyString(object, "releaseTime", m_version->releaseTime);
+ applyString(object, "time", m_version->time);
+ applyString(object, "assets", m_version->assets);
+ {
+ if (m_version->assets.isEmpty())
+ {
+ m_version->assets = "legacy";
+ }
+ }
+ if (object.contains("minimumLauncherVersion"))
+ {
+ auto minLauncherVersionVal = object.value("minimumLauncherVersion");
+ if (minLauncherVersionVal.isDouble())
+ {
+ m_version->minimumLauncherVersion = minLauncherVersionVal.toDouble();
+ }
+ }
+
+ // libraries
+ if (object.contains("libraries"))
+ {
+ m_version->libraries.clear();
+ auto librariesValue = object.value("libraries");
+ if (!librariesValue.isArray())
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
+ return false;
+ }
+ auto array = librariesValue.toArray();
+ for (auto libVal : array)
+ {
+ if (libVal.isObject())
+ {
+ if (!applyLibrary(libVal.toObject(), Override))
+ {
+ return false;
+ }
+ }
+
+ }
+ }
+
+ // +libraries
+ if (object.contains("+libraries"))
+ {
+ auto librariesValue = object.value("+libraries");
+ if (!librariesValue.isArray())
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
+ return false;
+ }
+ for (auto libVal : librariesValue.toArray())
+ {
+ if (libVal.isObject())
+ {
+ applyLibrary(libVal.toObject(), Add);
+ }
+
+ }
+ }
+
+ // -libraries
+ if (object.contains("-libraries"))
+ {
+ auto librariesValue = object.value("-libraries");
+ if (!librariesValue.isArray())
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("One json files contains a libraries field, but it's not an array"));
+ return false;
+ }
+ for (auto libVal : librariesValue.toArray())
+ {
+ if (libVal.isObject())
+ {
+ applyLibrary(libVal.toObject(), Remove);
+ }
+
+ }
+ }
+
+ return true;
+}
+
+int findLibrary(QList<std::shared_ptr<OneSixLibrary> > haystack, const QString &needle)
+{
+ for (int i = 0; i < haystack.size(); ++i)
+ {
+ if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(haystack.at(i)->rawName()) != -1)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool OneSixVersionBuilder::applyLibrary(const QJsonObject &lib, const OneSixVersionBuilder::Type type)
+{
+ // Library name
+ auto nameVal = lib.value("name");
+ if (!nameVal.isString())
+ {
+ return false;
+ }
+ auto name = nameVal.toString();
+
+ if (type == Remove)
+ {
+ int index = findLibrary(m_version->libraries, name);
+ if (index >= 0)
+ {
+ m_version->libraries.removeAt(index);
+ }
+ return true;
+ }
+
+ if (type == Add && !lib.contains("insert"))
+ {
+ return false;
+ }
+
+ std::shared_ptr<OneSixLibrary> library;
+
+ if (lib.value("insert").toString() != "apply" && type == Add)
+ {
+ QMutableListIterator<std::shared_ptr<OneSixLibrary> > it(m_version->libraries);
+ while (it.hasNext())
+ {
+ if (it.next()->rawName() == name)
+ {
+ it.remove();
+ }
+ }
+ }
+
+ if (lib.value("insert").toString() == "apply" && type == Add)
+ {
+ library = m_version->libraries[findLibrary(m_version->libraries, name)];
+ }
+ else
+ {
+ library.reset(new OneSixLibrary(nameVal.toString()));
+ }
+
+ applyString(lib, "url", library, &OneSixLibrary::setBaseUrl);
+ applyString(lib, "MMC-hint", library, &OneSixLibrary::setHint);
+ applyString(lib, "MMC-absulute_url", library, &OneSixLibrary::setAbsoluteUrl);
+ applyString(lib, "MMC-absoluteUrl", library, &OneSixLibrary::setAbsoluteUrl);
+
+ auto extractVal = lib.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 = lib.value("natives");
+ if (nativesVal.isObject())
+ {
+ library->setIsNative();
+ auto nativesObj = nativesVal.toObject();
+ for (auto it = nativesObj.begin(); it != nativesObj.end(); ++it)
+ {
+ auto osType = OpSys_fromString(it.key());
+ if (osType == Os_Other)
+ {
+ continue;
+ }
+ if (!it.value().isString())
+ {
+ continue;
+ }
+ library->addNative(osType, it.value().toString());
+ }
+ }
+
+ if (lib.contains("rules"))
+ {
+ library->setRules(rulesFromJsonV4(lib));
+ }
+ library->finalize();
+ if (type == Override)
+ {
+ m_version->libraries.append(library);
+ }
+ else if (lib.value("insert").toString() != "apply")
+ {
+ if (lib.value("insert").toString() == "append")
+ {
+ m_version->libraries.append(library);
+ }
+ else if (lib.value("insert").toString() == "prepend")
+ {
+ m_version->libraries.prepend(library);
+ }
+ else if (lib.value("insert").isObject())
+ {
+ QJsonObject insertObj = lib.value("insert").toObject();
+ if (insertObj.isEmpty())
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("'insert' object empty"));
+ return false;
+ }
+ const QString key = insertObj.keys().first();
+ const QString value = insertObj.value(key).toString();
+ const int index = findLibrary(m_version->libraries, value);
+ if (index >= 0)
+ {
+ if (key == "before")
+ {
+ m_version->libraries.insert(index, library);
+ }
+ else if (key == "after")
+ {
+ m_version->libraries.insert(index + 1, library);
+ }
+ else
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Invalid value for 'insert': %1").arg(lib.value("insert").toString()));
+ return false;
+ }
+ }
+ }
+ else
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Invalid value for 'insert': %1").arg(lib.value("insert").toString()));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool OneSixVersionBuilder::read(const QFileInfo &fileInfo, QJsonObject *out)
+{
+ QFile file(fileInfo.absoluteFilePath());
+ if (!file.open(QFile::ReadOnly))
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Unable to open %1: %2").arg(file.fileName(), file.errorString()));
+ return false;
+ }
+ QJsonParseError error;
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
+ if (error.error != QJsonParseError::NoError)
+ {
+ QMessageBox::critical(m_widgetParent, QObject::tr("Error"), QObject::tr("Unable to parse %1: %2 at %3").arg(file.fileName(), error.errorString()).arg(error.offset));
+ return false;
+ }
+ *out = doc.object();
+ return true;
+}
diff --git a/logic/OneSixVersionBuilder.h b/logic/OneSixVersionBuilder.h
new file mode 100644
index 00000000..a3ba331c
--- /dev/null
+++ b/logic/OneSixVersionBuilder.h
@@ -0,0 +1,53 @@
+/* Copyright 2013 MultiMC Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QString>
+
+class OneSixVersion;
+class OneSixInstance;
+class QWidget;
+class QJsonObject;
+class QFileInfo;
+
+class OneSixVersionBuilder
+{
+ OneSixVersionBuilder();
+public:
+ static bool build(OneSixVersion *version, OneSixInstance *instance, QWidget *widgetParent);
+ static bool read(OneSixVersion *version, const QJsonObject &obj);
+
+private:
+ OneSixVersion *m_version;
+ OneSixInstance *m_instance;
+ QWidget *m_widgetParent;
+
+ enum Type
+ {
+ Override,
+ Add,
+ Remove
+ };
+
+ bool build();
+ bool read(const QJsonObject &obj);
+
+ void clear();
+ bool apply(const QJsonObject &object);
+ bool applyLibrary(const QJsonObject &lib, const Type type);
+
+ bool read(const QFileInfo &fileInfo, QJsonObject *out);
+};