Implement adding jar mods, break saving library order.

This commit is contained in:
Petr Mrázek
2014-05-19 02:22:09 +02:00
parent 55a0d110b6
commit e118b1f990
21 changed files with 226 additions and 162 deletions

View File

@ -16,19 +16,22 @@
#include <QDebug>
#include <QFile>
#include <QDir>
#include <QUuid>
#include <QJsonDocument>
#include <QJsonArray>
#include <pathutils.h>
#include "logic/minecraft/VersionFinal.h"
#include "logic/minecraft/InstanceVersion.h"
#include "logic/minecraft/VersionBuilder.h"
#include "logic/OneSixInstance.h"
VersionFinal::VersionFinal(OneSixInstance *instance, QObject *parent)
InstanceVersion::InstanceVersion(OneSixInstance *instance, QObject *parent)
: QAbstractListModel(parent), m_instance(instance)
{
clear();
}
void VersionFinal::reload(const QStringList &external)
void InstanceVersion::reload(const QStringList &external)
{
beginResetModel();
VersionBuilder::build(this, m_instance, external);
@ -36,7 +39,7 @@ void VersionFinal::reload(const QStringList &external)
endResetModel();
}
void VersionFinal::clear()
void InstanceVersion::clear()
{
id.clear();
m_updateTimeString.clear();
@ -56,12 +59,12 @@ void VersionFinal::clear()
traits.clear();
}
bool VersionFinal::canRemove(const int index) const
bool InstanceVersion::canRemove(const int index) const
{
return VersionPatches.at(index)->isMoveable();
}
bool VersionFinal::preremove(VersionPatchPtr patch)
bool InstanceVersion::preremove(VersionPatchPtr patch)
{
bool ok = true;
for(auto & jarmod: patch->getJarMods())
@ -74,7 +77,7 @@ bool VersionFinal::preremove(VersionPatchPtr patch)
return ok;
}
bool VersionFinal::remove(const int index)
bool InstanceVersion::remove(const int index)
{
if (!canRemove(index))
return false;
@ -91,7 +94,7 @@ bool VersionFinal::remove(const int index)
return true;
}
bool VersionFinal::remove(const QString id)
bool InstanceVersion::remove(const QString id)
{
int i = 0;
for (auto patch : VersionPatches)
@ -105,7 +108,7 @@ bool VersionFinal::remove(const QString id)
return false;
}
QString VersionFinal::versionFileId(const int index) const
QString InstanceVersion::versionFileId(const int index) const
{
if (index < 0 || index >= VersionPatches.size())
{
@ -114,7 +117,7 @@ QString VersionFinal::versionFileId(const int index) const
return VersionPatches.at(index)->getPatchID();
}
VersionPatchPtr VersionFinal::versionPatch(const QString &id)
VersionPatchPtr InstanceVersion::versionPatch(const QString &id)
{
for (auto file : VersionPatches)
{
@ -126,7 +129,7 @@ VersionPatchPtr VersionFinal::versionPatch(const QString &id)
return 0;
}
VersionPatchPtr VersionFinal::versionPatch(int index)
VersionPatchPtr InstanceVersion::versionPatch(int index)
{
if(index < 0 || index >= VersionPatches.size())
return 0;
@ -134,22 +137,22 @@ VersionPatchPtr VersionFinal::versionPatch(int index)
}
bool VersionFinal::hasJarMods()
bool InstanceVersion::hasJarMods()
{
return !jarMods.isEmpty();
}
bool VersionFinal::hasFtbPack()
bool InstanceVersion::hasFtbPack()
{
return versionPatch("org.multimc.ftb.pack.json") != nullptr;
}
bool VersionFinal::removeFtbPack()
bool InstanceVersion::removeFtbPack()
{
return remove("org.multimc.ftb.pack.json");
}
bool VersionFinal::isVanilla()
bool InstanceVersion::isVanilla()
{
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
if(VersionPatches.size() > 1)
@ -159,7 +162,7 @@ bool VersionFinal::isVanilla()
return true;
}
bool VersionFinal::revertToVanilla()
bool InstanceVersion::revertToVanilla()
{
beginResetModel();
auto it = VersionPatches.begin();
@ -187,12 +190,12 @@ bool VersionFinal::revertToVanilla()
return true;
}
bool VersionFinal::usesLegacyCustomJson()
bool InstanceVersion::usesLegacyCustomJson()
{
return QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json"));
}
QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs()
{
QList<std::shared_ptr<OneSixLibrary> > output;
for (auto lib : libraries)
@ -204,7 +207,7 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNormalLibs()
}
return output;
}
QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs()
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs()
{
QList<std::shared_ptr<OneSixLibrary> > output;
for (auto lib : libraries)
@ -217,9 +220,9 @@ QList<std::shared_ptr<OneSixLibrary> > VersionFinal::getActiveNativeLibs()
return output;
}
std::shared_ptr<VersionFinal> VersionFinal::fromJson(const QJsonObject &obj)
std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &obj)
{
std::shared_ptr<VersionFinal> version(new VersionFinal(0));
std::shared_ptr<InstanceVersion> version(new InstanceVersion(0));
try
{
VersionBuilder::readJsonAndApplyToVersion(version.get(), obj);
@ -231,7 +234,7 @@ std::shared_ptr<VersionFinal> VersionFinal::fromJson(const QJsonObject &obj)
return version;
}
QVariant VersionFinal::data(const QModelIndex &index, int role) const
QVariant InstanceVersion::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
@ -256,7 +259,7 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
}
return QVariant();
}
QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int role) const
QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal)
{
@ -275,33 +278,27 @@ QVariant VersionFinal::headerData(int section, Qt::Orientation orientation, int
}
return QVariant();
}
Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const
Qt::ItemFlags InstanceVersion::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
int VersionFinal::rowCount(const QModelIndex &parent) const
int InstanceVersion::rowCount(const QModelIndex &parent) const
{
return VersionPatches.size();
}
int VersionFinal::columnCount(const QModelIndex &parent) const
int InstanceVersion::columnCount(const QModelIndex &parent) const
{
return 2;
}
QMap<QString, int> VersionFinal::getExistingOrder() const
QMap<QString, int> InstanceVersion::getExistingOrder() const
{
QMap<QString, int> order;
// default
{
for (auto file : VersionPatches)
{
order.insert(file->getPatchID(), file->getOrder());
}
}
int index = 0;
// overriden
{
QMap<QString, int> overridenOrder = VersionBuilder::readOverrideOrders(m_instance);
@ -313,87 +310,71 @@ QMap<QString, int> VersionFinal::getExistingOrder() const
}
}
}
for(auto item: VersionPatches)
{
// things with fixed (negative) order.
if(!item->isMoveable())
continue;
// the other things.
auto id = item->getPatchID();
order[id] = index;
index++;
}
return order;
}
void VersionFinal::move(const int index, const MoveDirection direction)
void InstanceVersion::move(const int index, const MoveDirection direction)
{
int theirIndex;
int theirIndex_qt;
if (direction == MoveUp)
{
theirIndex_qt = theirIndex = index - 1;
theirIndex = index - 1;
}
else
{
theirIndex = index + 1;
theirIndex_qt = index + 2;
}
if (index < 0 || index >= VersionPatches.size())
return;
if (theirIndex >= rowCount())
theirIndex = rowCount() - 1;
if (theirIndex == -1)
theirIndex = rowCount() - 1;
if (index == theirIndex)
return;
int togap = theirIndex > index ? theirIndex + 1 : theirIndex;
auto from = versionPatch(index);
auto to = versionPatch(theirIndex);
if (!from || !to || !from->isMoveable() || !from->isMoveable())
if (!from || !to || !to->isMoveable() || !from->isMoveable())
{
return;
}
if(direction == MoveDown)
{
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
}
else
{
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
}
beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap);
VersionPatches.swap(index, theirIndex);
endMoveRows();
auto order = getExistingOrder();
order[from->getPatchID()] = theirIndex;
order[to->getPatchID()] = index;
if (!VersionBuilder::writeOverrideOrders(order, m_instance))
{
throw MMCError(tr("Couldn't save the new order"));
}
else
{
reapply();
}
reapply();
}
void VersionFinal::resetOrder()
void InstanceVersion::resetOrder()
{
QDir(m_instance->instanceRoot()).remove("order.json");
reapply();
}
void VersionFinal::reapply(const bool alreadyReseting)
void InstanceVersion::reapply(const bool alreadyReseting)
{
if (!alreadyReseting)
{
beginResetModel();
}
clear();
auto existingOrders = getExistingOrder();
QList<int> orders = existingOrders.values();
std::sort(orders.begin(), orders.end());
QList<VersionPatchPtr> newVersionFiles;
for (auto order : orders)
for(auto file: VersionPatches)
{
auto file = versionPatch(existingOrders.key(order));
newVersionFiles.append(file);
file->applyTo(this);
}
VersionPatches.swap(newVersionFiles);
finalize();
if (!alreadyReseting)
{
endResetModel();
}
}
void VersionFinal::finalize()
void InstanceVersion::finalize()
{
// HACK: deny april fools. my head hurts enough already.
QDate now = QDate::currentDate();
@ -430,3 +411,83 @@ void VersionFinal::finalize()
finalizeArguments(minecraftArguments, processArguments);
}
void InstanceVersion::installJarMods(QStringList selectedFiles)
{
for(auto filename: selectedFiles)
{
installJarModByFilename(filename);
}
}
void InstanceVersion::installJarModByFilename(QString filepath)
{
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
if(!ensureFolderPathExists(patchDir))
{
// THROW...
return;
}
if (!ensureFolderPathExists(m_instance->jarModsDir()))
{
// THROW...
return;
}
QFileInfo sourceInfo(filepath);
auto uuid = QUuid::createUuid();
QString id = uuid.toString().remove('{').remove('}');
QString target_filename = id + ".jar";
QString target_id = "org.multimc.jarmod." + id;
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
QString finalPath = PathCombine(m_instance->jarModsDir(), target_filename);
QFileInfo targetInfo(finalPath);
if(targetInfo.exists())
{
// THROW
return;
}
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
{
// THROW
return;
}
auto f = std::make_shared<VersionFile>();
auto jarMod = std::make_shared<Jarmod>();
jarMod->name = target_filename;
f->jarMods.append(jarMod);
f->name = target_name;
f->fileId = target_id;
f->order = getFreeOrderNumber();
QFile file(PathCombine(patchDir, target_id + ".json"));
if (!file.open(QFile::WriteOnly))
{
QLOG_ERROR() << "Error opening" << file.fileName()
<< "for reading:" << file.errorString();
return;
// THROW
}
file.write(f->toJson(true).toJson());
file.close();
int index = VersionPatches.size();
beginInsertRows(QModelIndex(), index, index);
VersionPatches.append(f);
endInsertRows();
}
int InstanceVersion::getFreeOrderNumber()
{
int largest = 100;
// yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next.
for(auto thing: VersionPatches)
{
int order = thing->getOrder();
if(order > largest)
largest = order;
}
return largest + 1;
}

