NOISSUE Use patch problems and problem levels instead of exceptions for minecraft profiles.

This commit is contained in:
Petr Mrázek 2016-03-18 15:02:54 +01:00
parent fb9dfcb951
commit b7d8e512f4
10 changed files with 172 additions and 147 deletions

View File

@ -1529,6 +1529,10 @@ void MainWindow::on_actionLaunchInstanceOffline_triggered()
void MainWindow::launch(InstancePtr instance, bool online, BaseProfilerFactory *profiler) void MainWindow::launch(InstancePtr instance, bool online, BaseProfilerFactory *profiler)
{ {
if(!instance->canLaunch())
{
return;
}
m_launchController.reset(new LaunchController()); m_launchController.reset(new LaunchController());
m_launchController->setInstance(instance); m_launchController->setInstance(instance);
m_launchController->setOnline(online); m_launchController->setOnline(online);
@ -1565,7 +1569,9 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
m_selectedInstance = MMC->instances()->getInstanceById(id); m_selectedInstance = MMC->instances()->getInstanceById(id);
if (m_selectedInstance) if (m_selectedInstance)
{ {
ui->instanceToolBar->setEnabled(m_selectedInstance->canLaunch()); ui->instanceToolBar->setEnabled(true);
ui->actionLaunchInstance->setEnabled(m_selectedInstance->canLaunch());
ui->actionLaunchInstanceOffline->setEnabled(m_selectedInstance->canLaunch());
renameButton->setText(m_selectedInstance->name()); renameButton->setText(m_selectedInstance->name());
m_statusLeft->setText(m_selectedInstance->getStatusbarDescription()); m_statusLeft->setText(m_selectedInstance->getStatusbarDescription());
updateInstanceToolIcon(m_selectedInstance->iconKey()); updateInstanceToolIcon(m_selectedInstance->iconKey());
@ -1576,6 +1582,7 @@ void MainWindow::instanceChanged(const QModelIndex &current, const QModelIndex &
} }
else else
{ {
ui->instanceToolBar->setEnabled(false);
MMC->settings()->set("SelectedInstance", QString()); MMC->settings()->set("SelectedInstance", QString());
selectionBad(); selectionBad();
return; return;

View File

@ -54,36 +54,38 @@ void MinecraftProfile::reload()
{ {
beginResetModel(); beginResetModel();
m_strategy->load(); m_strategy->load();
reapplySafe(); reapplyPatches();
endResetModel(); endResetModel();
} }
void MinecraftProfile::clear() void MinecraftProfile::clear()
{ {
id.clear(); m_minecraftVersion.clear();
type.clear(); m_minecraftVersionType.clear();
assets.clear(); m_minecraftAssets.clear();
minecraftArguments.clear(); m_minecraftArguments.clear();
mainClass.clear(); m_tweakers.clear();
appletClass.clear(); m_mainClass.clear();
libraries.clear(); m_appletClass.clear();
tweakers.clear(); m_libraries.clear();
jarMods.clear(); m_nativeLibraries.clear();
traits.clear(); m_traits.clear();
m_jarMods.clear();
m_problemSeverity = ProblemSeverity::PROBLEM_NONE;
} }
void MinecraftProfile::clearPatches() void MinecraftProfile::clearPatches()
{ {
beginResetModel(); beginResetModel();
VersionPatches.clear(); m_patches.clear();
endResetModel(); endResetModel();
} }
void MinecraftProfile::appendPatch(ProfilePatchPtr patch) void MinecraftProfile::appendPatch(ProfilePatchPtr patch)
{ {
int index = VersionPatches.size(); int index = m_patches.size();
beginInsertRows(QModelIndex(), index, index); beginInsertRows(QModelIndex(), index, index);
VersionPatches.append(patch); m_patches.append(patch);
endInsertRows(); endInsertRows();
} }
@ -103,9 +105,9 @@ bool MinecraftProfile::remove(const int index)
} }
beginRemoveRows(QModelIndex(), index, index); beginRemoveRows(QModelIndex(), index, index);
VersionPatches.removeAt(index); m_patches.removeAt(index);
endRemoveRows(); endRemoveRows();
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
return true; return true;
} }
@ -113,7 +115,7 @@ bool MinecraftProfile::remove(const int index)
bool MinecraftProfile::remove(const QString id) bool MinecraftProfile::remove(const QString id)
{ {
int i = 0; int i = 0;
for (auto patch : VersionPatches) for (auto patch : m_patches)
{ {
if (patch->getID() == id) if (patch->getID() == id)
{ {
@ -137,7 +139,7 @@ bool MinecraftProfile::customize(int index)
qCritical() << "Patch" << patch->getID() << "could not be customized"; qCritical() << "Patch" << patch->getID() << "could not be customized";
return false; return false;
} }
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
// FIXME: maybe later in unstable // FIXME: maybe later in unstable
// emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
@ -157,25 +159,16 @@ bool MinecraftProfile::revertToBase(int index)
qCritical() << "Patch" << patch->getID() << "could not be reverted"; qCritical() << "Patch" << patch->getID() << "could not be reverted";
return false; return false;
} }
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
// FIXME: maybe later in unstable // FIXME: maybe later in unstable
// emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1)); // emit dataChanged(createIndex(index, 0), createIndex(index, columnCount(QModelIndex()) - 1));
return true; return true;
} }
QString MinecraftProfile::versionFileId(const int index) const
{
if (index < 0 || index >= VersionPatches.size())
{
return QString();
}
return VersionPatches.at(index)->getID();
}
ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id) ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id)
{ {
for (auto file : VersionPatches) for (auto file : m_patches)
{ {
if (file->getID() == id) if (file->getID() == id)
{ {
@ -187,14 +180,14 @@ ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id)
ProfilePatchPtr MinecraftProfile::versionPatch(int index) ProfilePatchPtr MinecraftProfile::versionPatch(int index)
{ {
if(index < 0 || index >= VersionPatches.size()) if(index < 0 || index >= m_patches.size())
return nullptr; return nullptr;
return VersionPatches[index]; return m_patches[index];
} }
bool MinecraftProfile::isVanilla() bool MinecraftProfile::isVanilla()
{ {
for(auto patchptr: VersionPatches) for(auto patchptr: m_patches)
{ {
if(patchptr->isCustom()) if(patchptr->isCustom())
return false; return false;
@ -205,7 +198,7 @@ bool MinecraftProfile::isVanilla()
bool MinecraftProfile::revertToVanilla() bool MinecraftProfile::revertToVanilla()
{ {
// remove patches, if present // remove patches, if present
auto VersionPatchesCopy = VersionPatches; auto VersionPatchesCopy = m_patches;
for(auto & it: VersionPatchesCopy) for(auto & it: VersionPatchesCopy)
{ {
if (!it->isCustom()) if (!it->isCustom())
@ -217,13 +210,13 @@ bool MinecraftProfile::revertToVanilla()
if(!remove(it->getID())) if(!remove(it->getID()))
{ {
qWarning() << "Couldn't remove" << it->getID() << "from profile!"; qWarning() << "Couldn't remove" << it->getID() << "from profile!";
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
return false; return false;
} }
} }
} }
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
return true; return true;
} }
@ -236,17 +229,17 @@ QVariant MinecraftProfile::data(const QModelIndex &index, int role) const
int row = index.row(); int row = index.row();
int column = index.column(); int column = index.column();
if (row < 0 || row >= VersionPatches.size()) if (row < 0 || row >= m_patches.size())
return QVariant(); return QVariant();
auto patch = VersionPatches.at(row); auto patch = m_patches.at(row);
if (role == Qt::DisplayRole) if (role == Qt::DisplayRole)
{ {
switch (column) switch (column)
{ {
case 0: case 0:
return VersionPatches.at(row)->getName(); return m_patches.at(row)->getName();
case 1: case 1:
{ {
if(patch->isCustom()) if(patch->isCustom())
@ -315,7 +308,7 @@ Qt::ItemFlags MinecraftProfile::flags(const QModelIndex &index) const
int MinecraftProfile::rowCount(const QModelIndex &parent) const int MinecraftProfile::rowCount(const QModelIndex &parent) const
{ {
return VersionPatches.size(); return m_patches.size();
} }
int MinecraftProfile::columnCount(const QModelIndex &parent) const int MinecraftProfile::columnCount(const QModelIndex &parent) const
@ -326,7 +319,7 @@ int MinecraftProfile::columnCount(const QModelIndex &parent) const
void MinecraftProfile::saveCurrentOrder() const void MinecraftProfile::saveCurrentOrder() const
{ {
ProfileUtils::PatchOrder order; ProfileUtils::PatchOrder order;
for(auto item: VersionPatches) for(auto item: m_patches)
{ {
if(!item->isMoveable()) if(!item->isMoveable())
continue; continue;
@ -347,7 +340,7 @@ void MinecraftProfile::move(const int index, const MoveDirection direction)
theirIndex = index + 1; theirIndex = index + 1;
} }
if (index < 0 || index >= VersionPatches.size()) if (index < 0 || index >= m_patches.size())
return; return;
if (theirIndex >= rowCount()) if (theirIndex >= rowCount())
theirIndex = rowCount() - 1; theirIndex = rowCount() - 1;
@ -365,9 +358,9 @@ void MinecraftProfile::move(const int index, const MoveDirection direction)
return; return;
} }
beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap); beginMoveRows(QModelIndex(), index, index, QModelIndex(), togap);
VersionPatches.swap(index, theirIndex); m_patches.swap(index, theirIndex);
endMoveRows(); endMoveRows();
reapplySafe(); reapplyPatches();
saveCurrentOrder(); saveCurrentOrder();
} }
void MinecraftProfile::resetOrder() void MinecraftProfile::resetOrder()
@ -376,20 +369,15 @@ void MinecraftProfile::resetOrder()
reload(); reload();
} }
void MinecraftProfile::reapply() bool MinecraftProfile::reapplyPatches()
{
clear();
for(auto file: VersionPatches)
{
file->applyTo(this);
}
}
bool MinecraftProfile::reapplySafe()
{ {
try try
{ {
reapply(); clear();
for(auto file: m_patches)
{
file->applyTo(this);
}
} }
catch (Exception & error) catch (Exception & error)
{ {
@ -409,37 +397,37 @@ static void applyString(const QString & from, QString & to)
void MinecraftProfile::applyMinecraftVersion(const QString& id) void MinecraftProfile::applyMinecraftVersion(const QString& id)
{ {
applyString(id, this->id); applyString(id, this->m_minecraftVersion);
} }
void MinecraftProfile::applyAppletClass(const QString& appletClass) void MinecraftProfile::applyAppletClass(const QString& appletClass)
{ {
applyString(appletClass, this->appletClass); applyString(appletClass, this->m_appletClass);
} }
void MinecraftProfile::applyMainClass(const QString& mainClass) void MinecraftProfile::applyMainClass(const QString& mainClass)
{ {
applyString(mainClass, this->mainClass); applyString(mainClass, this->m_mainClass);
} }
void MinecraftProfile::applyMinecraftArguments(const QString& minecraftArguments) void MinecraftProfile::applyMinecraftArguments(const QString& minecraftArguments)
{ {
applyString(minecraftArguments, this->minecraftArguments); applyString(minecraftArguments, this->m_minecraftArguments);
} }
void MinecraftProfile::applyMinecraftVersionType(const QString& type) void MinecraftProfile::applyMinecraftVersionType(const QString& type)
{ {
applyString(type, this->type); applyString(type, this->m_minecraftVersionType);
} }
void MinecraftProfile::applyMinecraftAssets(const QString& assets) void MinecraftProfile::applyMinecraftAssets(const QString& assets)
{ {
applyString(assets, this->assets); applyString(assets, this->m_minecraftAssets);
} }
void MinecraftProfile::applyTraits(const QSet<QString>& traits) void MinecraftProfile::applyTraits(const QSet<QString>& traits)
{ {
this->traits.unite(traits); this->m_traits.unite(traits);
} }
void MinecraftProfile::applyTweakers(const QStringList& tweakers) void MinecraftProfile::applyTweakers(const QStringList& tweakers)
@ -448,13 +436,13 @@ void MinecraftProfile::applyTweakers(const QStringList& tweakers)
// FIXME: does order matter? // FIXME: does order matter?
for (auto tweaker : tweakers) for (auto tweaker : tweakers)
{ {
this->tweakers += tweaker; this->m_tweakers += tweaker;
} }
} }
void MinecraftProfile::applyJarMods(const QList<JarmodPtr>& jarMods) void MinecraftProfile::applyJarMods(const QList<JarmodPtr>& jarMods)
{ {
this->jarMods.append(jarMods); this->m_jarMods.append(jarMods);
} }
static int findLibraryByName(QList<LibraryPtr> haystack, const GradleSpecifier &needle) static int findLibraryByName(QList<LibraryPtr> haystack, const GradleSpecifier &needle)
@ -499,49 +487,61 @@ void MinecraftProfile::applyLibrary(LibraryPtr library)
} }
if(library->isNative()) if(library->isNative())
{ {
insert(nativeLibraries); insert(m_nativeLibraries);
} }
else else
{ {
insert(libraries); insert(m_libraries);
}
}
void MinecraftProfile::applyProblemSeverity(ProblemSeverity severity)
{
if (m_problemSeverity < severity)
{
m_problemSeverity = severity;
} }
} }
QString MinecraftProfile::getMinecraftVersion() const QString MinecraftProfile::getMinecraftVersion() const
{ {
return id; return m_minecraftVersion;
} }
QString MinecraftProfile::getAppletClass() const QString MinecraftProfile::getAppletClass() const
{ {
return appletClass; return m_appletClass;
} }
QString MinecraftProfile::getMainClass() const QString MinecraftProfile::getMainClass() const
{ {
return mainClass; return m_mainClass;
} }
const QSet<QString> &MinecraftProfile::getTraits() const const QSet<QString> &MinecraftProfile::getTraits() const
{ {
return traits; return m_traits;
} }
const QStringList & MinecraftProfile::getTweakers() const const QStringList & MinecraftProfile::getTweakers() const
{ {
return tweakers; return m_tweakers;
} }
bool MinecraftProfile::hasTrait(const QString& trait) const bool MinecraftProfile::hasTrait(const QString& trait) const
{ {
return traits.contains(trait); return m_traits.contains(trait);
} }
ProblemSeverity MinecraftProfile::getProblemSeverity() const
{
return m_problemSeverity;
}
QString MinecraftProfile::getMinecraftVersionType() const QString MinecraftProfile::getMinecraftVersionType() const
{ {
return type; return m_minecraftVersionType;
} }
QString MinecraftProfile::getMinecraftAssets() const QString MinecraftProfile::getMinecraftAssets() const
@ -549,35 +549,35 @@ QString MinecraftProfile::getMinecraftAssets() const
// HACK: deny april fools. my head hurts enough already. // HACK: deny april fools. my head hurts enough already.
QDate now = QDate::currentDate(); QDate now = QDate::currentDate();
bool isAprilFools = now.month() == 4 && now.day() == 1; bool isAprilFools = now.month() == 4 && now.day() == 1;
if (assets.endsWith("_af") && !isAprilFools) if (m_minecraftAssets.endsWith("_af") && !isAprilFools)
{ {
return assets.left(assets.length() - 3); return m_minecraftAssets.left(m_minecraftAssets.length() - 3);
} }
if (assets.isEmpty()) if (m_minecraftAssets.isEmpty())
{ {
return QLatin1Literal("legacy"); return QLatin1Literal("legacy");
} }
return assets; return m_minecraftAssets;
} }
QString MinecraftProfile::getMinecraftArguments() const QString MinecraftProfile::getMinecraftArguments() const
{ {
return minecraftArguments; return m_minecraftArguments;
} }
const QList<JarmodPtr> & MinecraftProfile::getJarMods() const const QList<JarmodPtr> & MinecraftProfile::getJarMods() const
{ {
return jarMods; return m_jarMods;
} }
const QList<LibraryPtr> & MinecraftProfile::getLibraries() const const QList<LibraryPtr> & MinecraftProfile::getLibraries() const
{ {
return libraries; return m_libraries;
} }
const QList<LibraryPtr> & MinecraftProfile::getNativeLibraries() const const QList<LibraryPtr> & MinecraftProfile::getNativeLibraries() const
{ {
return nativeLibraries; return m_nativeLibraries;
} }
@ -593,7 +593,7 @@ int MinecraftProfile::getFreeOrderNumber()
{ {
int largest = 100; int largest = 100;
// yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next. // yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next.
for(auto thing: VersionPatches) for(auto thing: m_patches)
{ {
int order = thing->getOrder(); int order = thing->getOrder();
if(order > largest) if(order > largest)

View File

@ -34,7 +34,6 @@ class OneSixInstance;
class MULTIMC_LOGIC_EXPORT MinecraftProfile : public QAbstractListModel class MULTIMC_LOGIC_EXPORT MinecraftProfile : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
friend class ProfileStrategy;
public: public:
explicit MinecraftProfile(ProfileStrategy *strategy); explicit MinecraftProfile(ProfileStrategy *strategy);
@ -82,13 +81,10 @@ public:
/// clear the profile /// clear the profile
void clear(); void clear();
/// apply the patches. Throws all sorts of errors.
void reapply();
/// apply the patches. Catches all the errors and returns true/false for success/failure /// apply the patches. Catches all the errors and returns true/false for success/failure
bool reapplySafe(); bool reapplyPatches();
public: public: /* application of profile variables from patches */
void applyMinecraftVersion(const QString& id); void applyMinecraftVersion(const QString& id);
void applyMainClass(const QString& mainClass); void applyMainClass(const QString& mainClass);
void applyAppletClass(const QString& appletClass); void applyAppletClass(const QString& appletClass);
@ -99,26 +95,24 @@ public:
void applyTweakers(const QStringList &tweakers); void applyTweakers(const QStringList &tweakers);
void applyJarMods(const QList<JarmodPtr> &jarMods); void applyJarMods(const QList<JarmodPtr> &jarMods);
void applyLibrary(LibraryPtr library); void applyLibrary(LibraryPtr library);
void applyProblemSeverity(ProblemSeverity severity);
public: public: /* getters for proifile variables */
QString getMinecraftVersion() const; QString getMinecraftVersion() const;
QString getMainClass() const; QString getMainClass() const;
QString getAppletClass() const; QString getAppletClass() const;
QString getMinecraftVersionType() const; QString getMinecraftVersionType() const;
QString getMinecraftAssets() const; QString getMinecraftAssets() const;
QString getMinecraftArguments() const; QString getMinecraftArguments() const;
QString getVanillaMinecraftArguments() const;
const QSet<QString> & getTraits() const; const QSet<QString> & getTraits() const;
const QStringList & getTweakers() const; const QStringList & getTweakers() const;
const QList<JarmodPtr> & getJarMods() const; const QList<JarmodPtr> & getJarMods() const;
const QList<LibraryPtr> & getLibraries() const; const QList<LibraryPtr> & getLibraries() const;
const QList<LibraryPtr> & getNativeLibraries() const; const QList<LibraryPtr> & getNativeLibraries() const;
bool hasTrait(const QString & trait) const; bool hasTrait(const QString & trait) const;
ProblemSeverity getProblemSeverity() const;
public: public:
/// get file ID of the patch file at #
QString versionFileId(const int index) const;
/// get the profile patch by id /// get the profile patch by id
ProfilePatchPtr versionPatch(const QString &id); ProfilePatchPtr versionPatch(const QString &id);
@ -134,15 +128,15 @@ public:
/// Add the patch object to the internal list of patches /// Add the patch object to the internal list of patches
void appendPatch(ProfilePatchPtr patch); void appendPatch(ProfilePatchPtr patch);
protected: /* data */ private: /* data */
/// the ID - determines which jar to use! ACTUALLY IMPORTANT! /// the version of Minecraft - jar to use
QString id; QString m_minecraftVersion;
/// Release type - "release" or "snapshot" /// Release type - "release" or "snapshot"
QString type; QString m_minecraftVersionType;
/// Assets type - "legacy" or a version ID /// Assets type - "legacy" or a version ID
QString assets; QString m_minecraftAssets;
/** /**
* arguments that should be used for launching minecraft * arguments that should be used for launching minecraft
@ -150,28 +144,30 @@ protected: /* data */
* ex: "--username ${auth_player_name} --session ${auth_session} * ex: "--username ${auth_player_name} --session ${auth_session}
* --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}" * --version ${version_name} --gameDir ${game_directory} --assetsDir ${game_assets}"
*/ */
QString minecraftArguments; QString m_minecraftArguments;
/// A list of all tweaker classes /// A list of all tweaker classes
QStringList tweakers; QStringList m_tweakers;
/// The main class to load first /// The main class to load first
QString mainClass; QString m_mainClass;
/// The applet class, for some very old minecraft releases /// The applet class, for some very old minecraft releases
QString appletClass; QString m_appletClass;
/// the list of libraries /// the list of libraries
QList<LibraryPtr> libraries; QList<LibraryPtr> m_libraries;
/// the list of native libraries /// the list of native libraries
QList<LibraryPtr> nativeLibraries; QList<LibraryPtr> m_nativeLibraries;
/// traits, collected from all the version files (version files can only add) /// traits, collected from all the version files (version files can only add)
QSet<QString> traits; QSet<QString> m_traits;
/// A list of jar mods. version files can add those. /// A list of jar mods. version files can add those.
QList<JarmodPtr> jarMods; QList<JarmodPtr> m_jarMods;
ProblemSeverity m_problemSeverity = PROBLEM_NONE;
/* /*
FIXME: add support for those rules here? Looks like a pile of quick hacks to me though. FIXME: add support for those rules here? Looks like a pile of quick hacks to me though.
@ -193,7 +189,10 @@ protected: /* data */
} }
*/ */
// QList<Rule> rules; // QList<Rule> rules;
private:
QList<ProfilePatchPtr> VersionPatches; /// list of attached profile patches
QList<ProfilePatchPtr> m_patches;
/// strategy used for profile operations
ProfileStrategy *m_strategy = nullptr; ProfileStrategy *m_strategy = nullptr;
}; };

View File

@ -169,6 +169,7 @@ void MinecraftVersion::applyTo(MinecraftProfile *profile)
profile->applyMinecraftArguments(" ${auth_player_name} ${auth_session}"); // all builtin versions are legacy profile->applyMinecraftArguments(" ${auth_player_name} ${auth_session}"); // all builtin versions are legacy
profile->applyMinecraftVersionType(m_type); profile->applyMinecraftVersionType(m_type);
profile->applyTraits(m_traits); profile->applyTraits(m_traits);
profile->applyProblemSeverity(m_problemSeverity);
} }
int MinecraftVersion::getOrder() int MinecraftVersion::getOrder()

View File

@ -99,20 +99,42 @@ bool readOverrideOrders(QString path, PatchOrder &order)
return true; return true;
} }
static VersionFilePtr createErrorVersionFile(QString fileId, QString filepath, QString error)
{
auto outError = std::make_shared<VersionFile>();
outError->fileId = outError->name = fileId;
outError->filename = filepath;
outError->addProblem(PROBLEM_ERROR, error);
return outError;
}
static VersionFilePtr guardedParseJson(const QJsonDocument & doc,const QString &fileId,const QString &filepath,const bool &requireOrder)
{
try
{
return OneSixVersionFormat::versionFileFromJson(doc, filepath, requireOrder);
}
catch (Exception & e)
{
return createErrorVersionFile(fileId, filepath, e.cause());
}
}
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder) VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder)
{ {
QFile file(fileInfo.absoluteFilePath()); QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly)) if (!file.open(QFile::ReadOnly))
{ {
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.") auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString());
.arg(fileInfo.fileName(), file.errorString())); return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
} }
QJsonParseError error; QJsonParseError error;
auto data = file.readAll(); auto data = file.readAll();
QJsonDocument doc = QJsonDocument::fromJson(data, &error); QJsonDocument doc = QJsonDocument::fromJson(data, &error);
file.close();
if (error.error != QJsonParseError::NoError) if (error.error != QJsonParseError::NoError)
{ {
int line = 0; int line = 1;
int column = 0; int column = 0;
for(int i = 0; i < error.offset; i++) for(int i = 0; i < error.offset; i++)
{ {
@ -124,12 +146,12 @@ VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder)
} }
column++; column++;
} }
throw JSONValidationError( auto errorStr = QObject::tr("Unable to process the version file %1: %2 at line %3 column %4.")
QObject::tr("Unable to process the version file %1: %2 at line %3 column %4.")
.arg(fileInfo.fileName(), error.errorString()) .arg(fileInfo.fileName(), error.errorString())
.arg(line).arg(column)); .arg(line).arg(column);
return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
} }
return OneSixVersionFormat::versionFileFromJson(doc, file.fileName(), requireOrder); return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), requireOrder);
} }
VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo) VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
@ -137,18 +159,17 @@ VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
QFile file(fileInfo.absoluteFilePath()); QFile file(fileInfo.absoluteFilePath());
if (!file.open(QFile::ReadOnly)) if (!file.open(QFile::ReadOnly))
{ {
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.") auto errorStr = QObject::tr("Unable to open the version file %1: %2.").arg(fileInfo.fileName(), file.errorString());
.arg(fileInfo.fileName(), file.errorString())); return createErrorVersionFile(fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), errorStr);
} }
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll()); QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
file.close(); file.close();
if (doc.isNull()) if (doc.isNull())
{ {
file.remove(); file.remove();
throw JSONValidationError( throw JSONValidationError(QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
} }
return OneSixVersionFormat::versionFileFromJson(doc, file.fileName(), false); return guardedParseJson(doc, fileInfo.completeBaseName(), fileInfo.absoluteFilePath(), false);
} }
void removeLwjglFromPatch(VersionFilePtr patch) void removeLwjglFromPatch(VersionFilePtr patch)

