summaryrefslogtreecommitdiffstats
path: root/logic/minecraft
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2015-05-17 23:38:28 +0200
committerPetr Mrázek <peterix@gmail.com>2015-05-17 23:38:28 +0200
commit743af4769ee59b5830d79139852dda0679b28a03 (patch)
tree939e150c6127c9bc64926da052fe56e2b483990d /logic/minecraft
parent6ab6a450f6831c99ba507436ab15047cfa4d4528 (diff)
downloadMultiMC-743af4769ee59b5830d79139852dda0679b28a03.tar
MultiMC-743af4769ee59b5830d79139852dda0679b28a03.tar.gz
MultiMC-743af4769ee59b5830d79139852dda0679b28a03.tar.lz
MultiMC-743af4769ee59b5830d79139852dda0679b28a03.tar.xz
MultiMC-743af4769ee59b5830d79139852dda0679b28a03.zip
GH-952 Hardcore version page tweakery
Version patches get a lot of new flags that determine which actions are allowed Version page respects the flags Customize, revert and edit for version patches Builting patches can be customized
Diffstat (limited to 'logic/minecraft')
-rw-r--r--logic/minecraft/MinecraftProfile.cpp87
-rw-r--r--logic/minecraft/MinecraftProfile.h7
-rw-r--r--logic/minecraft/MinecraftVersion.cpp11
-rw-r--r--logic/minecraft/MinecraftVersion.h26
-rw-r--r--logic/minecraft/NullProfileStrategy.h10
-rw-r--r--logic/minecraft/OneSixProfileStrategy.cpp150
-rw-r--r--logic/minecraft/OneSixProfileStrategy.h4
-rw-r--r--logic/minecraft/ProfilePatch.h15
-rw-r--r--logic/minecraft/ProfileStrategy.h5
-rw-r--r--logic/minecraft/VersionFile.h56
10 files changed, 294 insertions, 77 deletions
diff --git a/logic/minecraft/MinecraftProfile.cpp b/logic/minecraft/MinecraftProfile.cpp
index acde7dc7..345930ca 100644
--- a/logic/minecraft/MinecraftProfile.cpp
+++ b/logic/minecraft/MinecraftProfile.cpp
@@ -91,22 +91,18 @@ void MinecraftProfile::appendPatch(ProfilePatchPtr patch)
endInsertRows();
}
-bool MinecraftProfile::canRemove(const int index) const
-{
- return VersionPatches.at(index)->isMoveable();
-}
-
bool MinecraftProfile::remove(const int index)
{
- if (!canRemove(index))
+ auto patch = versionPatch(index);
+ if (!patch->isRemovable())
{
- qDebug() << "Patch" << index << "is non-removable";
+ qDebug() << "Patch" << patch->getPatchID() << "is non-removable";
return false;
}
- if(!m_strategy->removePatch(VersionPatches.at(index)))
+ if(!m_strategy->removePatch(patch))
{
- qCritical() << "Patch" << index << "could not be removed";
+ qCritical() << "Patch" << patch->getPatchID() << "could not be removed";
return false;
}
@@ -132,6 +128,46 @@ bool MinecraftProfile::remove(const QString id)
return false;
}
+bool MinecraftProfile::customize(int index)
+{
+ auto patch = versionPatch(index);
+ if (!patch->isCustomizable())
+ {
+ qDebug() << "Patch" << patch->getPatchID() << "is not customizable";
+ return false;
+ }
+ if(!m_strategy->customizePatch(patch))
+ {
+ qCritical() << "Patch" << patch->getPatchID() << "could not be customized";
+ return false;
+ }
+ reapply();
+ saveCurrentOrder();
+ // FIXME: maybe later in unstable
+ // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
+ return true;
+}
+
+bool MinecraftProfile::revert(int index)
+{
+ auto patch = versionPatch(index);
+ if (!patch->isRevertible())
+ {
+ qDebug() << "Patch" << patch->getPatchID() << "is not revertible";
+ return false;
+ }
+ if(!m_strategy->revertPatch(patch))
+ {
+ qCritical() << "Patch" << patch->getPatchID() << "could not be reverted";
+ return false;
+ }
+ reapply();
+ saveCurrentOrder();
+ // FIXME: maybe later in unstable
+ // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
+ return true;
+}
+
QString MinecraftProfile::versionFileId(const int index) const
{
if (index < 0 || index >= VersionPatches.size())
@@ -150,13 +186,13 @@ ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id)
return file;
}
}
- return 0;
+ return nullptr;
}
ProfilePatchPtr MinecraftProfile::versionPatch(int index)
{
if(index < 0 || index >= VersionPatches.size())
- return 0;
+ return nullptr;
return VersionPatches[index];
}
@@ -172,37 +208,28 @@ bool MinecraftProfile::isVanilla()
bool MinecraftProfile::revertToVanilla()
{
- /*
- beginResetModel();
// remove patches, if present
- auto it = VersionPatches.begin();
- while (it != VersionPatches.end())
+ auto VersionPatchesCopy = VersionPatches;
+ for(auto & it: VersionPatchesCopy)
{
- if ((*it)->isMoveable())
+ if (!it->isCustom())
{
- if(!preremove(*it))
- {
- endResetModel();
- saveCurrentOrder();
- return false;
- }
- if(!QFile::remove((*it)->getPatchFilename()))
+ continue;
+ }
+ if(it->isRevertible() || it->isRemovable())
+ {
+ if(!remove(it->getPatchID()))
{
- endResetModel();
+ qWarning() << "Couldn't remove" << it->getPatchID() << "from profile!";
+ reapply();
saveCurrentOrder();
return false;
}
- it = VersionPatches.erase(it);
}
- else
- it++;
}
reapply();
- endResetModel();
saveCurrentOrder();
return true;
- */
- return false;
}
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNormalLibs()
diff --git a/logic/minecraft/MinecraftProfile.h b/logic/minecraft/MinecraftProfile.h
index ef7e1369..dba7d744 100644
--- a/logic/minecraft/MinecraftProfile.h
+++ b/logic/minecraft/MinecraftProfile.h
@@ -60,9 +60,6 @@ public:
/// DEPRECATED, remove ASAP
int getFreeOrderNumber();
- /// Can patch file # be removed?
- bool canRemove(const int index) const;
-
enum MoveDirection { MoveUp, MoveDown };
/// move patch file # up or down the list
void move(const int index, const MoveDirection direction);
@@ -73,6 +70,10 @@ public:
/// remove patch file by id - including files/records
bool remove(const QString id);
+ bool customize(int index);
+
+ bool revert(int index);
+
void resetOrder();
/// reload all profile patches from storage, clear the profile and apply the patches
diff --git a/logic/minecraft/MinecraftVersion.cpp b/logic/minecraft/MinecraftVersion.cpp
index 5a759421..982a5ac3 100644
--- a/logic/minecraft/MinecraftVersion.cpp
+++ b/logic/minecraft/MinecraftVersion.cpp
@@ -60,11 +60,20 @@ void MinecraftVersion::applyFileTo(MinecraftProfile *version)
getVersionFile()->applyTo(version);
}
+QJsonDocument MinecraftVersion::toJson(bool saveOrder)
+{
+ return getVersionFile()->toJson(saveOrder);
+}
+
VersionFilePtr MinecraftVersion::getVersionFile()
{
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
- return ProfileUtils::parseBinaryJsonFile(versionFile);
+ auto loadedVersionFile = ProfileUtils::parseBinaryJsonFile(versionFile);
+ loadedVersionFile->name = "Minecraft";
+ //FIXME: possibly not the best place for this... but w/e
+ loadedVersionFile->setCustomizable(true);
+ return loadedVersionFile;
}
diff --git a/logic/minecraft/MinecraftVersion.h b/logic/minecraft/MinecraftVersion.h
index 9ee8425a..af15c1a4 100644
--- a/logic/minecraft/MinecraftVersion.h
+++ b/logic/minecraft/MinecraftVersion.h
@@ -48,9 +48,35 @@ public: /* methods */
bool needsUpdate();
bool hasUpdate();
virtual bool isCustom() override;
+ virtual bool isMoveable() override
+ {
+ return false;
+ }
+ virtual bool isCustomizable() override
+ {
+ return true;
+ }
+ virtual bool isRemovable() override
+ {
+ return false;
+ }
+ virtual bool isRevertible() override
+ {
+ return false;
+ }
+ virtual bool isEditable() override
+ {
+ return false;
+ }
+ virtual bool isVersionChangeable() override
+ {
+ return true;
+ }
VersionFilePtr getVersionFile();
+ virtual QJsonDocument toJson(bool saveOrder) override;
+
private: /* methods */
void applyFileTo(MinecraftProfile *version);
diff --git a/logic/minecraft/NullProfileStrategy.h b/logic/minecraft/NullProfileStrategy.h
index eaabd3c7..44a46060 100644
--- a/logic/minecraft/NullProfileStrategy.h
+++ b/logic/minecraft/NullProfileStrategy.h
@@ -13,6 +13,14 @@ class NullProfileStrategy: public ProfileStrategy
{
return false;
}
+ virtual bool customizePatch(ProfilePatchPtr patch)
+ {
+ return false;
+ }
+ virtual bool revertPatch(ProfilePatchPtr patch)
+ {
+ return false;
+ }
virtual bool resetOrder()
{
return false;
@@ -21,4 +29,4 @@ class NullProfileStrategy: public ProfileStrategy
{
return false;
}
-}; \ No newline at end of file
+};
diff --git a/logic/minecraft/OneSixProfileStrategy.cpp b/logic/minecraft/OneSixProfileStrategy.cpp
index a84f0387..acd2904d 100644
--- a/logic/minecraft/OneSixProfileStrategy.cpp
+++ b/logic/minecraft/OneSixProfileStrategy.cpp
@@ -76,46 +76,62 @@ void OneSixProfileStrategy::upgradeDeprecatedFiles()
}
}
-
void OneSixProfileStrategy::loadDefaultBuiltinPatches()
{
- auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
- // load up the base minecraft patch
- ProfilePatchPtr minecraftPatch;
- if(QFile::exists(mcJson))
{
- auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
- if(file->version.isEmpty())
+ auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
+ // load up the base minecraft patch
+ ProfilePatchPtr minecraftPatch;
+ if(QFile::exists(mcJson))
{
- file->version = m_instance->intendedVersionId();
+ auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
+ if(file->version.isEmpty())
+ {
+ file->version = m_instance->intendedVersionId();
+ }
+ file->setVanilla(false);
+ file->setRevertible(true);
+ minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file);
}
- file->setVanilla(false);
- minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file);
- }
- else
- {
- auto mcversion = ENV.getVersion("net.minecraft", m_instance->intendedVersionId());
- minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(mcversion);
- }
- if (!minecraftPatch)
- {
- throw VersionIncomplete("net.minecraft");
+ else
+ {
+ auto mcversion = ENV.getVersion("net.minecraft", m_instance->intendedVersionId());
+ minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(mcversion);
+ }
+ if (!minecraftPatch)
+ {
+ throw VersionIncomplete("net.minecraft");
+ }
+ minecraftPatch->setOrder(-2);
+ profile->appendPatch(minecraftPatch);
}
- minecraftPatch->setOrder(-2);
- profile->appendPatch(minecraftPatch);
-
- // TODO: this is obviously fake.
- QResource LWJGL(":/versions/LWJGL/2.9.1.json");
- auto lwjgl = ProfileUtils::parseJsonFile(LWJGL.absoluteFilePath(), false);
- auto lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(lwjgl);
- if (!lwjglPatch)
{
- throw VersionIncomplete("org.lwjgl");
+ auto lwjglJson = PathCombine(m_instance->instanceRoot(), "patches" , "org.lwjgl.json");
+ ProfilePatchPtr lwjglPatch;
+ if(QFile::exists(lwjglJson))
+ {
+ auto file = ProfileUtils::parseJsonFile(QFileInfo(lwjglJson), false);
+ file->setVanilla(false);
+ file->setRevertible(true);
+ lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(file);
+ }
+ else
+ {
+ // NOTE: this is obviously fake, is fixed in unstable.
+ QResource LWJGL(":/versions/LWJGL/2.9.1.json");
+ auto lwjgl = ProfileUtils::parseJsonFile(LWJGL.absoluteFilePath(), false);
+ lwjgl->setVanilla(true);
+ lwjgl->setCustomizable(true);
+ lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(lwjgl);
+ }
+ if (!lwjglPatch)
+ {
+ throw VersionIncomplete("org.lwjgl");
+ }
+ lwjglPatch->setOrder(-1);
+ profile->appendPatch(lwjglPatch);
}
- lwjglPatch->setOrder(-1);
- lwjgl->setVanilla(true);
- profile->appendPatch(lwjglPatch);
}
void OneSixProfileStrategy::loadUserPatches()
@@ -149,6 +165,8 @@ void OneSixProfileStrategy::loadUserPatches()
throw VersionBuildError(
QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId));
}
+ file->setRemovable(true);
+ file->setMovable(true);
profile->appendPatch(file);
}
// now load the rest by internal preference.
@@ -172,6 +190,8 @@ void OneSixProfileStrategy::loadUserPatches()
throw VersionBuildError(QObject::tr("%1 has the same order as %2")
.arg(file->fileId, files[file->order].second->fileId));
}
+ file->setRemovable(true);
+ file->setMovable(true);
files.insert(file->order, qMakePair(info.fileName(), file));
}
for (auto order : files.keys())
@@ -243,6 +263,74 @@ bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch)
return ok;
}
+bool OneSixProfileStrategy::customizePatch(ProfilePatchPtr patch)
+{
+ if(patch->isCustom())
+ {
+ return false;
+ }
+
+ auto filename = PathCombine(m_instance->instanceRoot(), "patches" , patch->getPatchID() + ".json");
+ if(!ensureFilePathExists(filename))
+ {
+ return false;
+ }
+ QSaveFile jsonFile(filename);
+ if(!jsonFile.open(QIODevice::WriteOnly))
+ {
+ return false;
+ }
+ auto document = patch->toJson(true);
+ jsonFile.write(document.toJson());
+ if(!jsonFile.commit())
+ {
+ return false;
+ }
+ try
+ {
+ load();
+ }
+ catch (VersionIncomplete &error)
+ {
+ qDebug() << "Version was incomplete:" << error.cause();
+ }
+ catch (MMCError &error)
+ {
+ qWarning() << "Version could not be loaded:" << error.cause();
+ }
+ return true;
+}
+
+bool OneSixProfileStrategy::revertPatch(ProfilePatchPtr patch)
+{
+ if(!patch->isCustom())
+ {
+ // already not custom
+ return true;
+ }
+ auto filename = patch->getPatchFilename();
+ if(!QFile::exists(filename))
+ {
+ // already gone / not custom
+ return true;
+ }
+ // just kill the file and reload
+ bool result = QFile::remove(filename);
+ try
+ {
+ load();
+ }
+ catch (VersionIncomplete &error)
+ {
+ qDebug() << "Version was incomplete:" << error.cause();
+ }
+ catch (MMCError &error)
+ {
+ qWarning() << "Version could not be loaded:" << error.cause();
+ }
+ return result;
+}
+
bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
{
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
diff --git a/logic/minecraft/OneSixProfileStrategy.h b/logic/minecraft/OneSixProfileStrategy.h
index b554b1ea..b140dee5 100644
--- a/logic/minecraft/OneSixProfileStrategy.h
+++ b/logic/minecraft/OneSixProfileStrategy.h
@@ -13,6 +13,8 @@ public:
virtual bool saveOrder(ProfileUtils::PatchOrder order) override;
virtual bool installJarMods(QStringList filepaths) override;
virtual bool removePatch(ProfilePatchPtr patch) override;
+ virtual bool customizePatch(ProfilePatchPtr patch) override;
+ virtual bool revertPatch(ProfilePatchPtr patch) override;
protected:
void loadDefaultBuiltinPatches();
@@ -21,4 +23,4 @@ protected:
protected:
OneSixInstance *m_instance;
-}; \ No newline at end of file
+};
diff --git a/logic/minecraft/ProfilePatch.h b/logic/minecraft/ProfilePatch.h
index 2e97677e..de42cb7a 100644
--- a/logic/minecraft/ProfilePatch.h
+++ b/logic/minecraft/ProfilePatch.h
@@ -2,6 +2,7 @@
#include <memory>
#include <QList>
+#include <QJsonDocument>
#include "JarMod.h"
class MinecraftProfile;
@@ -10,15 +11,20 @@ class ProfilePatch
public:
virtual ~ProfilePatch(){};
virtual void applyTo(MinecraftProfile *version) = 0;
+ virtual QJsonDocument toJson(bool saveOrder) = 0;
virtual bool isMinecraftVersion() = 0;
virtual bool hasJarMods() = 0;
virtual QList<JarmodPtr> getJarMods() = 0;
- virtual bool isMoveable()
- {
- return getOrder() >= 0;
- }
+ virtual bool isMoveable() = 0;
+ virtual bool isCustomizable() = 0;
+ virtual bool isRevertible() = 0;
+ virtual bool isRemovable() = 0;
+ virtual bool isCustom() = 0;
+ virtual bool isEditable() = 0;
+ virtual bool isVersionChangeable() = 0;
+
virtual void setOrder(int order) = 0;
virtual int getOrder() = 0;
@@ -26,7 +32,6 @@ public:
virtual QString getPatchName() = 0;
virtual QString getPatchVersion() = 0;
virtual QString getPatchFilename() = 0;
- virtual bool isCustom() = 0;
};
typedef std::shared_ptr<ProfilePatch> ProfilePatchPtr;
diff --git a/logic/minecraft/ProfileStrategy.h b/logic/minecraft/ProfileStrategy.h
index 364458f5..b4dfc4b3 100644
--- a/logic/minecraft/ProfileStrategy.h
+++ b/logic/minecraft/ProfileStrategy.h
@@ -25,6 +25,11 @@ public:
/// remove any files or records that constitute the version patch
virtual bool removePatch(ProfilePatchPtr jarMod) = 0;
+ /// make the patch custom, if possible
+ virtual bool customizePatch(ProfilePatchPtr patch) = 0;
+
+ /// revert the custom patch to 'vanilla', if possible
+ virtual bool revertPatch(ProfilePatchPtr patch) = 0;
protected:
MinecraftProfile *profile;
};
diff --git a/logic/minecraft/VersionFile.h b/logic/minecraft/VersionFile.h
index 346a8dcd..dd5c962f 100644
--- a/logic/minecraft/VersionFile.h
+++ b/logic/minecraft/VersionFile.h
@@ -20,7 +20,7 @@ class VersionFile : public ProfilePatch
public: /* methods */
static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename,
const bool requireOrder);
- QJsonDocument toJson(bool saveOrder);
+ virtual QJsonDocument toJson(bool saveOrder) override;
virtual void applyTo(MinecraftProfile *version) override;
virtual bool isMinecraftVersion() override;
@@ -53,18 +53,64 @@ public: /* methods */
{
return filename;
}
- virtual bool isCustom()
+ virtual bool isCustom() override
{
- return !isVanilla;
+ return !m_isVanilla;
};
+ virtual bool isCustomizable() override
+ {
+ return m_isCustomizable;
+ }
+ virtual bool isRemovable() override
+ {
+ return m_isRemovable;
+ }
+ virtual bool isRevertible() override
+ {
+ return m_isRevertible;
+ }
+ virtual bool isMoveable() override
+ {
+ return m_isMovable;
+ }
+ virtual bool isEditable() override
+ {
+ return isCustom();
+ }
+ virtual bool isVersionChangeable() override
+ {
+ return false;
+ }
+
void setVanilla (bool state)
{
- isVanilla = state;
+ m_isVanilla = state;
+ }
+ void setRemovable (bool state)
+ {
+ m_isRemovable = state;
+ }
+ void setRevertible (bool state)
+ {
+ m_isRevertible = state;
}
+ void setCustomizable (bool state)
+ {
+ m_isCustomizable = state;
+ }
+ void setMovable (bool state)
+ {
+ m_isMovable = state;
+ }
+
public: /* data */
int order = 0;
- bool isVanilla = false;
+ bool m_isVanilla = false;
+ bool m_isRemovable = false;
+ bool m_isRevertible = false;
+ bool m_isCustomizable = false;
+ bool m_isMovable = false;
QString name;
QString fileId;
QString version;