summaryrefslogtreecommitdiffstats
path: root/logic
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2014-03-19 22:26:25 +0100
committerPetr Mrázek <peterix@gmail.com>2014-03-19 22:26:25 +0100
commit39d37394423dc204efe774920a59ce010781b28c (patch)
tree2b961bcbb4d979790f40e88e45e2bd0f8ddb9140 /logic
parent26b485d82f03c0191142cf9b660b4ab43962878d (diff)
parent42a85def60036a5788a9dd862d0c6f835b62337c (diff)
downloadMultiMC-39d37394423dc204efe774920a59ce010781b28c.tar
MultiMC-39d37394423dc204efe774920a59ce010781b28c.tar.gz
MultiMC-39d37394423dc204efe774920a59ce010781b28c.tar.lz
MultiMC-39d37394423dc204efe774920a59ce010781b28c.tar.xz
MultiMC-39d37394423dc204efe774920a59ce010781b28c.zip
Merge remote-tracking branch 'origin/feature_json_fixes' into develop
Diffstat (limited to 'logic')
-rw-r--r--logic/BaseInstaller.h6
-rw-r--r--logic/ForgeInstaller.cpp105
-rw-r--r--logic/ForgeInstaller.h5
-rw-r--r--logic/LiteLoaderInstaller.cpp68
-rw-r--r--logic/LiteLoaderInstaller.h5
-rw-r--r--logic/OneSixVersionBuilder.cpp13
-rw-r--r--logic/VersionFinal.cpp157
-rw-r--r--logic/VersionFinal.h16
8 files changed, 349 insertions, 26 deletions
diff --git a/logic/BaseInstaller.h b/logic/BaseInstaller.h
index c572e004..d59833cc 100644
--- a/logic/BaseInstaller.h
+++ b/logic/BaseInstaller.h
@@ -20,6 +20,10 @@
class OneSixInstance;
class QDir;
class QString;
+class QObject;
+class ProgressProvider;
+class BaseVersion;
+typedef std::shared_ptr<BaseVersion> BaseVersionPtr;
class BaseInstaller
{
@@ -31,6 +35,8 @@ public:
virtual bool add(OneSixInstance *to);
virtual bool remove(OneSixInstance *from);
+ virtual ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) = 0;
+
protected:
virtual QString id() const = 0;
QString filename(const QString &root) const;
diff --git a/logic/ForgeInstaller.cpp b/logic/ForgeInstaller.cpp
index 6f238c21..48bfb8a3 100644
--- a/logic/ForgeInstaller.cpp
+++ b/logic/ForgeInstaller.cpp
@@ -24,17 +24,24 @@
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include "MultiMC.h"
+#include "tasks/Task.h"
#include "OneSixInstance.h"
+#include "lists/ForgeVersionList.h"
+#include "gui/dialogs/ProgressDialog.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QSaveFile>
#include <QCryptographicHash>
-ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
+ForgeInstaller::ForgeInstaller()
+ : BaseInstaller()
+{
+}
+void ForgeInstaller::prepare(const QString &filename, const QString &universalUrl)
{
std::shared_ptr<VersionFinal> newVersion;
- m_universal_url = universal_url;
+ m_universal_url = universalUrl;
QuaZip zip(filename);
if (!zip.open(QuaZip::mdUnzip))
@@ -111,7 +118,6 @@ ForgeInstaller::ForgeInstaller(QString filename, QString universal_url)
m_forge_version = newVersion;
realVersionId = m_forge_version->id = installObj.value("minecraft").toString();
}
-
bool ForgeInstaller::add(OneSixInstance *to)
{
if (!BaseInstaller::add(to))
@@ -226,3 +232,96 @@ bool ForgeInstaller::add(OneSixInstance *to)
return true;
}
+
+class ForgeInstallTask : public Task
+{
+ Q_OBJECT
+public:
+ ForgeInstallTask(ForgeInstaller *installer, OneSixInstance *instance, BaseVersionPtr version, QObject *parent = 0)
+ : Task(parent), m_installer(installer), m_instance(instance), m_version(version)
+ {
+ }
+
+protected:
+ void executeTask() override
+ {
+ {
+ setStatus(tr("Installing forge..."));
+ ForgeVersionPtr forgeVersion =
+ std::dynamic_pointer_cast<ForgeVersion>(m_version);
+ if (!forgeVersion)
+ {
+ emitFailed(tr("Unknown error occured"));
+ return;
+ }
+ auto entry = MMC->metacache()->resolveEntry("minecraftforge", forgeVersion->filename);
+ if (entry->stale)
+ {
+ NetJob *fjob = new NetJob("Forge download");
+ fjob->addNetAction(CacheDownload::make(forgeVersion->installer_url, entry));
+ connect(fjob, &NetJob::progress, [this](qint64 current, qint64 total){setProgress(100 * current / qMax((qint64)1, total));});
+ connect(fjob, &NetJob::status, [this](const QString &msg){setStatus(msg);});
+ connect(fjob, &NetJob::failed, [this](){emitFailed(tr("Failure to download forge"));});
+ connect(fjob, &NetJob::succeeded, [this, entry, forgeVersion]()
+ {
+ if (!install(entry, forgeVersion))
+ {
+ QLOG_ERROR() << "Failure installing forge";
+ emitFailed(tr("Failure to install forge"));
+ }
+ else
+ {
+ reload();
+ }
+ });
+ }
+ else
+ {
+ if (!install(entry, forgeVersion))
+ {
+ QLOG_ERROR() << "Failure installing forge";
+ emitFailed(tr("Failure to install forge"));
+ }
+ else
+ {
+ reload();
+ }
+ }
+ }
+ }
+
+ bool install(const std::shared_ptr<MetaEntry> &entry, const ForgeVersionPtr &forgeVersion)
+ {
+ QString forgePath = entry->getFullPath();
+ m_installer->prepare(forgePath, forgeVersion->universal_url);
+ return m_installer->add(m_instance);
+ }
+ void reload()
+ {
+ try
+ {
+ m_instance->reloadVersion();
+ emitSucceeded();
+ }
+ catch (MMCError &e)
+ {
+ emitFailed(e.cause());
+ }
+ catch (...)
+ {
+ emitFailed(tr("Failed to load the version description file for reasons unknown."));
+ }
+ }
+
+private:
+ ForgeInstaller *m_installer;
+ OneSixInstance *m_instance;
+ BaseVersionPtr m_version;
+};
+
+ProgressProvider *ForgeInstaller::createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent)
+{
+ return new ForgeInstallTask(this, instance, version, parent);
+}
+
+#include "ForgeInstaller.moc"
diff --git a/logic/ForgeInstaller.h b/logic/ForgeInstaller.h
index df029f38..05cc994b 100644
--- a/logic/ForgeInstaller.h
+++ b/logic/ForgeInstaller.h
@@ -25,12 +25,15 @@ class VersionFinal;
class ForgeInstaller : public BaseInstaller
{
public:
- ForgeInstaller(QString filename, QString universal_url);
+ ForgeInstaller();
+ void prepare(const QString &filename, const QString &universalUrl);
bool add(OneSixInstance *to) override;
QString id() const override { return "net.minecraftforge"; }
+ ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override;
+
private:
// the version, read from the installer
std::shared_ptr<VersionFinal> m_forge_version;
diff --git a/logic/LiteLoaderInstaller.cpp b/logic/LiteLoaderInstaller.cpp
index bb4b07ca..99cc5643 100644
--- a/logic/LiteLoaderInstaller.cpp
+++ b/logic/LiteLoaderInstaller.cpp
@@ -23,12 +23,17 @@
#include "VersionFinal.h"
#include "OneSixLibrary.h"
#include "OneSixInstance.h"
+#include "MultiMC.h"
+#include "lists/LiteLoaderVersionList.h"
-LiteLoaderInstaller::LiteLoaderInstaller(LiteLoaderVersionPtr version)
- : BaseInstaller(), m_version(version)
+LiteLoaderInstaller::LiteLoaderInstaller() : BaseInstaller()
{
}
+void LiteLoaderInstaller::prepare(LiteLoaderVersionPtr version)
+{
+ m_version = version;
+}
bool LiteLoaderInstaller::add(OneSixInstance *to)
{
if (!BaseInstaller::add(to))
@@ -84,3 +89,62 @@ bool LiteLoaderInstaller::add(OneSixInstance *to)
return true;
}
+
+class LiteLoaderInstallTask : public Task
+{
+ Q_OBJECT
+public:
+ LiteLoaderInstallTask(LiteLoaderInstaller *installer, OneSixInstance *instance,
+ BaseVersionPtr version, QObject *parent)
+ : Task(parent), m_installer(installer), m_instance(instance), m_version(version)
+ {
+ }
+
+protected:
+ void executeTask() override
+ {
+ LiteLoaderVersionPtr liteloaderVersion =
+ std::dynamic_pointer_cast<LiteLoaderVersion>(m_version);
+ if (!liteloaderVersion)
+ {
+ return;
+ }
+ m_installer->prepare(liteloaderVersion);
+ if (!m_installer->add(m_instance))
+ {
+ emitFailed(tr("For reasons unknown, the LiteLoader installation failed. Check your "
+ "MultiMC log files for details."));
+ }
+ else
+ {
+ try
+ {
+ m_instance->reloadVersion();
+ emitSucceeded();
+ }
+ catch (MMCError &e)
+ {
+ emitFailed(e.cause());
+ }
+ catch (...)
+ {
+ emitFailed(
+ tr("Failed to load the version description file for reasons unknown."));
+ }
+ }
+ }
+
+private:
+ LiteLoaderInstaller *m_installer;
+ OneSixInstance *m_instance;
+ BaseVersionPtr m_version;
+};
+
+ProgressProvider *LiteLoaderInstaller::createInstallTask(OneSixInstance *instance,
+ BaseVersionPtr version,
+ QObject *parent)
+{
+ return new LiteLoaderInstallTask(this, instance, version, parent);
+}
+
+#include "LiteLoaderInstaller.moc"
diff --git a/logic/LiteLoaderInstaller.h b/logic/LiteLoaderInstaller.h
index 2e0de64a..3ab5acb2 100644
--- a/logic/LiteLoaderInstaller.h
+++ b/logic/LiteLoaderInstaller.h
@@ -25,10 +25,13 @@
class LiteLoaderInstaller : public BaseInstaller
{
public:
- LiteLoaderInstaller(LiteLoaderVersionPtr version);
+ LiteLoaderInstaller();
+ void prepare(LiteLoaderVersionPtr version);
bool add(OneSixInstance *to) override;
+ ProgressProvider *createInstallTask(OneSixInstance *instance, BaseVersionPtr version, QObject *parent) override;
+
private:
virtual QString id() const override
{
diff --git a/logic/OneSixVersionBuilder.cpp b/logic/OneSixVersionBuilder.cpp
index 8eacbce4..35d01a46 100644
--- a/logic/OneSixVersionBuilder.cpp
+++ b/logic/OneSixVersionBuilder.cpp
@@ -58,13 +58,15 @@ void OneSixVersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringList &external)
{
- m_version->clear();
+ m_version->versionFiles.clear();
QDir root(m_instance->instanceRoot());
QDir patches(root.absoluteFilePath("patches/"));
// if we do external files, do just those.
if (!external.isEmpty())
+ {
+ int externalOrder = -1;
for (auto fileName : external)
{
QLOG_INFO() << "Reading" << fileName;
@@ -72,11 +74,12 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
file->name = QFileInfo(fileName).fileName();
file->fileId = "org.multimc.external." + file->name;
+ file->order = (externalOrder += 1);
file->version = QString();
file->mcVersion = QString();
- file->applyTo(m_version);
m_version->versionFiles.append(file);
}
+ }
// else, if there's custom json, we just do that.
else if (QFile::exists(root.absoluteFilePath("custom.json")))
{
@@ -85,8 +88,8 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
file->name = "custom.json";
file->filename = "custom.json";
file->fileId = "org.multimc.custom.json";
+ file->order = -1;
file->version = QString();
- file->applyTo(m_version);
m_version->versionFiles.append(file);
// QObject::tr("The version descriptors of this instance are not compatible with the
// current version of MultiMC"));
@@ -101,9 +104,9 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false);
file->name = "Minecraft";
file->fileId = "org.multimc.version.json";
+ file->order = -1;
file->version = m_instance->intendedVersionId();
file->mcVersion = m_instance->intendedVersionId();
- file->applyTo(m_version);
m_version->versionFiles.append(file);
// QObject::tr("Error while applying %1. Please check MultiMC-0.log for more
// info.").arg(root.absoluteFilePath("version.json")));
@@ -128,9 +131,7 @@ void OneSixVersionBuilder::buildInternal(const bool onlyVanilla, const QStringLi
}
for (auto order : files.keys())
{
- QLOG_DEBUG() << "Applying file with order" << order;
auto &filePair = files[order];
- filePair.second->applyTo(m_version);
m_version->versionFiles.append(filePair.second);
}
} while (0);
diff --git a/logic/VersionFinal.cpp b/logic/VersionFinal.cpp
index a057ecdd..d0e85c15 100644
--- a/logic/VersionFinal.cpp
+++ b/logic/VersionFinal.cpp
@@ -17,8 +17,20 @@
#include <QDebug>
#include <QFile>
+#include <QDir>
#include "OneSixVersionBuilder.h"
+#include "OneSixInstance.h"
+
+template <typename A, typename B> QMap<A, B> invert(const QMap<B, A> &in)
+{
+ QMap<A, B> out;
+ for (auto it = in.begin(); it != in.end(); ++it)
+ {
+ out.insert(it.value(), it.key());
+ }
+ return out;
+}
VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent)
: QAbstractListModel(parent), m_instance(instance)
@@ -31,12 +43,12 @@ bool VersionFinal::reload(const bool onlyVanilla, const QStringList &external)
//FIXME: source of epic failure.
beginResetModel();
OneSixVersionBuilder::build(this, m_instance, onlyVanilla, external);
+ reapply(true);
endResetModel();
}
void VersionFinal::clear()
{
- beginResetModel();
id.clear();
time.clear();
releaseTime.clear();
@@ -48,8 +60,6 @@ void VersionFinal::clear()
mainClass.clear();
libraries.clear();
tweakers.clear();
- versionFiles.clear();
- endResetModel();
}
bool VersionFinal::canRemove(const int index) const
@@ -60,6 +70,18 @@ bool VersionFinal::canRemove(const int index) const
}
return false;
}
+bool VersionFinal::remove(const int index)
+{
+ if (canRemove(index) && QFile::remove(versionFiles.at(index)->filename))
+ {
+ beginResetModel();
+ versionFiles.removeAt(index);
+ reapply(true);
+ endResetModel();
+ return true;
+ }
+ return false;
+}
QString VersionFinal::versionFileId(const int index) const
{
@@ -69,14 +91,16 @@ QString VersionFinal::versionFileId(const int index) const
}
return versionFiles.at(index)->fileId;
}
-
-bool VersionFinal::remove(const int index)
+VersionFilePtr VersionFinal::versionFile(const QString &id)
{
- if (canRemove(index))
+ for (auto file : versionFiles)
{
- return QFile::remove(versionFiles.at(index)->filename);
+ if (file->fileId == id)
+ {
+ return file;
+ }
}
- return false;
+ return 0;
}
QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
@@ -91,7 +115,6 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
}
return output;
}
-
QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs()
{
QList<std::shared_ptr<OneSixLibrary> > output;
@@ -144,7 +167,6 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
}
return QVariant();
}
-
QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal)
@@ -164,7 +186,6 @@ QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int
}
return QVariant();
}
-
Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const
{
if (!index.isValid())
@@ -181,3 +202,117 @@ int VersionFinal::columnCount(const QModelIndex &parent) const
{
return 2;
}
+
+bool VersionFinal::isCustom()
+{
+ return QDir(m_instance->instanceRoot()).exists("custom.json");
+}
+bool VersionFinal::revertToBase()
+{
+ return QDir(m_instance->instanceRoot()).remove("custom.json");
+}
+
+QMap<QString, int> VersionFinal::getExistingOrder() const
+{
+
+ QMap<QString, int> order;
+ // default
+ {
+ for (auto file : versionFiles)
+ {
+ order.insert(file->fileId, file->order);
+ }
+ }
+ // overriden
+ {
+ QMap<QString, int> overridenOrder = OneSixVersionBuilder::readOverrideOrders(m_instance);
+ for (auto id : order.keys())
+ {
+ if (overridenOrder.contains(id))
+ {
+ order[id] = overridenOrder[id];
+ }
+ }
+ }
+ return order;
+}
+
+void VersionFinal::move(const int index, const MoveDirection direction)
+{
+ int theirIndex;
+ if (direction == MoveUp)
+ {
+ theirIndex = index - 1;
+ }
+ else
+ {
+ theirIndex = index + 1;
+ }
+ if (theirIndex < 0 || theirIndex >= versionFiles.size())
+ {
+ return;
+ }
+ const QString ourId = versionFileId(index);
+ const QString theirId = versionFileId(theirIndex);
+ if (ourId.isNull() || ourId.startsWith("org.multimc.") ||
+ theirId.isNull() || theirId.startsWith("org.multimc."))
+ {
+ return;
+ }
+
+ VersionFilePtr we = versionFiles[index];
+ VersionFilePtr them = versionFiles[theirIndex];
+ if (!we || !them)
+ {
+ return;
+ }
+ beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex);
+ versionFiles.replace(theirIndex, we);
+ versionFiles.replace(index, them);
+ endMoveRows();
+
+ auto order = getExistingOrder();
+ order[ourId] = theirIndex;
+ order[theirId] = index;
+
+ if (!OneSixVersionBuilder::writeOverrideOrders(order, m_instance))
+ {
+ throw MMCError(tr("Couldn't save the new order"));
+ }
+ else
+ {
+ reapply();
+ }
+}
+void VersionFinal::resetOrder()
+{
+ QDir(m_instance->instanceRoot()).remove("order.json");
+ reapply();
+}
+
+void VersionFinal::reapply(const bool alreadyReseting)
+{
+ if (!alreadyReseting)
+ {
+ beginResetModel();
+ }
+
+ clear();
+
+ auto existingOrders = getExistingOrder();
+ QList<int> orders = existingOrders.values();
+ std::sort(orders.begin(), orders.end());
+ QList<VersionFilePtr> newVersionFiles;
+ for (auto order : orders)
+ {
+ auto file = versionFile(existingOrders.key(order));
+ newVersionFiles.append(file);
+ file->applyTo(this);
+ }
+ versionFiles.swap(newVersionFiles);
+
+ if (!alreadyReseting)
+ {
+ endResetModel();
+ }
+}
diff --git a/logic/VersionFinal.h b/logic/VersionFinal.h
index 99fd5ff0..fcffb3c3 100644
--- a/logic/VersionFinal.h
+++ b/logic/VersionFinal.h
@@ -41,12 +41,22 @@ public:
bool reload(const bool onlyVanilla = false, const QStringList &external = QStringList());
void clear();
- void dump() const;
-
bool canRemove(const int index) const;
QString versionFileId(const int index) const;
+ // does this instance have an all overriding custom.json
+ bool isCustom();
+ // remove custom.json
+ bool revertToBase();
+
+ enum MoveDirection { MoveUp, MoveDown };
+ void move(const int index, const MoveDirection direction);
+ void resetOrder();
+
+ // clears and reapplies all version files
+ void reapply(const bool alreadyReseting = false);
+
public
slots:
bool remove(const int index);
@@ -120,7 +130,9 @@ public:
// QList<Rule> rules;
QList<VersionFilePtr> versionFiles;
+ VersionFilePtr versionFile(const QString &id);
private:
OneSixInstance *m_instance;
+ QMap<QString, int> getExistingOrder() const;
};