All of the broken legacy things work.
This commit is contained in:
parent
9860d5ee12
commit
92abe4c603
@ -479,6 +479,8 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/minecraft/OneSixRule.h
|
logic/minecraft/OneSixRule.h
|
||||||
logic/minecraft/OpSys.cpp
|
logic/minecraft/OpSys.cpp
|
||||||
logic/minecraft/OpSys.h
|
logic/minecraft/OpSys.h
|
||||||
|
logic/minecraft/ParseUtils.cpp
|
||||||
|
logic/minecraft/ParseUtils.h
|
||||||
logic/minecraft/RawLibrary.cpp
|
logic/minecraft/RawLibrary.cpp
|
||||||
logic/minecraft/RawLibrary.h
|
logic/minecraft/RawLibrary.h
|
||||||
logic/minecraft/VersionBuilder.cpp
|
logic/minecraft/VersionBuilder.cpp
|
||||||
@ -489,10 +491,6 @@ SET(MULTIMC_SOURCES
|
|||||||
logic/minecraft/VersionFinal.h
|
logic/minecraft/VersionFinal.h
|
||||||
logic/minecraft/VersionPatch.h
|
logic/minecraft/VersionPatch.h
|
||||||
|
|
||||||
# Trivial operating system utilities
|
|
||||||
logic/minecraft/OpSys.h
|
|
||||||
logic/minecraft/OpSys.cpp
|
|
||||||
|
|
||||||
# Various base classes
|
# Various base classes
|
||||||
logic/BaseInstaller.h
|
logic/BaseInstaller.h
|
||||||
logic/BaseInstaller.cpp
|
logic/BaseInstaller.cpp
|
||||||
|
@ -24,6 +24,7 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.applet.Applet;
|
import java.applet.Applet;
|
||||||
import java.applet.AppletStub;
|
import java.applet.AppletStub;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
public class Launcher extends Applet implements AppletStub
|
public class Launcher extends Applet implements AppletStub
|
||||||
{
|
{
|
||||||
@ -130,13 +131,23 @@ public class Launcher extends Applet implements AppletStub
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getCodeBase() {
|
public URL getCodeBase() {
|
||||||
return wrappedApplet.getCodeBase();
|
try {
|
||||||
|
return new URL("http://www.minecraft.net/game/");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getDocumentBase()
|
public URL getDocumentBase()
|
||||||
{
|
{
|
||||||
return documentBase;
|
try {
|
||||||
|
return new URL("http://www.minecraft.net/game/");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +53,7 @@ public class OneSixLauncher implements Launcher
|
|||||||
{
|
{
|
||||||
libraries = params.all("cp");
|
libraries = params.all("cp");
|
||||||
extlibs = params.all("ext");
|
extlibs = params.all("ext");
|
||||||
mcparams = params.all("param");
|
mcparams = params.allSafe("param", new ArrayList<String>() );
|
||||||
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
mainClass = params.firstSafe("mainClass", "net.minecraft.client.Minecraft");
|
||||||
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
appletClass = params.firstSafe("appletClass", "net.minecraft.client.MinecraftApplet");
|
||||||
mods = params.allSafe("mods", new ArrayList<String>());
|
mods = params.allSafe("mods", new ArrayList<String>());
|
||||||
|
@ -47,7 +47,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent)
|
|||||||
taskDlg->exec(loadTask);
|
taskDlg->exec(loadTask);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
setSelectedVersion(MMC->minecraftlist()->getLatestStable());
|
setSelectedVersion(MMC->minecraftlist()->getLatestStable(), true);
|
||||||
InstIconKey = "infinity";
|
InstIconKey = "infinity";
|
||||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||||
}
|
}
|
||||||
@ -63,13 +63,17 @@ void NewInstanceDialog::updateDialogState()
|
|||||||
->setEnabled(!instName().isEmpty() && m_selectedVersion);
|
->setEnabled(!instName().isEmpty() && m_selectedVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version)
|
void NewInstanceDialog::setSelectedVersion(BaseVersionPtr version, bool initial)
|
||||||
{
|
{
|
||||||
m_selectedVersion = version;
|
m_selectedVersion = version;
|
||||||
|
|
||||||
if (m_selectedVersion)
|
if (m_selectedVersion)
|
||||||
{
|
{
|
||||||
ui->versionTextBox->setText(version->name());
|
ui->versionTextBox->setText(version->name());
|
||||||
|
if(ui->instNameTextBox->text().isEmpty() && !initial)
|
||||||
|
{
|
||||||
|
ui->instNameTextBox->setText(version->name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
void updateDialogState();
|
void updateDialogState();
|
||||||
|
|
||||||
void setSelectedVersion(BaseVersionPtr version);
|
void setSelectedVersion(BaseVersionPtr version, bool initial = false);
|
||||||
|
|
||||||
void loadVersionList();
|
void loadVersionList();
|
||||||
|
|
||||||
|
@ -224,7 +224,10 @@ bool OneSixInstance::prepareForLaunch(AuthSessionPtr account, QString &launchScr
|
|||||||
}
|
}
|
||||||
launchScript += "cp " + versionsPath().absoluteFilePath(minecraftjarpath) + "\n";
|
launchScript += "cp " + versionsPath().absoluteFilePath(minecraftjarpath) + "\n";
|
||||||
}
|
}
|
||||||
launchScript += "mainClass " + version->mainClass + "\n";
|
if(!version->mainClass.isEmpty())
|
||||||
|
{
|
||||||
|
launchScript += "mainClass " + version->mainClass + "\n";
|
||||||
|
}
|
||||||
if(!version->appletClass.isEmpty())
|
if(!version->appletClass.isEmpty())
|
||||||
{
|
{
|
||||||
launchScript += "appletClass " + version->appletClass + "\n";
|
launchScript += "appletClass " + version->appletClass + "\n";
|
||||||
|
@ -62,12 +62,14 @@ void OneSixUpdate::executeTask()
|
|||||||
emitFailed(tr("The specified Minecraft version is invalid. Choose a different one."));
|
emitFailed(tr("The specified Minecraft version is invalid. Choose a different one."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
versionFileStart();
|
// builtins need no updates, so only update for Mojang
|
||||||
}
|
if(targetVersion->m_versionSource == MinecraftVersion::Mojang)
|
||||||
else
|
{
|
||||||
{
|
versionFileStart();
|
||||||
jarlibStart();
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
jarlibStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneSixUpdate::versionFileStart()
|
void OneSixUpdate::versionFileStart()
|
||||||
|
@ -1,2 +1,95 @@
|
|||||||
#include "MinecraftVersion.h"
|
#include "MinecraftVersion.h"
|
||||||
|
#include "VersionFinal.h"
|
||||||
|
|
||||||
|
bool MinecraftVersion::usesLegacyLauncher()
|
||||||
|
{
|
||||||
|
return m_traits.contains("legacyLaunch") || m_traits.contains("aplhaLaunch");
|
||||||
|
}
|
||||||
|
QString MinecraftVersion::descriptor()
|
||||||
|
{
|
||||||
|
return m_descriptor;
|
||||||
|
}
|
||||||
|
QString MinecraftVersion::name()
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
QString MinecraftVersion::typeString() const
|
||||||
|
{
|
||||||
|
if (is_latest && is_snapshot)
|
||||||
|
{
|
||||||
|
return QObject::tr("Latest snapshot");
|
||||||
|
}
|
||||||
|
else if (is_latest)
|
||||||
|
{
|
||||||
|
return QObject::tr("Latest release");
|
||||||
|
}
|
||||||
|
else if (is_snapshot)
|
||||||
|
{
|
||||||
|
return QObject::tr("Snapshot");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QObject::tr("Regular release");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool MinecraftVersion::hasJarMods()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool MinecraftVersion::isVanilla()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinecraftVersion::applyTo(VersionFinal *version)
|
||||||
|
{
|
||||||
|
// FIXME: make this work.
|
||||||
|
if(m_versionSource != Builtin)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_descriptor.isNull())
|
||||||
|
{
|
||||||
|
version->id = m_descriptor;
|
||||||
|
}
|
||||||
|
if (!m_mainClass.isNull())
|
||||||
|
{
|
||||||
|
version->mainClass = m_mainClass;
|
||||||
|
}
|
||||||
|
if (!m_appletClass.isNull())
|
||||||
|
{
|
||||||
|
version->appletClass = m_appletClass;
|
||||||
|
}
|
||||||
|
if (!m_processArguments.isNull())
|
||||||
|
{
|
||||||
|
version->vanillaProcessArguments = m_processArguments;
|
||||||
|
version->processArguments = m_processArguments;
|
||||||
|
}
|
||||||
|
if (!m_type.isNull())
|
||||||
|
{
|
||||||
|
version->type = m_type;
|
||||||
|
}
|
||||||
|
if (!m_releaseTimeString.isNull())
|
||||||
|
{
|
||||||
|
version->m_releaseTimeString = m_releaseTimeString;
|
||||||
|
version->m_releaseTime = m_releaseTime;
|
||||||
|
}
|
||||||
|
if (!m_updateTimeString.isNull())
|
||||||
|
{
|
||||||
|
version->m_updateTimeString = m_updateTimeString;
|
||||||
|
version->m_updateTime = m_updateTime;
|
||||||
|
}
|
||||||
|
version->traits.unite(m_traits);
|
||||||
|
}
|
||||||
|
int MinecraftVersion::getOrder()
|
||||||
|
{
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
void MinecraftVersion::setOrder(int order)
|
||||||
|
{
|
||||||
|
this->order = order;
|
||||||
|
}
|
||||||
|
QList<JarmodPtr> MinecraftVersion::getJarMods()
|
||||||
|
{
|
||||||
|
return QList<JarmodPtr>();
|
||||||
|
}
|
||||||
|
@ -15,16 +15,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "logic/BaseVersion.h"
|
|
||||||
#include "VersionPatch.h"
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "logic/BaseVersion.h"
|
||||||
|
#include "VersionPatch.h"
|
||||||
|
#include "VersionFile.h"
|
||||||
|
|
||||||
|
class VersionFinal;
|
||||||
|
|
||||||
struct MinecraftVersion : public BaseVersion, public VersionPatch
|
struct MinecraftVersion : public BaseVersion, public VersionPatch
|
||||||
{
|
{
|
||||||
/// The version's timestamp - this is primarily used for sorting versions in a list.
|
|
||||||
qint64 timestamp;
|
|
||||||
|
|
||||||
/// The URL that this version will be downloaded from. maybe.
|
/// The URL that this version will be downloaded from. maybe.
|
||||||
QString download_url;
|
QString download_url;
|
||||||
|
|
||||||
@ -34,16 +36,20 @@ struct MinecraftVersion : public BaseVersion, public VersionPatch
|
|||||||
/// is this a snapshot?
|
/// is this a snapshot?
|
||||||
bool is_snapshot = false;
|
bool is_snapshot = false;
|
||||||
|
|
||||||
/// is this a built-in version that comes with MultiMC?
|
/// where is this from?
|
||||||
bool is_builtin = false;
|
enum VersionSource
|
||||||
|
{
|
||||||
|
Builtin,
|
||||||
|
Mojang
|
||||||
|
} m_versionSource = Builtin;
|
||||||
|
|
||||||
/// the human readable version name
|
/// the human readable version name
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
|
||||||
/// the version ID.
|
/// the version ID.
|
||||||
QString m_descriptor;
|
QString m_descriptor;
|
||||||
|
|
||||||
/// version traits. generally launcher business...
|
/// version traits. added by MultiMC
|
||||||
QSet<QString> m_traits;
|
QSet<QString> m_traits;
|
||||||
|
|
||||||
/// The main class this version uses (if any, can be empty).
|
/// The main class this version uses (if any, can be empty).
|
||||||
@ -52,57 +58,47 @@ struct MinecraftVersion : public BaseVersion, public VersionPatch
|
|||||||
/// The applet class this version uses (if any, can be empty).
|
/// The applet class this version uses (if any, can be empty).
|
||||||
QString m_appletClass;
|
QString m_appletClass;
|
||||||
|
|
||||||
bool usesLegacyLauncher()
|
/// The process arguments used by this version
|
||||||
|
QString m_processArguments;
|
||||||
|
|
||||||
|
/// The type of this release
|
||||||
|
QString m_type;
|
||||||
|
|
||||||
|
/// the time this version was actually released by Mojang, as string and as QDateTime
|
||||||
|
QString m_releaseTimeString;
|
||||||
|
QDateTime m_releaseTime;
|
||||||
|
|
||||||
|
/// the time this version was last updated by Mojang, as string and as QDateTime
|
||||||
|
QString m_updateTimeString;
|
||||||
|
QDateTime m_updateTime;
|
||||||
|
|
||||||
|
/// order of this file... default = -2
|
||||||
|
int order = -2;
|
||||||
|
|
||||||
|
bool usesLegacyLauncher();
|
||||||
|
virtual QString descriptor() override;
|
||||||
|
virtual QString name() override;
|
||||||
|
virtual QString typeString() const override;
|
||||||
|
virtual bool hasJarMods() override;
|
||||||
|
virtual bool isVanilla() override;
|
||||||
|
virtual void applyTo(VersionFinal *version) override;
|
||||||
|
virtual int getOrder();
|
||||||
|
virtual void setOrder(int order);
|
||||||
|
virtual QList<JarmodPtr> getJarMods() override;
|
||||||
|
virtual QString getPatchID()
|
||||||
{
|
{
|
||||||
return m_traits.contains("legacyLaunch") || m_traits.contains("aplhaLaunch");
|
return "net.minecraft";
|
||||||
}
|
}
|
||||||
|
virtual QString getPatchVersion()
|
||||||
virtual QString descriptor() override
|
|
||||||
{
|
{
|
||||||
return m_descriptor;
|
return m_descriptor;
|
||||||
}
|
}
|
||||||
|
virtual QString getPatchName()
|
||||||
virtual QString name() override
|
|
||||||
{
|
{
|
||||||
return m_name;
|
return "Minecraft";
|
||||||
}
|
}
|
||||||
|
virtual QString getPatchFilename()
|
||||||
virtual QString typeString() const override
|
|
||||||
{
|
{
|
||||||
if (is_latest && is_snapshot)
|
return QString();
|
||||||
{
|
};
|
||||||
return QObject::tr("Latest snapshot");
|
|
||||||
}
|
|
||||||
else if(is_latest)
|
|
||||||
{
|
|
||||||
return QObject::tr("Latest release");
|
|
||||||
}
|
|
||||||
else if(is_snapshot)
|
|
||||||
{
|
|
||||||
return QObject::tr("Snapshot");
|
|
||||||
}
|
|
||||||
else if(is_builtin)
|
|
||||||
{
|
|
||||||
return QObject::tr("Museum piece");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return QObject::tr("Regular release");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool hasJarMods() override
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool isVanilla() override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void applyTo(VersionFinal *version)
|
|
||||||
{
|
|
||||||
// umm... what now?
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
#include "MinecraftVersionList.h"
|
#include "MinecraftVersionList.h"
|
||||||
#include "MultiMC.h"
|
#include "MultiMC.h"
|
||||||
#include "logic/net/URLConstants.h"
|
#include "logic/net/URLConstants.h"
|
||||||
#include <logic/MMCJson.h>
|
#include "logic/MMCJson.h"
|
||||||
|
#include "ParseUtils.h"
|
||||||
|
|
||||||
#include <QtXml>
|
#include <QtXml>
|
||||||
|
|
||||||
@ -30,11 +31,6 @@
|
|||||||
|
|
||||||
#include <QtNetwork>
|
#include <QtNetwork>
|
||||||
|
|
||||||
inline QDateTime timeFromS3Time(QString str)
|
|
||||||
{
|
|
||||||
return QDateTime::fromString(str, Qt::ISODate);
|
|
||||||
}
|
|
||||||
|
|
||||||
MinecraftVersionList::MinecraftVersionList(QObject *parent) : BaseVersionList(parent)
|
MinecraftVersionList::MinecraftVersionList(QObject *parent) : BaseVersionList(parent)
|
||||||
{
|
{
|
||||||
loadBuiltinList();
|
loadBuiltinList();
|
||||||
@ -64,7 +60,7 @@ static bool cmpVersions(BaseVersionPtr first, BaseVersionPtr second)
|
|||||||
{
|
{
|
||||||
auto left = std::dynamic_pointer_cast<MinecraftVersion>(first);
|
auto left = std::dynamic_pointer_cast<MinecraftVersion>(first);
|
||||||
auto right = std::dynamic_pointer_cast<MinecraftVersion>(second);
|
auto right = std::dynamic_pointer_cast<MinecraftVersion>(second);
|
||||||
return left->timestamp > right->timestamp;
|
return left->m_releaseTime > right->m_releaseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MinecraftVersionList::sortInternal()
|
void MinecraftVersionList::sortInternal()
|
||||||
@ -79,55 +75,55 @@ void MinecraftVersionList::loadBuiltinList()
|
|||||||
QFile filez(versionList.absoluteFilePath());
|
QFile filez(versionList.absoluteFilePath());
|
||||||
filez.open(QIODevice::ReadOnly);
|
filez.open(QIODevice::ReadOnly);
|
||||||
auto data = filez.readAll();
|
auto data = filez.readAll();
|
||||||
|
|
||||||
// parse the data as json
|
// parse the data as json
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);
|
||||||
QJsonObject root = jsonDoc.object();
|
QJsonObject root = jsonDoc.object();
|
||||||
|
|
||||||
// parse all the versions
|
// parse all the versions
|
||||||
for (const auto version : MMCJson::ensureArray(root.value("versions")))
|
for (const auto version : MMCJson::ensureArray(root.value("versions")))
|
||||||
{
|
{
|
||||||
QJsonObject versionObj = version.toObject();
|
QJsonObject versionObj = version.toObject();
|
||||||
QString versionID = versionObj.value("id").toString("");
|
QString versionID = versionObj.value("id").toString("");
|
||||||
QString versionTimeStr = versionObj.value("releaseTime").toString("");
|
|
||||||
QString versionTypeStr = versionObj.value("type").toString("");
|
QString versionTypeStr = versionObj.value("type").toString("");
|
||||||
QSet<QString> traits;
|
if (versionID.isEmpty() || versionTypeStr.isEmpty())
|
||||||
if (versionObj.contains("+traits"))
|
|
||||||
{
|
{
|
||||||
for (auto traitVal : MMCJson::ensureArray(versionObj.value("+traits")))
|
QLOG_ERROR() << "Parsed version is missing ID or type";
|
||||||
{
|
|
||||||
traits.insert(MMCJson::ensureString(traitVal));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty())
|
|
||||||
{
|
|
||||||
// FIXME: log this somewhere
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Parse the timestamp.
|
|
||||||
QDateTime versionTime = timeFromS3Time(versionTimeStr);
|
|
||||||
if (!versionTime.isValid())
|
|
||||||
{
|
|
||||||
// FIXME: log this somewhere
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Get the download URL.
|
|
||||||
QString dlUrl = "http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
|
|
||||||
|
|
||||||
// main class and applet class
|
|
||||||
QString mainClass = versionObj.value("type").toString("");
|
|
||||||
QString appletClass = versionObj.value("type").toString("");
|
|
||||||
|
|
||||||
// Now, we construct the version object and add it to the list.
|
// Now, we construct the version object and add it to the list.
|
||||||
std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
|
std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
|
||||||
mcVersion->m_name = mcVersion->m_descriptor = versionID;
|
mcVersion->m_name = mcVersion->m_descriptor = versionID;
|
||||||
mcVersion->timestamp = versionTime.toMSecsSinceEpoch();
|
|
||||||
mcVersion->download_url = dlUrl;
|
// Parse the timestamp.
|
||||||
mcVersion->is_builtin = true;
|
try
|
||||||
mcVersion->m_appletClass = appletClass;
|
{
|
||||||
mcVersion->m_mainClass = mainClass;
|
parse_timestamp(versionObj.value("releaseTime").toString(""),
|
||||||
mcVersion->m_traits = traits;
|
mcVersion->m_releaseTimeString, mcVersion->m_releaseTime);
|
||||||
|
}
|
||||||
|
catch (MMCError &e)
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Error while parsing version" << versionID << ":" << e.cause();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the download URL.
|
||||||
|
mcVersion->download_url =
|
||||||
|
"http://" + URLConstants::AWS_DOWNLOAD_VERSIONS + versionID + "/";
|
||||||
|
|
||||||
|
mcVersion->m_versionSource = MinecraftVersion::Builtin;
|
||||||
|
mcVersion->m_appletClass = versionObj.value("appletClass").toString("");
|
||||||
|
mcVersion->m_mainClass = versionObj.value("mainClass").toString("");
|
||||||
|
mcVersion->m_processArguments = versionObj.value("processArguments").toString("legacy");
|
||||||
|
if (versionObj.contains("+traits"))
|
||||||
|
{
|
||||||
|
for (auto traitVal : MMCJson::ensureArray(versionObj.value("+traits")))
|
||||||
|
{
|
||||||
|
mcVersion->m_traits.insert(MMCJson::ensureString(traitVal));
|
||||||
|
}
|
||||||
|
}
|
||||||
m_vlist.append(mcVersion);
|
m_vlist.append(mcVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,50 +261,14 @@ void MCVListLoadTask::list_downloaded()
|
|||||||
// Load the version info.
|
// Load the version info.
|
||||||
if (!version.isObject())
|
if (!version.isObject())
|
||||||
{
|
{
|
||||||
// FIXME: log this somewhere
|
QLOG_ERROR() << "Error while parsing version list : invalid JSON structure";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QJsonObject versionObj = version.toObject();
|
QJsonObject versionObj = version.toObject();
|
||||||
QString versionID = versionObj.value("id").toString("");
|
QString versionID = versionObj.value("id").toString("");
|
||||||
QString versionTimeStr = versionObj.value("releaseTime").toString("");
|
if (versionID.isEmpty())
|
||||||
QString versionTypeStr = versionObj.value("type").toString("");
|
|
||||||
if (versionID.isEmpty() || versionTimeStr.isEmpty() || versionTypeStr.isEmpty())
|
|
||||||
{
|
{
|
||||||
// FIXME: log this somewhere
|
QLOG_ERROR() << "Error while parsing version : version ID is missing";
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the timestamp.
|
|
||||||
QDateTime versionTime = timeFromS3Time(versionTimeStr);
|
|
||||||
if (!versionTime.isValid())
|
|
||||||
{
|
|
||||||
// FIXME: log this somewhere
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// OneSix or Legacy. use filter to determine type
|
|
||||||
if (versionTypeStr == "release")
|
|
||||||
{
|
|
||||||
is_latest = (versionID == latestReleaseID);
|
|
||||||
is_snapshot = false;
|
|
||||||
}
|
|
||||||
else if (versionTypeStr == "snapshot") // It's a snapshot... yay
|
|
||||||
{
|
|
||||||
is_latest = (versionID == latestSnapshotID);
|
|
||||||
is_snapshot = true;
|
|
||||||
}
|
|
||||||
else if (versionTypeStr == "old_alpha")
|
|
||||||
{
|
|
||||||
is_latest = false;
|
|
||||||
is_snapshot = false;
|
|
||||||
}
|
|
||||||
else if (versionTypeStr == "old_beta")
|
|
||||||
{
|
|
||||||
is_latest = false;
|
|
||||||
is_snapshot = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// FIXME: log this somewhere
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get the download URL.
|
// Get the download URL.
|
||||||
@ -317,10 +277,61 @@ void MCVListLoadTask::list_downloaded()
|
|||||||
// Now, we construct the version object and add it to the list.
|
// Now, we construct the version object and add it to the list.
|
||||||
std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
|
std::shared_ptr<MinecraftVersion> mcVersion(new MinecraftVersion());
|
||||||
mcVersion->m_name = mcVersion->m_descriptor = versionID;
|
mcVersion->m_name = mcVersion->m_descriptor = versionID;
|
||||||
mcVersion->timestamp = versionTime.toMSecsSinceEpoch();
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse the timestamps.
|
||||||
|
parse_timestamp(versionObj.value("releaseTime").toString(""),
|
||||||
|
mcVersion->m_releaseTimeString, mcVersion->m_releaseTime);
|
||||||
|
|
||||||
|
parse_timestamp(versionObj.value("time").toString(""),
|
||||||
|
mcVersion->m_updateTimeString, mcVersion->m_updateTime);
|
||||||
|
}
|
||||||
|
catch (MMCError &e)
|
||||||
|
{
|
||||||
|
QLOG_ERROR() << "Error while parsing version" << versionID << ":" << e.cause();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcVersion->m_versionSource = MinecraftVersion::Builtin;
|
||||||
mcVersion->download_url = dlUrl;
|
mcVersion->download_url = dlUrl;
|
||||||
mcVersion->is_latest = is_latest;
|
{
|
||||||
mcVersion->is_snapshot = is_snapshot;
|
QString versionTypeStr = versionObj.value("type").toString("");
|
||||||
|
if (versionTypeStr.isEmpty())
|
||||||
|
{
|
||||||
|
// FIXME: log this somewhere
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// OneSix or Legacy. use filter to determine type
|
||||||
|
if (versionTypeStr == "release")
|
||||||
|
{
|
||||||
|
is_latest = (versionID == latestReleaseID);
|
||||||
|
is_snapshot = false;
|
||||||
|
}
|
||||||
|
else if (versionTypeStr == "snapshot") // It's a snapshot... yay
|
||||||
|
{
|
||||||
|
is_latest = (versionID == latestSnapshotID);
|
||||||
|
is_snapshot = true;
|
||||||
|
}
|
||||||
|
else if (versionTypeStr == "old_alpha")
|
||||||
|
{
|
||||||
|
is_latest = false;
|
||||||
|
is_snapshot = false;
|
||||||
|
}
|
||||||
|
else if (versionTypeStr == "old_beta")
|
||||||
|
{
|
||||||
|
is_latest = false;
|
||||||
|
is_snapshot = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: log this somewhere
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mcVersion->m_type = versionTypeStr;
|
||||||
|
mcVersion->is_latest = is_latest;
|
||||||
|
mcVersion->is_snapshot = is_snapshot;
|
||||||
|
}
|
||||||
tempList.append(mcVersion);
|
tempList.append(mcVersion);
|
||||||
}
|
}
|
||||||
m_list->updateListData(tempList);
|
m_list->updateListData(tempList);
|
||||||
|
23
logic/minecraft/ParseUtils.cpp
Normal file
23
logic/minecraft/ParseUtils.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <QDateTime>
|
||||||
|
#include <QString>
|
||||||
|
#include "ParseUtils.h"
|
||||||
|
#include <logic/MMCJson.h>
|
||||||
|
|
||||||
|
QDateTime timeFromS3Time(QString str)
|
||||||
|
{
|
||||||
|
return QDateTime::fromString(str, Qt::ISODate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_timestamp (const QString & raw, QString & save_here, QDateTime & parse_here)
|
||||||
|
{
|
||||||
|
save_here = raw;
|
||||||
|
if (save_here.isEmpty())
|
||||||
|
{
|
||||||
|
throw JSONValidationError("The timestamp is empty!");
|
||||||
|
}
|
||||||
|
parse_here = timeFromS3Time(save_here);
|
||||||
|
if (!parse_here.isValid())
|
||||||
|
{
|
||||||
|
throw JSONValidationError("The timestamp not a valid timestamp!");
|
||||||
|
}
|
||||||
|
}
|
14
logic/minecraft/ParseUtils.h
Normal file
14
logic/minecraft/ParseUtils.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse the S3 timestamp in 'raw' and fill the forwarded variables.
|
||||||
|
* return true/false for success/failure
|
||||||
|
*/
|
||||||
|
void parse_timestamp (const QString &raw, QString &save_here, QDateTime &parse_here);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* take the timestamp used by S3 and turn it into QDateTime
|
||||||
|
*/
|
||||||
|
QDateTime timeFromS3Time(QString str);
|
58
logic/minecraft/VersionBuildError.h
Normal file
58
logic/minecraft/VersionBuildError.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "MMCError.h"
|
||||||
|
|
||||||
|
class VersionBuildError : public MMCError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VersionBuildError(QString cause) : MMCError(cause) {};
|
||||||
|
virtual ~VersionBuildError() noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the base version file was meant for a newer version of the vanilla launcher than we support
|
||||||
|
*/
|
||||||
|
class LauncherVersionError : public VersionBuildError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LauncherVersionError(int actual, int supported)
|
||||||
|
: VersionBuildError(QObject::tr(
|
||||||
|
"The base version file of this instance was meant for a newer (%1) "
|
||||||
|
"version of the vanilla launcher than this version of MultiMC supports (%2).")
|
||||||
|
.arg(actual)
|
||||||
|
.arg(supported)) {};
|
||||||
|
virtual ~LauncherVersionError() noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* some patch was intended for a different version of minecraft
|
||||||
|
*/
|
||||||
|
class MinecraftVersionMismatch : public VersionBuildError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MinecraftVersionMismatch(QString fileId, QString mcVersion, QString parentMcVersion)
|
||||||
|
: VersionBuildError(QObject::tr("The patch %1 is for a different version of Minecraft "
|
||||||
|
"(%2) than that of the instance (%3).")
|
||||||
|
.arg(fileId)
|
||||||
|
.arg(mcVersion)
|
||||||
|
.arg(parentMcVersion)) {};
|
||||||
|
virtual ~MinecraftVersionMismatch() noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* files required for the version are not (yet?) present
|
||||||
|
*/
|
||||||
|
class VersionIncomplete : public VersionBuildError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VersionIncomplete(QString missingPatch)
|
||||||
|
: VersionBuildError(QObject::tr("Version is incomplete: missing %1.")
|
||||||
|
.arg(missingPatch)) {};
|
||||||
|
virtual ~VersionIncomplete() noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
@ -23,12 +23,17 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <qresource.h>
|
||||||
#include <modutils.h>
|
#include <modutils.h>
|
||||||
|
|
||||||
|
#include "MultiMC.h"
|
||||||
#include "logic/minecraft/VersionBuilder.h"
|
#include "logic/minecraft/VersionBuilder.h"
|
||||||
#include "logic/minecraft/VersionFinal.h"
|
#include "logic/minecraft/VersionFinal.h"
|
||||||
#include "logic/minecraft/OneSixRule.h"
|
#include "logic/minecraft/OneSixRule.h"
|
||||||
|
#include "logic/minecraft/VersionPatch.h"
|
||||||
#include "logic/minecraft/VersionFile.h"
|
#include "logic/minecraft/VersionFile.h"
|
||||||
|
#include "VersionBuildError.h"
|
||||||
|
#include "MinecraftVersionList.h"
|
||||||
|
|
||||||
#include "logic/OneSixInstance.h"
|
#include "logic/OneSixInstance.h"
|
||||||
#include "logic/MMCJson.h"
|
#include "logic/MMCJson.h"
|
||||||
@ -39,16 +44,17 @@ VersionBuilder::VersionBuilder()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance, const QStringList &external)
|
void VersionBuilder::build(VersionFinal *version, OneSixInstance *instance,
|
||||||
|
const QStringList &external)
|
||||||
{
|
{
|
||||||
VersionBuilder builder;
|
VersionBuilder builder;
|
||||||
builder.m_version = version;
|
builder.m_version = version;
|
||||||
builder.m_instance = instance;
|
builder.m_instance = instance;
|
||||||
builder.buildInternal(external);
|
builder.external_patches = external;
|
||||||
|
builder.buildInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
|
void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version, const QJsonObject &obj)
|
||||||
const QJsonObject &obj)
|
|
||||||
{
|
{
|
||||||
VersionBuilder builder;
|
VersionBuilder builder;
|
||||||
builder.m_version = version;
|
builder.m_version = version;
|
||||||
@ -56,88 +62,143 @@ void VersionBuilder::readJsonAndApplyToVersion(VersionFinal *version,
|
|||||||
builder.readJsonAndApply(obj);
|
builder.readJsonAndApply(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionBuilder::buildInternal(const QStringList &external)
|
void VersionBuilder::buildFromCustomJson()
|
||||||
{
|
{
|
||||||
m_version->versionFiles.clear();
|
QLOG_INFO() << "Building version from custom.json within the instance.";
|
||||||
|
QLOG_INFO() << "Reading custom.json";
|
||||||
|
auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("custom.json")), false);
|
||||||
|
file->name = "custom.json";
|
||||||
|
file->filename = "custom.json";
|
||||||
|
file->fileId = "org.multimc.custom.json";
|
||||||
|
file->order = -1;
|
||||||
|
file->version = QString();
|
||||||
|
m_version->VersionPatches.append(file);
|
||||||
|
// QObject::tr("The version descriptors of this instance are not compatible with the
|
||||||
|
// current version of MultiMC"));
|
||||||
|
// QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.")
|
||||||
|
// some final touches
|
||||||
|
m_version->finalize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QDir root(m_instance->instanceRoot());
|
void VersionBuilder::buildFromVersionJson()
|
||||||
QDir patches(root.absoluteFilePath("patches/"));
|
{
|
||||||
|
QLOG_INFO() << "Building version from version.json and patches within the instance.";
|
||||||
|
QLOG_INFO() << "Reading version.json";
|
||||||
|
auto file = parseJsonFile(QFileInfo(instance_root.absoluteFilePath("version.json")), false);
|
||||||
|
file->name = "Minecraft";
|
||||||
|
file->fileId = "org.multimc.version.json";
|
||||||
|
file->order = -1;
|
||||||
|
file->version = m_instance->intendedVersionId();
|
||||||
|
file->mcVersion = m_instance->intendedVersionId();
|
||||||
|
m_version->VersionPatches.append(file);
|
||||||
|
|
||||||
// if we do external files, do just those.
|
// load all patches, put into map for ordering, apply in the right order
|
||||||
if (!external.isEmpty())
|
readInstancePatches();
|
||||||
{
|
|
||||||
int externalOrder = -1;
|
|
||||||
for (auto fileName : external)
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Reading" << fileName;
|
|
||||||
auto file =
|
|
||||||
parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
|
|
||||||
file->name = QFileInfo(fileName).fileName();
|
|
||||||
file->fileId = "org.multimc.external." + file->name;
|
|
||||||
file->order = (externalOrder += 1);
|
|
||||||
file->version = QString();
|
|
||||||
file->mcVersion = QString();
|
|
||||||
m_version->versionFiles.append(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// else, if there's custom json, we just do that.
|
|
||||||
else if (QFile::exists(root.absoluteFilePath("custom.json")))
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Reading custom.json";
|
|
||||||
auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("custom.json")), false);
|
|
||||||
file->name = "custom.json";
|
|
||||||
file->filename = "custom.json";
|
|
||||||
file->fileId = "org.multimc.custom.json";
|
|
||||||
file->order = -1;
|
|
||||||
file->version = QString();
|
|
||||||
m_version->versionFiles.append(file);
|
|
||||||
// QObject::tr("The version descriptors of this instance are not compatible with the
|
|
||||||
// current version of MultiMC"));
|
|
||||||
// QObject::tr("Error while applying %1. Please check MultiMC-0.log for more info.")
|
|
||||||
}
|
|
||||||
// version.json -> patches/*.json -> user.json
|
|
||||||
else
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// version.json
|
|
||||||
QLOG_INFO() << "Reading version.json";
|
|
||||||
auto file = parseJsonFile(QFileInfo(root.absoluteFilePath("version.json")), false);
|
|
||||||
file->name = "Minecraft";
|
|
||||||
file->fileId = "org.multimc.version.json";
|
|
||||||
file->order = -1;
|
|
||||||
file->version = m_instance->intendedVersionId();
|
|
||||||
file->mcVersion = m_instance->intendedVersionId();
|
|
||||||
m_version->versionFiles.append(file);
|
|
||||||
// QObject::tr("Error while applying %1. Please check MultiMC-0.log for more
|
|
||||||
// info.").arg(root.absoluteFilePath("version.json")));
|
|
||||||
|
|
||||||
// patches/
|
|
||||||
// load all, put into map for ordering, apply in the right order
|
|
||||||
|
|
||||||
QMap<int, QPair<QString, VersionFilePtr>> files;
|
|
||||||
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
|
||||||
{
|
|
||||||
QLOG_INFO() << "Reading" << info.fileName();
|
|
||||||
auto file = parseJsonFile(info, true);
|
|
||||||
if (files.contains(file->order))
|
|
||||||
{
|
|
||||||
throw VersionBuildError(QObject::tr("%1 has the same order as %2").arg(
|
|
||||||
file->fileId, files[file->order].second->fileId));
|
|
||||||
}
|
|
||||||
files.insert(file->order, qMakePair(info.fileName(), file));
|
|
||||||
}
|
|
||||||
for (auto order : files.keys())
|
|
||||||
{
|
|
||||||
auto &filePair = files[order];
|
|
||||||
m_version->versionFiles.append(filePair.second);
|
|
||||||
}
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
// some final touches
|
// some final touches
|
||||||
m_version->finalize();
|
m_version->finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VersionBuilder::readInstancePatches()
|
||||||
|
{
|
||||||
|
QDir patches(instance_root.absoluteFilePath("patches/"));
|
||||||
|
QMap<int, QPair<QString, VersionFilePtr>> files;
|
||||||
|
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Reading" << info.fileName();
|
||||||
|
auto file = parseJsonFile(info, true);
|
||||||
|
if(file->fileId == "net.minecraft")
|
||||||
|
continue;
|
||||||
|
if(file->fileId == "org.lwjgl")
|
||||||
|
continue;
|
||||||
|
if (files.contains(file->order))
|
||||||
|
{
|
||||||
|
throw VersionBuildError(QObject::tr("%1 has the same order as %2")
|
||||||
|
.arg(file->fileId, files[file->order].second->fileId));
|
||||||
|
}
|
||||||
|
files.insert(file->order, qMakePair(info.fileName(), file));
|
||||||
|
}
|
||||||
|
for (auto order : files.keys())
|
||||||
|
{
|
||||||
|
auto &filePair = files[order];
|
||||||
|
m_version->VersionPatches.append(filePair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionBuilder::buildFromExternalPatches()
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Building version from external files.";
|
||||||
|
int externalOrder = -1;
|
||||||
|
for (auto fileName : external_patches)
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Reading" << fileName;
|
||||||
|
auto file = parseJsonFile(QFileInfo(fileName), false, fileName.endsWith("pack.json"));
|
||||||
|
file->name = QFileInfo(fileName).fileName();
|
||||||
|
file->fileId = "org.multimc.external." + file->name;
|
||||||
|
file->order = (externalOrder += 1);
|
||||||
|
file->version = QString();
|
||||||
|
file->mcVersion = QString();
|
||||||
|
m_version->VersionPatches.append(file);
|
||||||
|
}
|
||||||
|
// some final touches
|
||||||
|
m_version->finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionBuilder::buildFromMultilayer()
|
||||||
|
{
|
||||||
|
QLOG_INFO() << "Building version from multilayered sources.";
|
||||||
|
// just the builtin stuff for now
|
||||||
|
auto minecraftList = MMC->minecraftlist();
|
||||||
|
auto mcversion = minecraftList->findVersion(m_instance->intendedVersionId());
|
||||||
|
auto minecraftPatch = std::dynamic_pointer_cast<VersionPatch>(mcversion);
|
||||||
|
if(!minecraftPatch)
|
||||||
|
{
|
||||||
|
throw VersionIncomplete("net.minecraft");
|
||||||
|
}
|
||||||
|
minecraftPatch->setOrder(-2);
|
||||||
|
m_version->VersionPatches.append(minecraftPatch);
|
||||||
|
|
||||||
|
QResource LWJGL(":/versions/LWJGL/2.9.1.json");
|
||||||
|
auto lwjgl = parseJsonFile(LWJGL.absoluteFilePath(), false, false);
|
||||||
|
auto lwjglPatch = std::dynamic_pointer_cast<VersionPatch>(lwjgl);
|
||||||
|
if(!lwjglPatch)
|
||||||
|
{
|
||||||
|
throw VersionIncomplete("org.lwjgl");
|
||||||
|
}
|
||||||
|
lwjglPatch->setOrder(-1);
|
||||||
|
m_version->VersionPatches.append(lwjglPatch);
|
||||||
|
|
||||||
|
// load all patches, put into map for ordering, apply in the right order
|
||||||
|
readInstancePatches();
|
||||||
|
|
||||||
|
m_version->finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionBuilder::buildInternal()
|
||||||
|
{
|
||||||
|
m_version->VersionPatches.clear();
|
||||||
|
instance_root = QDir(m_instance->instanceRoot());
|
||||||
|
// if we do external files, do just those.
|
||||||
|
if (!external_patches.isEmpty())
|
||||||
|
{
|
||||||
|
buildFromExternalPatches();
|
||||||
|
}
|
||||||
|
// else, if there's custom json, we just do that.
|
||||||
|
else if (QFile::exists(instance_root.absoluteFilePath("custom.json")))
|
||||||
|
{
|
||||||
|
buildFromCustomJson();
|
||||||
|
}
|
||||||
|
// version.json -> patches/*.json
|
||||||
|
else if (QFile::exists(instance_root.absoluteFilePath("version.json")))
|
||||||
|
{
|
||||||
|
buildFromVersionJson();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buildFromMultilayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
||||||
{
|
{
|
||||||
@ -147,14 +208,14 @@ void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
|||||||
// QObject::tr("Error while reading. Please check MultiMC-0.log for more info."));
|
// QObject::tr("Error while reading. Please check MultiMC-0.log for more info."));
|
||||||
|
|
||||||
file->applyTo(m_version);
|
file->applyTo(m_version);
|
||||||
m_version->versionFiles.append(file);
|
m_version->VersionPatches.append(file);
|
||||||
// QObject::tr("Error while applying. Please check MultiMC-0.log for more info."));
|
// QObject::tr("Error while applying. Please check MultiMC-0.log for more info."));
|
||||||
// QObject::tr("The version descriptors of this instance are not compatible with the current
|
// QObject::tr("The version descriptors of this instance are not compatible with the current
|
||||||
// version of MultiMC"));
|
// version of MultiMC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo,
|
VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
|
||||||
const bool requireOrder, bool isFTB)
|
bool isFTB)
|
||||||
{
|
{
|
||||||
QFile file(fileInfo.absoluteFilePath());
|
QFile file(fileInfo.absoluteFilePath());
|
||||||
if (!file.open(QFile::ReadOnly))
|
if (!file.open(QFile::ReadOnly))
|
||||||
@ -166,9 +227,10 @@ VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo,
|
|||||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError)
|
||||||
{
|
{
|
||||||
throw JSONValidationError(QObject::tr("Unable to process the version file %1: %2 at %3.")
|
throw JSONValidationError(
|
||||||
.arg(fileInfo.fileName(), error.errorString())
|
QObject::tr("Unable to process the version file %1: %2 at %3.")
|
||||||
.arg(error.offset));
|
.arg(fileInfo.fileName(), error.errorString())
|
||||||
|
.arg(error.offset));
|
||||||
}
|
}
|
||||||
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
||||||
// QObject::tr("Error while reading %1. Please check MultiMC-0.log for more
|
// QObject::tr("Error while reading %1. Please check MultiMC-0.log for more
|
||||||
@ -226,7 +288,7 @@ QMap<QString, int> VersionBuilder::readOverrideOrders(OneSixInstance *instance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VersionBuilder::writeOverrideOrders(const QMap<QString, int> &order,
|
bool VersionBuilder::writeOverrideOrders(const QMap<QString, int> &order,
|
||||||
OneSixInstance *instance)
|
OneSixInstance *instance)
|
||||||
{
|
{
|
||||||
QJsonObject obj;
|
QJsonObject obj;
|
||||||
for (auto it = order.cbegin(); it != order.cend(); ++it)
|
for (auto it = order.cbegin(); it != order.cend(); ++it)
|
||||||
|
@ -37,8 +37,17 @@ public:
|
|||||||
private:
|
private:
|
||||||
VersionFinal *m_version;
|
VersionFinal *m_version;
|
||||||
OneSixInstance *m_instance;
|
OneSixInstance *m_instance;
|
||||||
|
QStringList external_patches;
|
||||||
void buildInternal(const QStringList& external);
|
QDir instance_root;
|
||||||
|
|
||||||
|
void buildInternal();
|
||||||
|
void buildFromExternalPatches();
|
||||||
|
void buildFromCustomJson();
|
||||||
|
void buildFromVersionJson();
|
||||||
|
void buildFromMultilayer();
|
||||||
|
|
||||||
|
void readInstancePatches();
|
||||||
|
|
||||||
void readJsonAndApply(const QJsonObject &obj);
|
void readJsonAndApply(const QJsonObject &obj);
|
||||||
|
|
||||||
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
|
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
|
||||||
|
@ -8,10 +8,13 @@
|
|||||||
#include "logic/minecraft/OneSixLibrary.h"
|
#include "logic/minecraft/OneSixLibrary.h"
|
||||||
#include "logic/minecraft/VersionFinal.h"
|
#include "logic/minecraft/VersionFinal.h"
|
||||||
#include "logic/minecraft/JarMod.h"
|
#include "logic/minecraft/JarMod.h"
|
||||||
|
#include "ParseUtils.h"
|
||||||
|
|
||||||
#include "logic/MMCJson.h"
|
#include "logic/MMCJson.h"
|
||||||
using namespace MMCJson;
|
using namespace MMCJson;
|
||||||
|
|
||||||
|
#include "VersionBuildError.h"
|
||||||
|
|
||||||
#define CURRENT_MINIMUM_LAUNCHER_VERSION 14
|
#define CURRENT_MINIMUM_LAUNCHER_VERSION 14
|
||||||
|
|
||||||
int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
|
int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
|
||||||
@ -23,7 +26,7 @@ int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
|
|||||||
if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(chunk) != -1)
|
if (QRegExp(needle, Qt::CaseSensitive, QRegExp::WildcardUnix).indexIn(chunk) != -1)
|
||||||
{
|
{
|
||||||
// only one is allowed.
|
// only one is allowed.
|
||||||
if(retval != -1)
|
if (retval != -1)
|
||||||
return -1;
|
return -1;
|
||||||
retval = i;
|
retval = i;
|
||||||
}
|
}
|
||||||
@ -32,7 +35,7 @@ int findLibrary(QList<OneSixLibraryPtr> haystack, const QString &needle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &filename,
|
VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &filename,
|
||||||
const bool requireOrder, const bool isFTB)
|
const bool requireOrder, const bool isFTB)
|
||||||
{
|
{
|
||||||
VersionFilePtr out(new VersionFile());
|
VersionFilePtr out(new VersionFile());
|
||||||
if (doc.isEmpty() || doc.isNull())
|
if (doc.isEmpty() || doc.isNull())
|
||||||
@ -41,7 +44,6 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
|
|||||||
}
|
}
|
||||||
if (!doc.isObject())
|
if (!doc.isObject())
|
||||||
{
|
{
|
||||||
throw JSONValidationError("The root of " + filename + " is not an object");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject root = doc.object();
|
QJsonObject root = doc.object();
|
||||||
@ -65,7 +67,7 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
|
|||||||
out->mcVersion = root.value("mcVersion").toString();
|
out->mcVersion = root.value("mcVersion").toString();
|
||||||
out->filename = filename;
|
out->filename = filename;
|
||||||
|
|
||||||
auto readString = [root, filename](const QString & key, QString & variable)
|
auto readString = [root](const QString & key, QString & variable)
|
||||||
{
|
{
|
||||||
if (root.contains(key))
|
if (root.contains(key))
|
||||||
{
|
{
|
||||||
@ -73,6 +75,16 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto readStringRet = [root](const QString & key)->QString
|
||||||
|
{
|
||||||
|
if (root.contains(key))
|
||||||
|
{
|
||||||
|
return ensureString(root.value(key));
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
// FIXME: This should be ignored when applying.
|
// FIXME: This should be ignored when applying.
|
||||||
if (!isFTB)
|
if (!isFTB)
|
||||||
{
|
{
|
||||||
@ -86,8 +98,14 @@ VersionFilePtr VersionFile::fromJson(const QJsonDocument &doc, const QString &fi
|
|||||||
readString("+minecraftArguments", out->addMinecraftArguments);
|
readString("+minecraftArguments", out->addMinecraftArguments);
|
||||||
readString("-minecraftArguments", out->removeMinecraftArguments);
|
readString("-minecraftArguments", out->removeMinecraftArguments);
|
||||||
readString("type", out->type);
|
readString("type", out->type);
|
||||||
readString("releaseTime", out->versionReleaseTime);
|
if (out->isVanilla())
|
||||||
readString("time", out->versionFileUpdateTime);
|
{
|
||||||
|
parse_timestamp(readStringRet("releaseTime"), out->m_releaseTimeString,
|
||||||
|
out->m_releaseTime);
|
||||||
|
parse_timestamp(readStringRet("time"), out->m_updateTimeString, out->m_updateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
readStringRet("time");
|
||||||
readString("assets", out->assets);
|
readString("assets", out->assets);
|
||||||
|
|
||||||
if (root.contains("minimumLauncherVersion"))
|
if (root.contains("minimumLauncherVersion"))
|
||||||
@ -284,7 +302,8 @@ void VersionFile::applyTo(VersionFinal *version)
|
|||||||
{
|
{
|
||||||
if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
|
if (minimumLauncherVersion > CURRENT_MINIMUM_LAUNCHER_VERSION)
|
||||||
{
|
{
|
||||||
throw LauncherVersionError(minimumLauncherVersion, CURRENT_MINIMUM_LAUNCHER_VERSION);
|
throw LauncherVersionError(minimumLauncherVersion,
|
||||||
|
CURRENT_MINIMUM_LAUNCHER_VERSION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,23 +330,28 @@ void VersionFile::applyTo(VersionFinal *version)
|
|||||||
}
|
}
|
||||||
if (!processArguments.isNull())
|
if (!processArguments.isNull())
|
||||||
{
|
{
|
||||||
if(isVanilla())
|
if (isVanilla())
|
||||||
{
|
{
|
||||||
version->vanillaProcessArguments = processArguments;
|
version->vanillaProcessArguments = processArguments;
|
||||||
}
|
}
|
||||||
version->processArguments = processArguments;
|
version->processArguments = processArguments;
|
||||||
}
|
}
|
||||||
if (!type.isNull())
|
if(isVanilla())
|
||||||
{
|
{
|
||||||
version->type = type;
|
if (!type.isNull())
|
||||||
}
|
{
|
||||||
if (!versionReleaseTime.isNull())
|
version->type = type;
|
||||||
{
|
}
|
||||||
version->versionReleaseTime = versionReleaseTime;
|
if (!m_releaseTimeString.isNull())
|
||||||
}
|
{
|
||||||
if (!versionFileUpdateTime.isNull())
|
version->m_releaseTimeString = m_releaseTimeString;
|
||||||
{
|
version->m_releaseTime = m_releaseTime;
|
||||||
version->time = versionFileUpdateTime;
|
}
|
||||||
|
if (!m_updateTimeString.isNull())
|
||||||
|
{
|
||||||
|
version->m_updateTimeString = m_updateTimeString;
|
||||||
|
version->m_updateTime = m_updateTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!assets.isNull())
|
if (!assets.isNull())
|
||||||
{
|
{
|
||||||
@ -335,11 +359,12 @@ void VersionFile::applyTo(VersionFinal *version)
|
|||||||
}
|
}
|
||||||
if (minimumLauncherVersion >= 0)
|
if (minimumLauncherVersion >= 0)
|
||||||
{
|
{
|
||||||
version->minimumLauncherVersion = minimumLauncherVersion;
|
if(version->minimumLauncherVersion < minimumLauncherVersion)
|
||||||
|
version->minimumLauncherVersion = minimumLauncherVersion;
|
||||||
}
|
}
|
||||||
if (!overwriteMinecraftArguments.isNull())
|
if (!overwriteMinecraftArguments.isNull())
|
||||||
{
|
{
|
||||||
if(isVanilla())
|
if (isVanilla())
|
||||||
{
|
{
|
||||||
version->vanillaMinecraftArguments = overwriteMinecraftArguments;
|
version->vanillaMinecraftArguments = overwriteMinecraftArguments;
|
||||||
}
|
}
|
||||||
@ -374,7 +399,7 @@ void VersionFile::applyTo(VersionFinal *version)
|
|||||||
{
|
{
|
||||||
libs.append(createLibrary(lib));
|
libs.append(createLibrary(lib));
|
||||||
}
|
}
|
||||||
if(isVanilla())
|
if (isVanilla())
|
||||||
version->vanillaLibraries = libs;
|
version->vanillaLibraries = libs;
|
||||||
version->libraries = libs;
|
version->libraries = libs;
|
||||||
}
|
}
|
||||||
@ -498,7 +523,7 @@ void VersionFile::applyTo(VersionFinal *version)
|
|||||||
case RawLibrary::Replace:
|
case RawLibrary::Replace:
|
||||||
{
|
{
|
||||||
QString toReplace;
|
QString toReplace;
|
||||||
if(lib->insertData.isEmpty())
|
if (lib->insertData.isEmpty())
|
||||||
{
|
{
|
||||||
const int startOfVersion = lib->name.lastIndexOf(':') + 1;
|
const int startOfVersion = lib->name.lastIndexOf(':') + 1;
|
||||||
toReplace = QString(lib->name).replace(startOfVersion, INT_MAX, '*');
|
toReplace = QString(lib->name).replace(startOfVersion, INT_MAX, '*');
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QDateTime>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "logic/minecraft/OpSys.h"
|
#include "logic/minecraft/OpSys.h"
|
||||||
#include "logic/minecraft/OneSixRule.h"
|
#include "logic/minecraft/OneSixRule.h"
|
||||||
@ -11,46 +12,8 @@
|
|||||||
#include "JarMod.h"
|
#include "JarMod.h"
|
||||||
|
|
||||||
class VersionFinal;
|
class VersionFinal;
|
||||||
|
|
||||||
|
|
||||||
class VersionBuildError : public MMCError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VersionBuildError(QString cause) : MMCError(cause) {};
|
|
||||||
virtual ~VersionBuildError() noexcept {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the base version file was meant for a newer version of the vanilla launcher than we support
|
|
||||||
*/
|
|
||||||
class LauncherVersionError : public VersionBuildError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LauncherVersionError(int actual, int supported)
|
|
||||||
: VersionBuildError(QObject::tr(
|
|
||||||
"The base version file of this instance was meant for a newer (%1) "
|
|
||||||
"version of the vanilla launcher than this version of MultiMC supports (%2).")
|
|
||||||
.arg(actual)
|
|
||||||
.arg(supported)) {};
|
|
||||||
virtual ~LauncherVersionError() noexcept {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* some patch was intended for a different version of minecraft
|
|
||||||
*/
|
|
||||||
class MinecraftVersionMismatch : public VersionBuildError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MinecraftVersionMismatch(QString fileId, QString mcVersion, QString parentMcVersion)
|
|
||||||
: VersionBuildError(QObject::tr("The patch %1 is for a different version of Minecraft "
|
|
||||||
"(%2) than that of the instance (%3).")
|
|
||||||
.arg(fileId)
|
|
||||||
.arg(mcVersion)
|
|
||||||
.arg(parentMcVersion)) {};
|
|
||||||
virtual ~MinecraftVersionMismatch() noexcept {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VersionFile;
|
struct VersionFile;
|
||||||
|
|
||||||
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
||||||
class VersionFile : public VersionPatch
|
class VersionFile : public VersionPatch
|
||||||
{
|
{
|
||||||
@ -62,7 +25,35 @@ public: /* methods */
|
|||||||
virtual void applyTo(VersionFinal *version) override;
|
virtual void applyTo(VersionFinal *version) override;
|
||||||
virtual bool isVanilla() override;
|
virtual bool isVanilla() override;
|
||||||
virtual bool hasJarMods() override;
|
virtual bool hasJarMods() override;
|
||||||
|
virtual int getOrder() override
|
||||||
|
{
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
virtual void setOrder(int order) override
|
||||||
|
{
|
||||||
|
this->order = order;
|
||||||
|
}
|
||||||
|
virtual QList<JarmodPtr> getJarMods() override
|
||||||
|
{
|
||||||
|
return jarMods;
|
||||||
|
}
|
||||||
|
virtual QString getPatchID() override
|
||||||
|
{
|
||||||
|
return fileId;
|
||||||
|
}
|
||||||
|
virtual QString getPatchName() override
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
virtual QString getPatchVersion() override
|
||||||
|
{
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
virtual QString getPatchFilename() override
|
||||||
|
{
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
public: /* data */
|
public: /* data */
|
||||||
int order = 0;
|
int order = 0;
|
||||||
QString name;
|
QString name;
|
||||||
@ -81,8 +72,16 @@ public: /* data */
|
|||||||
QString removeMinecraftArguments;
|
QString removeMinecraftArguments;
|
||||||
QString processArguments;
|
QString processArguments;
|
||||||
QString type;
|
QString type;
|
||||||
QString versionReleaseTime;
|
|
||||||
QString versionFileUpdateTime;
|
/// the time this version was actually released by Mojang, as string and as QDateTime
|
||||||
|
QString m_releaseTimeString;
|
||||||
|
QDateTime m_releaseTime;
|
||||||
|
|
||||||
|
/// the time this version was last updated by Mojang, as string and as QDateTime
|
||||||
|
QString m_updateTimeString;
|
||||||
|
QDateTime m_updateTime;
|
||||||
|
|
||||||
|
/// asset group used by this ... thing.
|
||||||
QString assets;
|
QString assets;
|
||||||
int minimumLauncherVersion = -1;
|
int minimumLauncherVersion = -1;
|
||||||
|
|
||||||
|
@ -39,8 +39,10 @@ void VersionFinal::reload(const QStringList &external)
|
|||||||
void VersionFinal::clear()
|
void VersionFinal::clear()
|
||||||
{
|
{
|
||||||
id.clear();
|
id.clear();
|
||||||
time.clear();
|
m_updateTimeString.clear();
|
||||||
versionReleaseTime.clear();
|
m_updateTime = QDateTime();
|
||||||
|
m_releaseTimeString.clear();
|
||||||
|
m_releaseTime = QDateTime();
|
||||||
type.clear();
|
type.clear();
|
||||||
assets.clear();
|
assets.clear();
|
||||||
processArguments.clear();
|
processArguments.clear();
|
||||||
@ -56,17 +58,13 @@ void VersionFinal::clear()
|
|||||||
|
|
||||||
bool VersionFinal::canRemove(const int index) const
|
bool VersionFinal::canRemove(const int index) const
|
||||||
{
|
{
|
||||||
if (index < versionFiles.size())
|
return VersionPatches.at(index)->isMoveable();
|
||||||
{
|
|
||||||
return versionFiles.at(index)->fileId != "org.multimc.version.json";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VersionFinal::preremove(VersionFilePtr versionfile)
|
bool VersionFinal::preremove(VersionPatchPtr patch)
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
for(auto & jarmod: versionfile->jarMods)
|
for(auto & jarmod: patch->getJarMods())
|
||||||
{
|
{
|
||||||
QString fullpath =PathCombine(m_instance->jarModsDir(), jarmod->name);
|
QString fullpath =PathCombine(m_instance->jarModsDir(), jarmod->name);
|
||||||
QFileInfo finfo (fullpath);
|
QFileInfo finfo (fullpath);
|
||||||
@ -80,14 +78,14 @@ bool VersionFinal::remove(const int index)
|
|||||||
{
|
{
|
||||||
if (!canRemove(index))
|
if (!canRemove(index))
|
||||||
return false;
|
return false;
|
||||||
if(!preremove(versionFiles[index]))
|
if(!preremove(VersionPatches[index]))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!QFile::remove(versionFiles.at(index)->filename))
|
if(!QFile::remove(VersionPatches.at(index)->getPatchFilename()))
|
||||||
return false;
|
return false;
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
versionFiles.removeAt(index);
|
VersionPatches.removeAt(index);
|
||||||
reapply(true);
|
reapply(true);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
return true;
|
return true;
|
||||||
@ -96,9 +94,9 @@ bool VersionFinal::remove(const int index)
|
|||||||
bool VersionFinal::remove(const QString id)
|
bool VersionFinal::remove(const QString id)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto file : versionFiles)
|
for (auto patch : VersionPatches)
|
||||||
{
|
{
|
||||||
if (file->fileId == id)
|
if (patch->getPatchID() == id)
|
||||||
{
|
{
|
||||||
return remove(i);
|
return remove(i);
|
||||||
}
|
}
|
||||||
@ -109,18 +107,18 @@ bool VersionFinal::remove(const QString id)
|
|||||||
|
|
||||||
QString VersionFinal::versionFileId(const int index) const
|
QString VersionFinal::versionFileId(const int index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= versionFiles.size())
|
if (index < 0 || index >= VersionPatches.size())
|
||||||
{
|
{
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
return versionFiles.at(index)->fileId;
|
return VersionPatches.at(index)->getPatchID();
|
||||||
}
|
}
|
||||||
|
|
||||||
VersionFilePtr VersionFinal::versionPatch(const QString &id)
|
VersionPatchPtr VersionFinal::versionPatch(const QString &id)
|
||||||
{
|
{
|
||||||
for (auto file : versionFiles)
|
for (auto file : VersionPatches)
|
||||||
{
|
{
|
||||||
if (file->fileId == id)
|
if (file->getPatchID() == id)
|
||||||
{
|
{
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@ -128,6 +126,14 @@ VersionFilePtr VersionFinal::versionPatch(const QString &id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VersionPatchPtr VersionFinal::versionPatch(int index)
|
||||||
|
{
|
||||||
|
if(index < 0 || index >= VersionPatches.size())
|
||||||
|
return 0;
|
||||||
|
return VersionPatches[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool VersionFinal::hasJarMods()
|
bool VersionFinal::hasJarMods()
|
||||||
{
|
{
|
||||||
return !jarMods.isEmpty();
|
return !jarMods.isEmpty();
|
||||||
@ -146,7 +152,7 @@ bool VersionFinal::removeFtbPack()
|
|||||||
bool VersionFinal::isVanilla()
|
bool VersionFinal::isVanilla()
|
||||||
{
|
{
|
||||||
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
|
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
|
||||||
if(versionFiles.size() > 1)
|
if(VersionPatches.size() > 1)
|
||||||
return false;
|
return false;
|
||||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
||||||
return false;
|
return false;
|
||||||
@ -156,22 +162,22 @@ bool VersionFinal::isVanilla()
|
|||||||
bool VersionFinal::revertToVanilla()
|
bool VersionFinal::revertToVanilla()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
auto it = versionFiles.begin();
|
auto it = VersionPatches.begin();
|
||||||
while (it != versionFiles.end())
|
while (it != VersionPatches.end())
|
||||||
{
|
{
|
||||||
if ((*it)->fileId != "org.multimc.version.json")
|
if ((*it)->isMoveable())
|
||||||
{
|
{
|
||||||
if(!preremove(*it))
|
if(!preremove(*it))
|
||||||
{
|
{
|
||||||
endResetModel();
|
endResetModel();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!QFile::remove((*it)->filename))
|
if(!QFile::remove((*it)->getPatchFilename()))
|
||||||
{
|
{
|
||||||
endResetModel();
|
endResetModel();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
it = versionFiles.erase(it);
|
it = VersionPatches.erase(it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
@ -233,7 +239,7 @@ QVariant VersionFinal::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 >= versionFiles.size())
|
if (row < 0 || row >= VersionPatches.size())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
@ -241,9 +247,9 @@ QVariant VersionFinal::data(const QModelIndex &index, int role) const
|
|||||||
switch (column)
|
switch (column)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return versionFiles.at(row)->name;
|
return VersionPatches.at(row)->getPatchName();
|
||||||
case 1:
|
case 1:
|
||||||
return versionFiles.at(row)->version;
|
return VersionPatches.at(row)->getPatchVersion();
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -278,7 +284,7 @@ Qt::ItemFlags VersionFinal::flags(const QModelIndex &index) const
|
|||||||
|
|
||||||
int VersionFinal::rowCount(const QModelIndex &parent) const
|
int VersionFinal::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return versionFiles.size();
|
return VersionPatches.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int VersionFinal::columnCount(const QModelIndex &parent) const
|
int VersionFinal::columnCount(const QModelIndex &parent) const
|
||||||
@ -288,13 +294,12 @@ int VersionFinal::columnCount(const QModelIndex &parent) const
|
|||||||
|
|
||||||
QMap<QString, int> VersionFinal::getExistingOrder() const
|
QMap<QString, int> VersionFinal::getExistingOrder() const
|
||||||
{
|
{
|
||||||
|
|
||||||
QMap<QString, int> order;
|
QMap<QString, int> order;
|
||||||
// default
|
// default
|
||||||
{
|
{
|
||||||
for (auto file : versionFiles)
|
for (auto file : VersionPatches)
|
||||||
{
|
{
|
||||||
order.insert(file->fileId, file->order);
|
order.insert(file->getPatchID(), file->getOrder());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// overriden
|
// overriden
|
||||||
@ -314,39 +319,37 @@ QMap<QString, int> VersionFinal::getExistingOrder() const
|
|||||||
void VersionFinal::move(const int index, const MoveDirection direction)
|
void VersionFinal::move(const int index, const MoveDirection direction)
|
||||||
{
|
{
|
||||||
int theirIndex;
|
int theirIndex;
|
||||||
|
int theirIndex_qt;
|
||||||
if (direction == MoveUp)
|
if (direction == MoveUp)
|
||||||
{
|
{
|
||||||
theirIndex = index - 1;
|
theirIndex_qt = theirIndex = index - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
theirIndex = index + 1;
|
theirIndex = index + 1;
|
||||||
|
theirIndex_qt = index + 2;
|
||||||
}
|
}
|
||||||
if (theirIndex < 0 || theirIndex >= versionFiles.size())
|
auto from = versionPatch(index);
|
||||||
{
|
auto to = versionPatch(theirIndex);
|
||||||
return;
|
|
||||||
}
|
if (!from || !to || !from->isMoveable() || !from->isMoveable())
|
||||||
const QString ourId = versionFileId(index);
|
|
||||||
const QString theirId = versionFileId(theirIndex);
|
|
||||||
if (ourId.isNull() || ourId.startsWith("org.multimc.") ||
|
|
||||||
theirId.isNull() || theirId.startsWith("org.multimc."))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(direction == MoveDown)
|
if(direction == MoveDown)
|
||||||
{
|
{
|
||||||
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex+1);
|
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex);
|
beginMoveRows(QModelIndex(), index, index, QModelIndex(), theirIndex_qt);
|
||||||
}
|
}
|
||||||
versionFiles.swap(index, theirIndex);
|
VersionPatches.swap(index, theirIndex);
|
||||||
endMoveRows();
|
endMoveRows();
|
||||||
|
|
||||||
auto order = getExistingOrder();
|
auto order = getExistingOrder();
|
||||||
order[ourId] = theirIndex;
|
order[from->getPatchID()] = theirIndex;
|
||||||
order[theirId] = index;
|
order[to->getPatchID()] = index;
|
||||||
|
|
||||||
if (!VersionBuilder::writeOverrideOrders(order, m_instance))
|
if (!VersionBuilder::writeOverrideOrders(order, m_instance))
|
||||||
{
|
{
|
||||||
@ -375,14 +378,14 @@ void VersionFinal::reapply(const bool alreadyReseting)
|
|||||||
auto existingOrders = getExistingOrder();
|
auto existingOrders = getExistingOrder();
|
||||||
QList<int> orders = existingOrders.values();
|
QList<int> orders = existingOrders.values();
|
||||||
std::sort(orders.begin(), orders.end());
|
std::sort(orders.begin(), orders.end());
|
||||||
QList<VersionFilePtr> newVersionFiles;
|
QList<VersionPatchPtr> newVersionFiles;
|
||||||
for (auto order : orders)
|
for (auto order : orders)
|
||||||
{
|
{
|
||||||
auto file = versionPatch(existingOrders.key(order));
|
auto file = versionPatch(existingOrders.key(order));
|
||||||
newVersionFiles.append(file);
|
newVersionFiles.append(file);
|
||||||
file->applyTo(this);
|
file->applyTo(this);
|
||||||
}
|
}
|
||||||
versionFiles.swap(newVersionFiles);
|
VersionPatches.swap(newVersionFiles);
|
||||||
finalize();
|
finalize();
|
||||||
if (!alreadyReseting)
|
if (!alreadyReseting)
|
||||||
{
|
{
|
||||||
|
@ -83,16 +83,21 @@ public:
|
|||||||
static std::shared_ptr<VersionFinal> fromJson(const QJsonObject &obj);
|
static std::shared_ptr<VersionFinal> fromJson(const QJsonObject &obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool preremove(VersionFilePtr);
|
bool preremove(VersionPatchPtr patch);
|
||||||
|
|
||||||
// data members
|
// data members
|
||||||
public:
|
public:
|
||||||
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
|
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
|
||||||
QString id;
|
QString id;
|
||||||
/// Last updated time - as a string
|
|
||||||
QString time;
|
/// the time this version was actually released by Mojang, as string and as QDateTime
|
||||||
/// Release time - as a string
|
QString m_releaseTimeString;
|
||||||
QString versionReleaseTime;
|
QDateTime m_releaseTime;
|
||||||
|
|
||||||
|
/// the time this version was last updated by Mojang, as string and as QDateTime
|
||||||
|
QString m_updateTimeString;
|
||||||
|
QDateTime m_updateTime;
|
||||||
|
|
||||||
/// Release type - "release" or "snapshot"
|
/// Release type - "release" or "snapshot"
|
||||||
QString type;
|
QString type;
|
||||||
/// Assets type - "legacy" or a version ID
|
/// Assets type - "legacy" or a version ID
|
||||||
@ -164,8 +169,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
// QList<Rule> rules;
|
// QList<Rule> rules;
|
||||||
|
|
||||||
QList<VersionFilePtr> versionFiles;
|
QList<VersionPatchPtr> VersionPatches;
|
||||||
VersionFilePtr versionPatch(const QString &id);
|
VersionPatchPtr versionPatch(const QString &id);
|
||||||
|
VersionPatchPtr versionPatch(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OneSixInstance *m_instance;
|
OneSixInstance *m_instance;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <QList>
|
||||||
|
#include "JarMod.h"
|
||||||
|
|
||||||
class VersionFinal;
|
class VersionFinal;
|
||||||
class VersionPatch
|
class VersionPatch
|
||||||
@ -8,8 +10,22 @@ class VersionPatch
|
|||||||
public:
|
public:
|
||||||
virtual ~VersionPatch(){};
|
virtual ~VersionPatch(){};
|
||||||
virtual void applyTo(VersionFinal *version) = 0;
|
virtual void applyTo(VersionFinal *version) = 0;
|
||||||
|
|
||||||
virtual bool isVanilla() = 0;
|
virtual bool isVanilla() = 0;
|
||||||
virtual bool hasJarMods() = 0;
|
virtual bool hasJarMods() = 0;
|
||||||
|
virtual QList<JarmodPtr> getJarMods() = 0;
|
||||||
|
|
||||||
|
virtual bool isMoveable()
|
||||||
|
{
|
||||||
|
return getOrder() >= 0;
|
||||||
|
}
|
||||||
|
virtual void setOrder(int order) = 0;
|
||||||
|
virtual int getOrder() = 0;
|
||||||
|
|
||||||
|
virtual QString getPatchID() = 0;
|
||||||
|
virtual QString getPatchName() = 0;
|
||||||
|
virtual QString getPatchVersion() = 0;
|
||||||
|
virtual QString getPatchFilename() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<VersionPatch> VersionPatchPtr;
|
typedef std::shared_ptr<VersionPatch> VersionPatchPtr;
|
||||||
|
@ -495,6 +495,7 @@
|
|||||||
"releaseTime": "2010-07-13T00:00:00+02:00",
|
"releaseTime": "2010-07-13T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "y",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -502,6 +503,7 @@
|
|||||||
"releaseTime": "2010-07-09T00:00:00+02:00",
|
"releaseTime": "2010-07-09T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "ax",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -509,6 +511,8 @@
|
|||||||
"releaseTime": "2010-06-16T00:00:00+02:00",
|
"releaseTime": "2010-06-16T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "net.minecraft.client.d",
|
||||||
|
"appletClass": "net.minecraft.client.MinecraftApplet",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -516,6 +520,8 @@
|
|||||||
"releaseTime": "2009-12-22T00:00:00+02:00",
|
"releaseTime": "2009-12-22T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "com.mojang.minecraft.l",
|
||||||
|
"appletClass": "com.mojang.minecraft.MinecraftApplet",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -523,6 +529,8 @@
|
|||||||
"releaseTime": "2009-05-22T00:00:00+02:00",
|
"releaseTime": "2009-05-22T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "com.mojang.minecraft.c",
|
||||||
|
"appletClass": "com.mojang.minecraft.MinecraftApplet",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -530,6 +538,8 @@
|
|||||||
"releaseTime": "2009-05-31T00:00:00+02:00",
|
"releaseTime": "2009-05-31T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "com.mojang.minecraft.Minecraft",
|
||||||
|
"appletClass": "com.mojang.minecraft.MinecraftApplet",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -537,6 +547,8 @@
|
|||||||
"releaseTime": "2009-05-17T00:00:00+02:00",
|
"releaseTime": "2009-05-17T00:00:00+02:00",
|
||||||
"type": "old_alpha",
|
"type": "old_alpha",
|
||||||
"processArguments": "legacy",
|
"processArguments": "legacy",
|
||||||
|
"mainClass": "com.mojang.minecraft.Minecraft",
|
||||||
|
"appletClass": "com.mojang.minecraft.MinecraftApplet",
|
||||||
"+traits": ["legacyLaunch"]
|
"+traits": ["legacyLaunch"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user