View File

@ -50,4 +50,5 @@ void VersionFile::applyTo(MinecraftProfile *profile)
{ {
profile->applyLibrary(library); profile->applyLibrary(library);
} }
profile->applyProblemSeverity(getProblemSeverity());
} }

View File

@ -82,6 +82,17 @@ void ForgeInstaller::prepare(const QString &filename, const QString &universalUr
} }
catch(Exception &err) catch(Exception &err)
{ {
qWarning() << "Forge: Fatal error while parsing version file:" << err.what();
return;
}
for(auto problem: newVersion->getProblems())
{
qWarning() << "Forge: Problem found: " << problem.getDescription();
}
if(newVersion->getProblemSeverity() == ProblemSeverity::PROBLEM_ERROR)
{
qWarning() << "Forge: Errors found while parsing version file";
return; return;
} }

View File

@ -462,24 +462,18 @@ QString OneSixInstance::currentVersionId() const
} }
void OneSixInstance::reloadProfile() void OneSixInstance::reloadProfile()
{
try
{ {
m_profile->reload(); m_profile->reload();
unsetFlag(VersionBrokenFlag); auto severity = m_profile->getProblemSeverity();
emit versionReloaded(); if(severity == ProblemSeverity::PROBLEM_ERROR)
}
catch (VersionIncomplete &error)
{ {
}
catch (Exception &error)
{
m_profile->clear();
setFlag(VersionBrokenFlag); setFlag(VersionBrokenFlag);
// TODO: rethrow to show some error message(s)?
emit versionReloaded();
throw;
} }
else
{
unsetFlag(VersionBrokenFlag);
}
emit versionReloaded();
} }
void OneSixInstance::clearProfile() void OneSixInstance::clearProfile()

View File

@ -407,7 +407,7 @@ bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
profile->appendPatch(f); profile->appendPatch(f);
} }
profile->saveCurrentOrder(); profile->saveCurrentOrder();
profile->reapplySafe(); profile->reapplyPatches();
return true; return true;
} }

View File

@ -174,19 +174,10 @@ void OneSixUpdate::jarlibStart()
setStatus(tr("Getting the library files from Mojang...")); setStatus(tr("Getting the library files from Mojang..."));
qDebug() << m_inst->name() << ": downloading libraries"; qDebug() << m_inst->name() << ": downloading libraries";
OneSixInstance *inst = (OneSixInstance *)m_inst; OneSixInstance *inst = (OneSixInstance *)m_inst;
try
{
inst->reloadProfile(); inst->reloadProfile();
} if(inst->flags() & BaseInstance::VersionBrokenFlag)
catch (Exception &e)
{ {
emitFailed(e.cause()); emitFailed(tr("Failed to load the version description files - check the instance for errors."));
return;
}
catch (...)
{
emitFailed(tr("Failed to load the version description file for reasons unknown."));
return;
} }
// Build a list of URLs that will need to be downloaded. // Build a list of URLs that will need to be downloaded.