View File

@ -27,11 +27,11 @@
class OneSixInstance;
class VersionFinal : public QAbstractListModel
class InstanceVersion : public QAbstractListModel
{
Q_OBJECT
public:
explicit VersionFinal(OneSixInstance *instance, QObject *parent = 0);
explicit InstanceVersion(OneSixInstance *instance, QObject *parent = 0);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
@ -58,10 +58,11 @@ public:
// does this version have any jar mods?
bool hasJarMods();
void installJarMods(QStringList selectedFiles);
void installJarModByFilename(QString filepath);
// does this version still use a legacy custom.json file?
bool usesLegacyCustomJson();
enum MoveDirection { MoveUp, MoveDown };
void move(const int index, const MoveDirection direction);
@ -80,7 +81,7 @@ public:
QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs();
QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs();
static std::shared_ptr<VersionFinal> fromJson(const QJsonObject &obj);
static std::shared_ptr<InstanceVersion> fromJson(const QJsonObject &obj);
private:
bool preremove(VersionPatchPtr patch);
@ -176,4 +177,5 @@ public:
private:
OneSixInstance *m_instance;
QMap<QString, int> getExistingOrder() const;
int getFreeOrderNumber();
};

View File

@ -1,5 +1,5 @@
#include "MinecraftVersion.h"
#include "VersionFinal.h"
#include "InstanceVersion.h"
#include "VersionBuildError.h"
#include "VersionBuilder.h"
@ -54,7 +54,7 @@ bool MinecraftVersion::isMinecraftVersion()
// 1. assume the local file is good. load, check. If it's good, apply.
// 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version).
void MinecraftVersion::applyFileTo(VersionFinal *version)
void MinecraftVersion::applyFileTo(InstanceVersion *version)
{
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
@ -62,7 +62,7 @@ void MinecraftVersion::applyFileTo(VersionFinal *version)
versionObj->applyTo(version);
}
void MinecraftVersion::applyTo(VersionFinal *version)
void MinecraftVersion::applyTo(InstanceVersion *version)
{
// do we have this one cached?
if (m_versionSource == Local)

View File

@ -24,7 +24,7 @@
#include "VersionFile.h"
#include "VersionSource.h"
class VersionFinal;
class InstanceVersion;
class MinecraftVersion;
typedef std::shared_ptr<MinecraftVersion> MinecraftVersionPtr;
@ -37,7 +37,7 @@ public: /* methods */
virtual QString typeString() const override;
virtual bool hasJarMods() override;
virtual bool isMinecraftVersion() override;
virtual void applyTo(VersionFinal *version) override;
virtual void applyTo(InstanceVersion *version) override;
virtual int getOrder();
virtual void setOrder(int order);
virtual QList<JarmodPtr> getJarMods() override;
@ -55,7 +55,7 @@ public: /* methods */
}
private: /* methods */
void applyFileTo(VersionFinal *version);
void applyFileTo(InstanceVersion *version);
public: /* data */
/// The URL that this version will be downloaded from. maybe.

