summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--application/pages/VersionPage.cpp172
-rw-r--r--application/pages/VersionPage.h29
-rw-r--r--application/pages/VersionPage.ui98
-rw-r--r--logic/ftb/FTBProfileStrategy.cpp14
-rw-r--r--logic/ftb/FTBProfileStrategy.h3
-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
15 files changed, 542 insertions, 145 deletions
diff --git a/application/pages/VersionPage.cpp b/application/pages/VersionPage.cpp
index ab4aecf6..bb310eea 100644
--- a/application/pages/VersionPage.cpp
+++ b/application/pages/VersionPage.cpp
@@ -67,16 +67,14 @@ VersionPage::VersionPage(OneSixInstance *inst, QWidget *parent)
m_version = m_inst->getMinecraftProfile();
if (m_version)
{
- ui->libraryTreeView->setModel(m_version.get());
- ui->libraryTreeView->installEventFilter(this);
- ui->libraryTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
- connect(ui->libraryTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
+ ui->packageView->setModel(m_version.get());
+ ui->packageView->installEventFilter(this);
+ ui->packageView->setSelectionMode(QAbstractItemView::SingleSelection);
+ connect(ui->packageView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &VersionPage::versionCurrent);
updateVersionControls();
// select first item.
- auto index = ui->libraryTreeView->model()->index(0,0);
- if(index.isValid())
- ui->libraryTreeView->setCurrentIndex(index);
+ preselect(0);
}
else
{
@@ -95,14 +93,15 @@ void VersionPage::updateVersionControls()
{
ui->forgeBtn->setEnabled(true);
ui->liteloaderBtn->setEnabled(true);
+ updateButtons();
}
void VersionPage::disableVersionControls()
{
ui->forgeBtn->setEnabled(false);
ui->liteloaderBtn->setEnabled(false);
- ui->reloadLibrariesBtn->setEnabled(false);
- ui->removeLibraryBtn->setEnabled(false);
+ ui->reloadBtn->setEnabled(false);
+ updateButtons();
}
bool VersionPage::reloadMinecraftProfile()
@@ -126,21 +125,22 @@ bool VersionPage::reloadMinecraftProfile()
}
}
-void VersionPage::on_reloadLibrariesBtn_clicked()
+void VersionPage::on_reloadBtn_clicked()
{
reloadMinecraftProfile();
}
-void VersionPage::on_removeLibraryBtn_clicked()
+void VersionPage::on_removeBtn_clicked()
{
- if (ui->libraryTreeView->currentIndex().isValid())
+ if (ui->packageView->currentIndex().isValid())
{
// FIXME: use actual model, not reloading.
- if (!m_version->remove(ui->libraryTreeView->currentIndex().row()))
+ if (!m_version->remove(ui->packageView->currentIndex().row()))
{
QMessageBox::critical(this, tr("Error"), tr("Couldn't remove file"));
}
}
+ updateButtons();
}
void VersionPage::on_jarmodBtn_clicked()
@@ -150,9 +150,10 @@ void VersionPage::on_jarmodBtn_clicked()
{
m_version->installJarMods(list);
}
+ updateButtons();
}
-void VersionPage::on_resetLibraryOrderBtn_clicked()
+void VersionPage::on_resetOrderBtn_clicked()
{
try
{
@@ -162,43 +163,36 @@ void VersionPage::on_resetLibraryOrderBtn_clicked()
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
+ updateButtons();
}
-void VersionPage::on_moveLibraryUpBtn_clicked()
+void VersionPage::on_moveUpBtn_clicked()
{
- if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty())
- {
- return;
- }
try
{
- const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
- m_version->move(row, MinecraftProfile::MoveUp);
+ m_version->move(currentRow(), MinecraftProfile::MoveUp);
}
catch (MMCError &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
+ updateButtons();
}
-void VersionPage::on_moveLibraryDownBtn_clicked()
+void VersionPage::on_moveDownBtn_clicked()
{
- if (ui->libraryTreeView->selectionModel()->selectedRows().isEmpty())
- {
- return;
- }
try
{
- const int row = ui->libraryTreeView->selectionModel()->selectedRows().first().row();
- m_version->move(row, MinecraftProfile::MoveDown);
+ m_version->move(currentRow(), MinecraftProfile::MoveDown);
}
catch (MMCError &e)
{
QMessageBox::critical(this, tr("Error"), e.cause());
}
+ updateButtons();
}
-void VersionPage::on_changeMCVersionBtn_clicked()
+void VersionPage::on_changeVersionBtn_clicked()
{
VersionSelectDialog vselect(m_inst->versionList().get(), tr("Change Minecraft version"),
this);
@@ -239,6 +233,7 @@ void VersionPage::on_changeMCVersionBtn_clicked()
ProgressDialog tDialog(this);
connect(updateTask.get(), SIGNAL(failed(QString)), SLOT(onGameUpdateError(QString)));
tDialog.exec(updateTask.get());
+ updateButtons();
}
void VersionPage::on_forgeBtn_clicked()
@@ -253,6 +248,7 @@ void VersionPage::on_forgeBtn_clicked()
ProgressDialog dialog(this);
dialog.exec(
ForgeInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
+ preselect(m_version->rowCount(QModelIndex())-1);
}
}
@@ -269,32 +265,59 @@ void VersionPage::on_liteloaderBtn_clicked()
ProgressDialog dialog(this);
dialog.exec(
LiteLoaderInstaller().createInstallTask(m_inst, vselect.selectedVersion(), this));
+ preselect(m_version->rowCount(QModelIndex())-1);
}
}
void VersionPage::versionCurrent(const QModelIndex &current, const QModelIndex &previous)
{
- if (!current.isValid())
+ currentIdx = current.row();
+ updateButtons(currentIdx);
+}
+
+void VersionPage::preselect(int row)
+{
+ if(row < 0)
{
- ui->removeLibraryBtn->setDisabled(true);
- ui->moveLibraryDownBtn->setDisabled(true);
- ui->moveLibraryUpBtn->setDisabled(true);
+ row = 0;
}
- else
+ if(row >= m_version->rowCount(QModelIndex()))
{
- bool enabled = m_version->canRemove(current.row());
- ui->removeLibraryBtn->setEnabled(enabled);
- ui->moveLibraryDownBtn->setEnabled(enabled);
- ui->moveLibraryUpBtn->setEnabled(enabled);
+ row = m_version->rowCount(QModelIndex()) - 1;
+ }
+ if(row < 0)
+ {
+ return;
}
- QString selectedId = m_version->versionFileId(current.row());
- if (selectedId == "net.minecraft")
+ auto model_index = m_version->index(row);
+ ui->packageView->selectionModel()->select(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+ updateButtons(row);
+}
+
+void VersionPage::updateButtons(int row)
+{
+ if(row == -1)
+ row = currentRow();
+ auto patch = m_version->versionPatch(row);
+ if (!patch)
{
- ui->changeMCVersionBtn->setEnabled(true);
+ ui->removeBtn->setDisabled(true);
+ ui->moveDownBtn->setDisabled(true);
+ ui->moveUpBtn->setDisabled(true);
+ ui->changeVersionBtn->setDisabled(true);
+ ui->editBtn->setDisabled(true);
+ ui->customizeBtn->setDisabled(true);
+ ui->revertBtn->setDisabled(true);
}
else
{
- ui->changeMCVersionBtn->setEnabled(false);
+ ui->removeBtn->setEnabled(patch->isRemovable());
+ ui->moveDownBtn->setEnabled(patch->isMoveable());
+ ui->moveUpBtn->setEnabled(patch->isMoveable());
+ ui->changeVersionBtn->setEnabled(patch->isVersionChangeable());
+ ui->editBtn->setEnabled(patch->isEditable());
+ ui->customizeBtn->setEnabled(patch->isCustomizable());
+ ui->revertBtn->setEnabled(patch->isRevertible());
}
}
@@ -303,3 +326,68 @@ void VersionPage::onGameUpdateError(QString error)
CustomMessageBox::selectable(this, tr("Error updating instance"), error,
QMessageBox::Warning)->show();
}
+
+ProfilePatchPtr VersionPage::current()
+{
+ auto row = currentRow();
+ if(row < 0)
+ {
+ return nullptr;
+ }
+ return m_version->versionPatch(row);
+}
+
+int VersionPage::currentRow()
+{
+ if (ui->packageView->selectionModel()->selectedRows().isEmpty())
+ {
+ return -1;
+ }
+ return ui->packageView->selectionModel()->selectedRows().first().row();
+}
+
+void VersionPage::on_customizeBtn_clicked()
+{
+ auto version = currentRow();
+ if(version == -1)
+ {
+ return;
+ }
+ if(!m_version->customize(version))
+ {
+ // TODO: some error box here
+ }
+ updateButtons();
+ preselect(currentIdx);
+}
+
+void VersionPage::on_editBtn_clicked()
+{
+ auto version = current();
+ if(!version)
+ {
+ return;
+ }
+ auto filename = version->getPatchFilename();
+ if(!QFileInfo::exists(filename))
+ {
+ qWarning() << "file" << filename << "can't be opened for editing, doesn't exist!";
+ return;
+ }
+ MMC->openJsonEditor(filename);
+}
+
+void VersionPage::on_revertBtn_clicked()
+{
+ auto version = currentRow();
+ if(version == -1)
+ {
+ return;
+ }
+ if(!m_version->revert(version))
+ {
+ // TODO: some error box here
+ }
+ updateButtons();
+ preselect(currentIdx);
+}
diff --git a/application/pages/VersionPage.h b/application/pages/VersionPage.h
index 0965edeb..45732b25 100644
--- a/application/pages/VersionPage.h
+++ b/application/pages/VersionPage.h
@@ -46,22 +46,29 @@ public:
return "Instance-version";
}
virtual bool shouldDisplay() const;
-private
-slots:
- // version tab
+private slots:
void on_forgeBtn_clicked();
void on_liteloaderBtn_clicked();
- void on_reloadLibrariesBtn_clicked();
- void on_removeLibraryBtn_clicked();
- void on_resetLibraryOrderBtn_clicked();
- void on_moveLibraryUpBtn_clicked();
- void on_moveLibraryDownBtn_clicked();
+ void on_reloadBtn_clicked();
+ void on_removeBtn_clicked();
+ void on_resetOrderBtn_clicked();
+ void on_moveUpBtn_clicked();
+ void on_moveDownBtn_clicked();
void on_jarmodBtn_clicked();
+ void on_revertBtn_clicked();
+ void on_editBtn_clicked();
+ void on_customizeBtn_clicked();
void updateVersionControls();
void disableVersionControls();
- void on_changeMCVersionBtn_clicked();
+ void on_changeVersionBtn_clicked();
+
+private:
+ ProfilePatchPtr current();
+ int currentRow();
+ void updateButtons(int row = -1);
+ void preselect(int row = 0);
protected:
/// FIXME: this shouldn't be necessary!
@@ -71,9 +78,9 @@ private:
Ui::VersionPage *ui;
std::shared_ptr<MinecraftProfile> m_version;
OneSixInstance *m_inst;
+ int currentIdx = 0;
-public
-slots:
+public slots:
void versionCurrent(const QModelIndex &current, const QModelIndex &previous);
private slots:
diff --git a/application/pages/VersionPage.ui b/application/pages/VersionPage.ui
index 67a556c8..1216229f 100644
--- a/application/pages/VersionPage.ui
+++ b/application/pages/VersionPage.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Version</string>
+ <string>Package Versions</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
@@ -37,7 +37,7 @@
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="ModListView" name="libraryTreeView">
+ <widget class="ModListView" name="packageView">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
@@ -65,16 +65,19 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="changeMCVersionBtn">
+ <widget class="QPushButton" name="changeVersionBtn">
+ <property name="toolTip">
+ <string>Change version of the selected package.</string>
+ </property>
<property name="text">
<string>Change version</string>
</property>
</widget>
</item>
<item>
- <widget class="QPushButton" name="moveLibraryUpBtn">
+ <widget class="QPushButton" name="moveUpBtn">
<property name="toolTip">
- <string>This isn't implemented yet.</string>
+ <string>Make the selected package apply sooner.</string>
</property>
<property name="text">
<string>Move up</string>
@@ -82,9 +85,9 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="moveLibraryDownBtn">
+ <widget class="QPushButton" name="moveDownBtn">
<property name="toolTip">
- <string>This isn't implemented yet.</string>
+ <string>Make the selected package apply later.</string>
</property>
<property name="text">
<string>Move down</string>
@@ -92,13 +95,59 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="removeLibraryBtn">
+ <widget class="QPushButton" name="removeBtn">
+ <property name="toolTip">
+ <string>Remove selected package from the instance.</string>
+ </property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
+ <widget class="LineSeparator" name="separator_4" native="true"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="customizeBtn">
+ <property name="toolTip">
+ <string>Customize selected package.</string>
+ </property>
+ <property name="text">
+ <string>Customize</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="editBtn">
+ <property name="toolTip">
+ <string>Edit selected package.</string>
+ </property>
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="revertBtn">
+ <property name="toolTip">
+ <string>Revert the selected package to default.</string>
+ </property>
+ <property name="text">
+ <string>Revert</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="LineSeparator" name="separator" native="true"/>
</item>
<item>
@@ -114,7 +163,7 @@
<item>
<widget class="QPushButton" name="forgeBtn">
<property name="toolTip">
- <string>Replace any current custom version with Minecraft Forge</string>
+ <string>Install the Minecraft Forge package.</string>
</property>
<property name="text">
<string>Install Forge</string>
@@ -123,6 +172,9 @@
</item>
<item>
<widget class="QPushButton" name="liteloaderBtn">
+ <property name="toolTip">
+ <string>Install the LiteLoader package.</string>
+ </property>
<property name="text">
<string>Install LiteLoader</string>
</property>
@@ -130,6 +182,9 @@
</item>
<item>
<widget class="QPushButton" name="jarmodBtn">
+ <property name="toolTip">
+ <string>Add a mod into the Minecraft jar file.</string>
+ </property>
<property name="text">
<string>Add jar mod</string>
</property>
@@ -149,9 +204,9 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="resetLibraryOrderBtn">
+ <widget class="QPushButton" name="resetOrderBtn">
<property name="toolTip">
- <string>This isn't implemented yet.</string>
+ <string>Reset apply order of packages.</string>
</property>
<property name="text">
<string>Reset order</string>
@@ -159,7 +214,10 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="reloadLibrariesBtn">
+ <widget class="QPushButton" name="reloadBtn">
+ <property name="toolTip">
+ <string>Reload all packages.</string>
+ </property>
<property name="text">
<string>Reload</string>
</property>
@@ -199,6 +257,22 @@
<container>1</container>
</customwidget>
</customwidgets>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>packageView</tabstop>
+ <tabstop>changeVersionBtn</tabstop>
+ <tabstop>moveUpBtn</tabstop>
+ <tabstop>moveDownBtn</tabstop>
+ <tabstop>removeBtn</tabstop>
+ <tabstop>customizeBtn</tabstop>
+ <tabstop>editBtn</tabstop>
+ <tabstop>revertBtn</tabstop>
+ <tabstop>forgeBtn</tabstop>
+ <tabstop>liteloaderBtn</tabstop>
+ <tabstop>jarmodBtn</tabstop>
+ <tabstop>resetOrderBtn</tabstop>
+ <tabstop>reloadBtn</tabstop>
+ </tabstops>
<resources/>
<connections/>
</ui>
diff --git a/logic/ftb/FTBProfileStrategy.cpp b/logic/ftb/FTBProfileStrategy.cpp
index cc20b247..ff40b642 100644
--- a/logic/ftb/FTBProfileStrategy.cpp
+++ b/logic/ftb/FTBProfileStrategy.cpp
@@ -26,6 +26,7 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
file->fileId = "net.minecraft";
file->name = QObject::tr("Minecraft (tracked)");
+ file->setVanilla(true);
if(file->version.isEmpty())
{
file->version = mcVersion;
@@ -59,6 +60,7 @@ void FTBProfileStrategy::loadDefaultBuiltinPatches()
addLib->insertType = RawLibrary::Prepend;
}
file->fileId = "org.multimc.ftb.pack";
+ file->setVanilla(true);
file->name = QObject::tr("%1 (FTB pack)").arg(m_instance->name());
if(file->version.isEmpty())
{
@@ -117,6 +119,8 @@ void FTBProfileStrategy::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.
@@ -140,6 +144,8 @@ void FTBProfileStrategy::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())
@@ -170,13 +176,17 @@ bool FTBProfileStrategy::resetOrder()
return false;
}
-bool FTBProfileStrategy::removePatch(ProfilePatchPtr patch)
+bool FTBProfileStrategy::installJarMods(QStringList filepaths)
{
return false;
}
-bool FTBProfileStrategy::installJarMods(QStringList filepaths)
+bool FTBProfileStrategy::customizePatch(ProfilePatchPtr patch)
{
return false;
}
+bool FTBProfileStrategy::revertPatch(ProfilePatchPtr patch)
+{
+ return false;
+}
diff --git a/logic/ftb/FTBProfileStrategy.h b/logic/ftb/FTBProfileStrategy.h
index 65f07069..5e5c2e73 100644
--- a/logic/ftb/FTBProfileStrategy.h
+++ b/logic/ftb/FTBProfileStrategy.h
@@ -13,7 +13,8 @@ public:
virtual bool resetOrder() override;
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();
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;