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
This commit is contained in:
Petr Mrázek 2015-05-17 23:38:28 +02:00
parent 6ab6a450f6
commit 743af4769e
15 changed files with 553 additions and 156 deletions

View File

@ -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;
}
if(row >= m_version->rowCount(QModelIndex()))
{
row = m_version->rowCount(QModelIndex()) - 1;
}
if(row < 0)
{
return;
}
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->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
{
bool enabled = m_version->canRemove(current.row());
ui->removeLibraryBtn->setEnabled(enabled);
ui->moveLibraryDownBtn->setEnabled(enabled);
ui->moveLibraryUpBtn->setEnabled(enabled);
}
QString selectedId = m_version->versionFileId(current.row());
if (selectedId == "net.minecraft")
{
ui->changeMCVersionBtn->setEnabled(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);
}

View File

@ -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:

View File

@ -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,12 +95,58 @@
</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>
@ -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>

View File

@ -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)
{
return false;
}
bool FTBProfileStrategy::installJarMods(QStringList filepaths)
{
return false;
}
bool FTBProfileStrategy::customizePatch(ProfilePatchPtr patch)
{
return false;
}
bool FTBProfileStrategy::revertPatch(ProfilePatchPtr patch)
{
return false;
}

View File

@ -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();

View File

@ -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()))
{
endResetModel();
saveCurrentOrder();
return false;
}
it = VersionPatches.erase(it);
continue;
}
if(it->isRevertible() || it->isRemovable())
{
if(!remove(it->getPatchID()))
{
qWarning() << "Couldn't remove" << it->getPatchID() << "from profile!";
reapply();
saveCurrentOrder();
return false;
}
}
else
it++;
}
reapply();
endResetModel();
saveCurrentOrder();
return true;
*/
return false;
}
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNormalLibs()

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
};
};

View File

@ -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");
}
minecraftPatch->setOrder(-2);
profile->appendPatch(minecraftPatch);
}
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);
// 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");

View File

@ -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;
};
};

View File

@ -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;

View File

@ -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;
};

View File

@ -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;