View File

@ -28,7 +28,7 @@
#include "MultiMC.h"
#include "logic/minecraft/VersionBuilder.h"
#include "logic/minecraft/VersionFinal.h"
#include "logic/minecraft/InstanceVersion.h"
#include "logic/minecraft/OneSixRule.h"
#include "logic/minecraft/VersionPatch.h"
#include "logic/minecraft/VersionFile.h"
@ -44,7 +44,7 @@ VersionBuilder::VersionBuilder()
{
}
void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance,
void VersionBuilder::build(InstanceVersion *version, OneSixInstance *instance,
const QStringList &external)
{
VersionBuilder builder;
@ -54,7 +54,7 @@ void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance,
builder.buildInternal();
}
void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj)
void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj)
{
VersionBuilder builder;
builder.m_version = version;
@ -312,10 +312,9 @@ bool VersionBuilder::writeOverrideOrders(const QMap<QString, int> &order,
QJsonObject obj;
for (auto it = order.cbegin(); it != order.cend(); ++it)
{
if (it.key().startsWith("org.multimc."))
{
int order = it.value();
if(order < 0)
continue;
}
obj.insert(it.key(), it.value());
}
QFile orderFile(instance->instanceRoot() + "/order.json");

View File

@ -19,7 +19,7 @@
#include <QMap>
#include "VersionFile.h"
class VersionFinal;
class InstanceVersion;
class OneSixInstance;
class QJsonObject;
class QFileInfo;
@ -28,8 +28,8 @@ class VersionBuilder
{
VersionBuilder();
public:
static void build(VersionFinal *version, OneSixInstance *instance, const QStringList &external);
static void readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj);
static void build(InstanceVersion *version, OneSixInstance *instance, const QStringList &external);
static void readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj);
static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
@ -37,7 +37,7 @@ public:
static bool writeOverrideOrders(const QMap<QString, int> &order, OneSixInstance *instance);
private:
VersionFinal *m_version;
InstanceVersion *m_version;
OneSixInstance *m_instance;
QStringList external_patches;
QDir instance_root;

View File

@ -6,7 +6,7 @@
#include "logic/minecraft/VersionFile.h"
#include "logic/minecraft/OneSixLibrary.h"
#include "logic/minecraft/VersionFinal.h"
#include "logic/minecraft/InstanceVersion.h"
#include "logic/minecraft/JarMod.h"
#include "ParseUtils.h"
@ -266,7 +266,7 @@ bool VersionFile::hasJarMods()
return !jarMods.isEmpty();
}
void VersionFile::applyTo(VersionFinal *version)
void VersionFile::applyTo(InstanceVersion *version)
{
if (minimumLauncherVersion != -1)
{

View File

@ -11,7 +11,7 @@
#include "OneSixLibrary.h"
#include "JarMod.h"
class VersionFinal;
class InstanceVersion;
struct VersionFile;
typedef std::shared_ptr<VersionFile> VersionFilePtr;
@ -22,7 +22,7 @@ public: /* methods */
const bool requireOrder, const bool isFTB = false);
QJsonDocument toJson(bool saveOrder);
virtual void applyTo(VersionFinal *version) override;
virtual void applyTo(InstanceVersion *version) override;
virtual bool isMinecraftVersion() override;
virtual bool hasJarMods() override;
virtual int getOrder() override

View File

@ -4,12 +4,12 @@
#include <QList>
#include "JarMod.h"
class VersionFinal;
class InstanceVersion;
class VersionPatch
{
public:
virtual ~VersionPatch(){};
virtual void applyTo(VersionFinal *version) = 0;
virtual void applyTo(InstanceVersion *version) = 0;
virtual bool isMinecraftVersion() = 0;
virtual bool hasJarMods() = 0;