NOISSUE Refactors and moving of things
This commit is contained in:
@ -11,30 +11,6 @@ JarmodPtr Jarmod::fromJson(const QJsonObject &libObj, const QString &filename)
|
||||
"contains a jarmod that doesn't have a 'name' field");
|
||||
}
|
||||
out->name = libObj.value("name").toString();
|
||||
|
||||
auto readString = [libObj, filename](const QString & key, QString & variable)
|
||||
{
|
||||
if (libObj.contains(key))
|
||||
{
|
||||
QJsonValue val = libObj.value(key);
|
||||
if (!val.isString())
|
||||
{
|
||||
QLOG_WARN() << key << "is not a string in" << filename << "(skipping)";
|
||||
}
|
||||
else
|
||||
{
|
||||
variable = val.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
readString("url", out->baseurl);
|
||||
readString("MMC-hint", out->hint);
|
||||
readString("MMC-absoluteUrl", out->absoluteUrl);
|
||||
if(!out->baseurl.isEmpty() && out->absoluteUrl.isEmpty())
|
||||
{
|
||||
out->absoluteUrl = out->baseurl + out->name;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -42,15 +18,5 @@ QJsonObject Jarmod::toJson()
|
||||
{
|
||||
QJsonObject out;
|
||||
writeString(out, "name", name);
|
||||
writeString(out, "url", baseurl);
|
||||
writeString(out, "MMC-absoluteUrl", absoluteUrl);
|
||||
writeString(out, "MMC-hint", hint);
|
||||
return out;
|
||||
}
|
||||
|
||||
QString Jarmod::url()
|
||||
{
|
||||
if(!absoluteUrl.isEmpty())
|
||||
return absoluteUrl;
|
||||
else return baseurl + name;
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ class Jarmod
|
||||
public: /* methods */
|
||||
static JarmodPtr fromJson(const QJsonObject &libObj, const QString &filename);
|
||||
QJsonObject toJson();
|
||||
QString url();
|
||||
public: /* data */
|
||||
QString name;
|
||||
QString baseurl;
|
||||
QString hint;
|
||||
QString absoluteUrl;
|
||||
};
|
||||
|
58
logic/minecraft/MinecraftInstance.cpp
Normal file
58
logic/minecraft/MinecraftInstance.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "MinecraftInstance.h"
|
||||
#include "MultiMC.h"
|
||||
#include "logic/settings/SettingsObject.h"
|
||||
#include <pathutils.h>
|
||||
#include "logic/minecraft/MinecraftVersionList.h"
|
||||
|
||||
MinecraftInstance::MinecraftInstance(const QString &rootDir, SettingsObject *settings, QObject *parent)
|
||||
: BaseInstance(rootDir, settings, parent)
|
||||
{
|
||||
auto globalSettings = MMC->settings();
|
||||
|
||||
// Java Settings
|
||||
m_settings->registerSetting("OverrideJava", false);
|
||||
m_settings->registerSetting("OverrideJavaLocation", false);
|
||||
m_settings->registerSetting("OverrideJavaArgs", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("JavaPath"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("JvmArgs"));
|
||||
|
||||
// Custom Commands
|
||||
m_settings->registerSetting({"OverrideCommands","OverrideLaunchCmd"}, false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("PreLaunchCommand"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("PostExitCommand"));
|
||||
|
||||
// Window Size
|
||||
m_settings->registerSetting("OverrideWindow", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("LaunchMaximized"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinWidth"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("MinecraftWinHeight"));
|
||||
|
||||
// Memory
|
||||
m_settings->registerSetting("OverrideMemory", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("MinMemAlloc"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("MaxMemAlloc"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("PermGen"));
|
||||
|
||||
// Console
|
||||
m_settings->registerSetting("OverrideConsole", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("ShowConsole"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("AutoCloseConsole"));
|
||||
m_settings->registerOverride(globalSettings->getSetting("LogPrePostOutput"));
|
||||
}
|
||||
|
||||
QString MinecraftInstance::minecraftRoot() const
|
||||
{
|
||||
QFileInfo mcDir(PathCombine(instanceRoot(), "minecraft"));
|
||||
QFileInfo dotMCDir(PathCombine(instanceRoot(), ".minecraft"));
|
||||
|
||||
if (dotMCDir.exists() && !mcDir.exists())
|
||||
return dotMCDir.filePath();
|
||||
else
|
||||
return mcDir.filePath();
|
||||
}
|
||||
|
||||
std::shared_ptr< BaseVersionList > MinecraftInstance::versionList() const
|
||||
{
|
||||
return std::dynamic_pointer_cast<BaseVersionList>(MMC->minecraftlist());
|
||||
}
|
||||
|
30
logic/minecraft/MinecraftInstance.h
Normal file
30
logic/minecraft/MinecraftInstance.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "logic/BaseInstance.h"
|
||||
|
||||
class MinecraftInstance: public BaseInstance
|
||||
{
|
||||
public:
|
||||
MinecraftInstance(const QString& rootDir, SettingsObject* settings, QObject* parent = 0);
|
||||
virtual ~MinecraftInstance() {};
|
||||
|
||||
/// Path to the instance's minecraft directory.
|
||||
QString minecraftRoot() const;
|
||||
|
||||
////// Mod Lists //////
|
||||
virtual std::shared_ptr<ModList> resourcePackList() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual std::shared_ptr<ModList> texturePackList() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
/// get all jar mods applicable to this instance's jar
|
||||
virtual QList<Mod> getJarMods() const
|
||||
{
|
||||
return QList<Mod>();
|
||||
}
|
||||
virtual std::shared_ptr< BaseVersionList > versionList() const;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<MinecraftInstance> MinecraftInstancePtr;
|
216
logic/minecraft/MinecraftProcess.cpp
Normal file
216
logic/minecraft/MinecraftProcess.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/* Copyright 2013-2014 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "MultiMC.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include "logic/minecraft/MinecraftProcess.h"
|
||||
#include "logic/BaseInstance.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "osutils.h"
|
||||
#include "pathutils.h"
|
||||
#include "cmdutils.h"
|
||||
|
||||
#define IBUS "@im=ibus"
|
||||
|
||||
// constructor
|
||||
MinecraftProcess::MinecraftProcess(MinecraftInstancePtr inst) : BaseProcess(inst)
|
||||
{
|
||||
}
|
||||
|
||||
MinecraftProcess* MinecraftProcess::create(MinecraftInstancePtr inst)
|
||||
{
|
||||
auto proc = new MinecraftProcess(inst);
|
||||
proc->init();
|
||||
return proc;
|
||||
}
|
||||
|
||||
|
||||
QString MinecraftProcess::censorPrivateInfo(QString in)
|
||||
{
|
||||
if (!m_session)
|
||||
return in;
|
||||
|
||||
if (m_session->session != "-")
|
||||
in.replace(m_session->session, "<SESSION ID>");
|
||||
in.replace(m_session->access_token, "<ACCESS TOKEN>");
|
||||
in.replace(m_session->client_token, "<CLIENT TOKEN>");
|
||||
in.replace(m_session->uuid, "<PROFILE ID>");
|
||||
in.replace(m_session->player_name, "<PROFILE NAME>");
|
||||
|
||||
auto i = m_session->u.properties.begin();
|
||||
while (i != m_session->u.properties.end())
|
||||
{
|
||||
in.replace(i.value(), "<" + i.key().toUpper() + ">");
|
||||
++i;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
// console window
|
||||
MessageLevel::Enum MinecraftProcess::guessLevel(const QString &line, MessageLevel::Enum level)
|
||||
{
|
||||
QRegularExpression re("\\[(?<timestamp>[0-9:]+)\\] \\[[^/]+/(?<level>[^\\]]+)\\]");
|
||||
auto match = re.match(line);
|
||||
if(match.hasMatch())
|
||||
{
|
||||
// New style logs from log4j
|
||||
QString timestamp = match.captured("timestamp");
|
||||
QString levelStr = match.captured("level");
|
||||
if(levelStr == "INFO")
|
||||
level = MessageLevel::Message;
|
||||
if(levelStr == "WARN")
|
||||
level = MessageLevel::Warning;
|
||||
if(levelStr == "ERROR")
|
||||
level = MessageLevel::Error;
|
||||
if(levelStr == "FATAL")
|
||||
level = MessageLevel::Fatal;
|
||||
if(levelStr == "TRACE" || levelStr == "DEBUG")
|
||||
level = MessageLevel::Debug;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old style forge logs
|
||||
if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") ||
|
||||
line.contains("[FINER]") || line.contains("[FINEST]"))
|
||||
level = MessageLevel::Message;
|
||||
if (line.contains("[SEVERE]") || line.contains("[STDERR]"))
|
||||
level = MessageLevel::Error;
|
||||
if (line.contains("[WARNING]"))
|
||||
level = MessageLevel::Warning;
|
||||
if (line.contains("[DEBUG]"))
|
||||
level = MessageLevel::Debug;
|
||||
}
|
||||
if (line.contains("overwriting existing"))
|
||||
return MessageLevel::Fatal;
|
||||
if (line.contains("Exception in thread") || line.contains(QRegularExpression("\\s+at ")))
|
||||
return MessageLevel::Error;
|
||||
return level;
|
||||
}
|
||||
|
||||
QMap<QString, QString> MinecraftProcess::getVariables() const
|
||||
{
|
||||
auto mcInstance = std::dynamic_pointer_cast<MinecraftInstance>(m_instance);
|
||||
QMap<QString, QString> out;
|
||||
out.insert("INST_NAME", mcInstance->name());
|
||||
out.insert("INST_ID", mcInstance->id());
|
||||
out.insert("INST_DIR", QDir(mcInstance->instanceRoot()).absolutePath());
|
||||
out.insert("INST_MC_DIR", QDir(mcInstance->minecraftRoot()).absolutePath());
|
||||
out.insert("INST_JAVA", mcInstance->settings().get("JavaPath").toString());
|
||||
out.insert("INST_JAVA_ARGS", javaArguments().join(' '));
|
||||
return out;
|
||||
}
|
||||
|
||||
QStringList MinecraftProcess::javaArguments() const
|
||||
{
|
||||
QStringList args;
|
||||
|
||||
// custom args go first. we want to override them if we have our own here.
|
||||
args.append(m_instance->extraArguments());
|
||||
|
||||
// OSX dock icon and name
|
||||
#ifdef OSX
|
||||
args << "-Xdock:icon=icon.png";
|
||||
args << QString("-Xdock:name=\"%1\"").arg(m_instance->windowTitle());
|
||||
#endif
|
||||
|
||||
// HACK: Stupid hack for Intel drivers. See: https://mojang.atlassian.net/browse/MCL-767
|
||||
#ifdef Q_OS_WIN32
|
||||
args << QString("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_"
|
||||
"minecraft.exe.heapdump");
|
||||
#endif
|
||||
|
||||
args << QString("-Xms%1m").arg(m_instance->settings().get("MinMemAlloc").toInt());
|
||||
args << QString("-Xmx%1m").arg(m_instance->settings().get("MaxMemAlloc").toInt());
|
||||
auto permgen = m_instance->settings().get("PermGen").toInt();
|
||||
if (permgen != 64)
|
||||
{
|
||||
args << QString("-XX:PermSize=%1m").arg(permgen);
|
||||
}
|
||||
args << "-Duser.language=en";
|
||||
if (!m_nativeFolder.isEmpty())
|
||||
args << QString("-Djava.library.path=%1").arg(m_nativeFolder);
|
||||
args << "-jar" << PathCombine(MMC->bin(), "jars", "NewLaunch.jar");
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void MinecraftProcess::arm()
|
||||
{
|
||||
emit log("MultiMC version: " + BuildConfig.printableVersionString() + "\n\n");
|
||||
emit log("Minecraft folder is:\n" + workingDirectory() + "\n\n");
|
||||
|
||||
if (!preLaunch())
|
||||
{
|
||||
emit ended(m_instance, 1, QProcess::CrashExit);
|
||||
return;
|
||||
}
|
||||
|
||||
m_instance->setLastLaunch();
|
||||
|
||||
QStringList args = javaArguments();
|
||||
|
||||
QString JavaPath = m_instance->settings().get("JavaPath").toString();
|
||||
emit log("Java path is:\n" + JavaPath + "\n\n");
|
||||
QString allArgs = args.join(", ");
|
||||
emit log("Java Arguments:\n[" + censorPrivateInfo(allArgs) + "]\n\n");
|
||||
|
||||
auto realJavaPath = QStandardPaths::findExecutable(JavaPath);
|
||||
if (realJavaPath.isEmpty())
|
||||
{
|
||||
emit log(tr("The java binary \"%1\" couldn't be found. You may have to set up java "
|
||||
"if Minecraft fails to launch.").arg(JavaPath),
|
||||
MessageLevel::Warning);
|
||||
}
|
||||
|
||||
// instantiate the launcher part
|
||||
start(JavaPath, args);
|
||||
if (!waitForStarted())
|
||||
{
|
||||
//: Error message displayed if instace can't start
|
||||
emit log(tr("Could not launch minecraft!"), MessageLevel::Error);
|
||||
m_instance->cleanupAfterRun();
|
||||
emit launch_failed(m_instance);
|
||||
// not running, failed
|
||||
m_instance->setRunning(false);
|
||||
return;
|
||||
}
|
||||
// send the launch script to the launcher part
|
||||
QByteArray bytes = launchScript.toUtf8();
|
||||
writeData(bytes.constData(), bytes.length());
|
||||
}
|
||||
|
||||
void MinecraftProcess::launch()
|
||||
{
|
||||
QString launchString("launch\n");
|
||||
QByteArray bytes = launchString.toUtf8();
|
||||
writeData(bytes.constData(), bytes.length());
|
||||
}
|
||||
|
||||
void MinecraftProcess::abort()
|
||||
{
|
||||
QString launchString("abort\n");
|
||||
QByteArray bytes = launchString.toUtf8();
|
||||
writeData(bytes.constData(), bytes.length());
|
||||
}
|
77
logic/minecraft/MinecraftProcess.h
Normal file
77
logic/minecraft/MinecraftProcess.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* Copyright 2013-2014 MultiMC Contributors
|
||||
*
|
||||
* Authors: Orochimarufan <orochimarufan.x3@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include "logic/minecraft/MinecraftInstance.h"
|
||||
#include "logic/BaseProcess.h"
|
||||
|
||||
/**
|
||||
* The MinecraftProcess class
|
||||
*/
|
||||
class MinecraftProcess : public BaseProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
MinecraftProcess(MinecraftInstancePtr inst);
|
||||
public:
|
||||
static MinecraftProcess *create(MinecraftInstancePtr inst);
|
||||
|
||||
virtual ~MinecraftProcess(){};
|
||||
|
||||
/**
|
||||
* @brief start the launcher part with the provided launch script
|
||||
*/
|
||||
void arm() override;
|
||||
|
||||
/**
|
||||
* @brief launch the armed instance!
|
||||
*/
|
||||
void launch() override;
|
||||
|
||||
/**
|
||||
* @brief abort launch!
|
||||
*/
|
||||
void abort() override;
|
||||
|
||||
void setLaunchScript(QString script)
|
||||
{
|
||||
launchScript = script;
|
||||
}
|
||||
|
||||
void setNativeFolder(QString natives)
|
||||
{
|
||||
m_nativeFolder = natives;
|
||||
}
|
||||
|
||||
inline void setLogin(AuthSessionPtr session)
|
||||
{
|
||||
m_session = session;
|
||||
}
|
||||
|
||||
protected:
|
||||
AuthSessionPtr m_session;
|
||||
QString launchScript;
|
||||
QString m_nativeFolder;
|
||||
|
||||
virtual QMap<QString, QString> getVariables() const override;
|
||||
|
||||
QStringList javaArguments() const;
|
||||
virtual QString censorPrivateInfo(QString in) override;
|
||||
virtual MessageLevel::Enum guessLevel(const QString &message, MessageLevel::Enum defaultLevel) override;
|
||||
};
|
@ -15,31 +15,50 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QUuid>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <pathutils.h>
|
||||
|
||||
#include "logic/minecraft/InstanceVersion.h"
|
||||
#include "logic/minecraft/MinecraftProfile.h"
|
||||
#include "logic/minecraft/VersionBuilder.h"
|
||||
#include "ProfileUtils.h"
|
||||
#include "NullProfileStrategy.h"
|
||||
#include "logic/OneSixInstance.h"
|
||||
|
||||
InstanceVersion::InstanceVersion(OneSixInstance *instance, QObject *parent)
|
||||
: QAbstractListModel(parent), m_instance(instance)
|
||||
MinecraftProfile::MinecraftProfile(ProfileStrategy *strategy)
|
||||
: QAbstractListModel()
|
||||
{
|
||||
setStrategy(strategy);
|
||||
clear();
|
||||
}
|
||||
|
||||
void InstanceVersion::reload(const QStringList &external)
|
||||
void MinecraftProfile::setStrategy(ProfileStrategy* strategy)
|
||||
{
|
||||
Q_ASSERT(strategy != nullptr);
|
||||
|
||||
if(m_strategy != nullptr)
|
||||
{
|
||||
delete m_strategy;
|
||||
m_strategy = nullptr;
|
||||
}
|
||||
m_strategy = strategy;
|
||||
m_strategy->profile = this;
|
||||
}
|
||||
|
||||
ProfileStrategy* MinecraftProfile::strategy()
|
||||
{
|
||||
return m_strategy;
|
||||
}
|
||||
|
||||
void MinecraftProfile::reload()
|
||||
{
|
||||
m_externalPatches = external;
|
||||
beginResetModel();
|
||||
VersionBuilder::build(this, m_instance, m_externalPatches);
|
||||
reapply(true);
|
||||
m_strategy->load();
|
||||
reapply();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void InstanceVersion::clear()
|
||||
void MinecraftProfile::clear()
|
||||
{
|
||||
id.clear();
|
||||
m_updateTimeString.clear();
|
||||
@ -59,44 +78,45 @@ void InstanceVersion::clear()
|
||||
traits.clear();
|
||||
}
|
||||
|
||||
bool InstanceVersion::canRemove(const int index) const
|
||||
void MinecraftProfile::clearPatches()
|
||||
{
|
||||
beginResetModel();
|
||||
VersionPatches.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void MinecraftProfile::appendPatch(ProfilePatchPtr patch)
|
||||
{
|
||||
int index = VersionPatches.size();
|
||||
beginInsertRows(QModelIndex(), index, index);
|
||||
VersionPatches.append(patch);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
bool MinecraftProfile::canRemove(const int index) const
|
||||
{
|
||||
return VersionPatches.at(index)->isMoveable();
|
||||
}
|
||||
|
||||
bool InstanceVersion::preremove(VersionPatchPtr patch)
|
||||
{
|
||||
bool ok = true;
|
||||
for(auto & jarmod: patch->getJarMods())
|
||||
{
|
||||
QString fullpath =PathCombine(m_instance->jarModsDir(), jarmod->name);
|
||||
QFileInfo finfo (fullpath);
|
||||
if(finfo.exists())
|
||||
ok &= QFile::remove(fullpath);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool InstanceVersion::remove(const int index)
|
||||
bool MinecraftProfile::remove(const int index)
|
||||
{
|
||||
if (!canRemove(index))
|
||||
return false;
|
||||
if(!preremove(VersionPatches[index]))
|
||||
|
||||
if(!m_strategy->removePatch(VersionPatches.at(index)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto toDelete = VersionPatches.at(index)->getPatchFilename();
|
||||
if(!QFile::remove(toDelete))
|
||||
return false;
|
||||
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
VersionPatches.removeAt(index);
|
||||
endRemoveRows();
|
||||
reapply(true);
|
||||
reapply();
|
||||
saveCurrentOrder();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstanceVersion::remove(const QString id)
|
||||
bool MinecraftProfile::remove(const QString id)
|
||||
{
|
||||
int i = 0;
|
||||
for (auto patch : VersionPatches)
|
||||
@ -110,7 +130,7 @@ bool InstanceVersion::remove(const QString id)
|
||||
return false;
|
||||
}
|
||||
|
||||
QString InstanceVersion::versionFileId(const int index) const
|
||||
QString MinecraftProfile::versionFileId(const int index) const
|
||||
{
|
||||
if (index < 0 || index >= VersionPatches.size())
|
||||
{
|
||||
@ -119,7 +139,7 @@ QString InstanceVersion::versionFileId(const int index) const
|
||||
return VersionPatches.at(index)->getPatchID();
|
||||
}
|
||||
|
||||
VersionPatchPtr InstanceVersion::versionPatch(const QString &id)
|
||||
ProfilePatchPtr MinecraftProfile::versionPatch(const QString &id)
|
||||
{
|
||||
for (auto file : VersionPatches)
|
||||
{
|
||||
@ -131,67 +151,27 @@ VersionPatchPtr InstanceVersion::versionPatch(const QString &id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
VersionPatchPtr InstanceVersion::versionPatch(int index)
|
||||
ProfilePatchPtr MinecraftProfile::versionPatch(int index)
|
||||
{
|
||||
if(index < 0 || index >= VersionPatches.size())
|
||||
return 0;
|
||||
return VersionPatches[index];
|
||||
}
|
||||
|
||||
|
||||
bool InstanceVersion::hasJarMods()
|
||||
bool MinecraftProfile::isVanilla()
|
||||
{
|
||||
return !jarMods.isEmpty();
|
||||
}
|
||||
|
||||
bool InstanceVersion::hasFtbPack()
|
||||
{
|
||||
return versionPatch("org.multimc.ftb.pack.json") != nullptr;
|
||||
}
|
||||
|
||||
bool InstanceVersion::removeFtbPack()
|
||||
{
|
||||
return remove("org.multimc.ftb.pack.json");
|
||||
}
|
||||
|
||||
bool InstanceVersion::isVanilla()
|
||||
{
|
||||
QDir patches(PathCombine(m_instance->instanceRoot(), "patches/"));
|
||||
for(auto patchptr: VersionPatches)
|
||||
{
|
||||
if(patchptr->isCustom())
|
||||
return false;
|
||||
}
|
||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
||||
return false;
|
||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "version.json")))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstanceVersion::revertToVanilla()
|
||||
bool MinecraftProfile::revertToVanilla()
|
||||
{
|
||||
/*
|
||||
beginResetModel();
|
||||
// remove custom.json, if present
|
||||
QString customPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
||||
if(QFile::exists(customPath))
|
||||
{
|
||||
if(!QFile::remove(customPath))
|
||||
{
|
||||
endResetModel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// remove version.json, if present
|
||||
QString versionPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
||||
if(QFile::exists(versionPath))
|
||||
{
|
||||
if(!QFile::remove(versionPath))
|
||||
{
|
||||
endResetModel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// remove patches, if present
|
||||
auto it = VersionPatches.begin();
|
||||
while (it != VersionPatches.end())
|
||||
@ -215,49 +195,15 @@ bool InstanceVersion::revertToVanilla()
|
||||
else
|
||||
it++;
|
||||
}
|
||||
reapply(true);
|
||||
reapply();
|
||||
endResetModel();
|
||||
saveCurrentOrder();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstanceVersion::hasDeprecatedVersionFiles()
|
||||
{
|
||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "custom.json")))
|
||||
return true;
|
||||
if(QFile::exists(PathCombine(m_instance->instanceRoot(), "version.json")))
|
||||
return true;
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InstanceVersion::removeDeprecatedVersionFiles()
|
||||
{
|
||||
beginResetModel();
|
||||
// remove custom.json, if present
|
||||
QString customPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
||||
if(QFile::exists(customPath))
|
||||
{
|
||||
if(!QFile::remove(customPath))
|
||||
{
|
||||
endResetModel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// remove version.json, if present
|
||||
QString versionPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
||||
if(QFile::exists(versionPath))
|
||||
{
|
||||
if(!QFile::remove(versionPath))
|
||||
{
|
||||
endResetModel();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs()
|
||||
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNormalLibs()
|
||||
{
|
||||
QList<std::shared_ptr<OneSixLibrary> > output;
|
||||
for (auto lib : libraries)
|
||||
@ -277,7 +223,8 @@ QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNormalLibs()
|
||||
}
|
||||
return output;
|
||||
}
|
||||
QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs()
|
||||
|
||||
QList<std::shared_ptr<OneSixLibrary> > MinecraftProfile::getActiveNativeLibs()
|
||||
{
|
||||
QList<std::shared_ptr<OneSixLibrary> > output;
|
||||
for (auto lib : libraries)
|
||||
@ -290,9 +237,9 @@ QList<std::shared_ptr<OneSixLibrary> > InstanceVersion::getActiveNativeLibs()
|
||||
return output;
|
||||
}
|
||||
|
||||
std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &obj)
|
||||
std::shared_ptr<MinecraftProfile> MinecraftProfile::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
std::shared_ptr<InstanceVersion> version(new InstanceVersion(0));
|
||||
std::shared_ptr<MinecraftProfile> version(new MinecraftProfile(new NullProfileStrategy()));
|
||||
try
|
||||
{
|
||||
VersionBuilder::readJsonAndApplyToVersion(version.get(), obj);
|
||||
@ -304,7 +251,7 @@ std::shared_ptr<InstanceVersion> InstanceVersion::fromJson(const QJsonObject &ob
|
||||
return version;
|
||||
}
|
||||
|
||||
QVariant InstanceVersion::data(const QModelIndex &index, int role) const
|
||||
QVariant MinecraftProfile::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
@ -329,7 +276,7 @@ QVariant InstanceVersion::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
QVariant MinecraftProfile::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
@ -348,36 +295,36 @@ QVariant InstanceVersion::headerData(int section, Qt::Orientation orientation, i
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
Qt::ItemFlags InstanceVersion::flags(const QModelIndex &index) const
|
||||
Qt::ItemFlags MinecraftProfile::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
int InstanceVersion::rowCount(const QModelIndex &parent) const
|
||||
int MinecraftProfile::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return VersionPatches.size();
|
||||
}
|
||||
|
||||
int InstanceVersion::columnCount(const QModelIndex &parent) const
|
||||
int MinecraftProfile::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void InstanceVersion::saveCurrentOrder() const
|
||||
void MinecraftProfile::saveCurrentOrder() const
|
||||
{
|
||||
PatchOrder order;
|
||||
ProfileUtils::PatchOrder order;
|
||||
for(auto item: VersionPatches)
|
||||
{
|
||||
if(!item->isMoveable())
|
||||
continue;
|
||||
order.append(item->getPatchID());
|
||||
}
|
||||
VersionBuilder::writeOverrideOrders(m_instance, order);
|
||||
m_strategy->saveOrder(order);
|
||||
}
|
||||
|
||||
void InstanceVersion::move(const int index, const MoveDirection direction)
|
||||
void MinecraftProfile::move(const int index, const MoveDirection direction)
|
||||
{
|
||||
int theirIndex;
|
||||
if (direction == MoveUp)
|
||||
@ -388,7 +335,7 @@ void InstanceVersion::move(const int index, const MoveDirection direction)
|
||||
{
|
||||
theirIndex = index + 1;
|
||||
}
|
||||
|
||||
|
||||
if (index < 0 || index >= VersionPatches.size())
|
||||
return;
|
||||
if (theirIndex >= rowCount())
|
||||
@ -401,7 +348,7 @@ void InstanceVersion::move(const int index, const MoveDirection direction)
|
||||
|
||||
auto from = versionPatch(index);
|
||||
auto to = versionPatch(theirIndex);
|
||||
|
||||
|
||||
if (!from || !to || !to->isMoveable() || !from->isMoveable())
|
||||
{
|
||||
return;
|
||||
@ -412,13 +359,13 @@ void InstanceVersion::move(const int index, const MoveDirection direction)
|
||||
saveCurrentOrder();
|
||||
reapply();
|
||||
}
|
||||
void InstanceVersion::resetOrder()
|
||||
void MinecraftProfile::resetOrder()
|
||||
{
|
||||
QDir(m_instance->instanceRoot()).remove("order.json");
|
||||
reload(m_externalPatches);
|
||||
m_strategy->resetOrder();
|
||||
reload();
|
||||
}
|
||||
|
||||
void InstanceVersion::reapply(const bool alreadyReseting)
|
||||
void MinecraftProfile::reapply()
|
||||
{
|
||||
clear();
|
||||
for(auto file: VersionPatches)
|
||||
@ -428,7 +375,7 @@ void InstanceVersion::reapply(const bool alreadyReseting)
|
||||
finalize();
|
||||
}
|
||||
|
||||
void InstanceVersion::finalize()
|
||||
void MinecraftProfile::finalize()
|
||||
{
|
||||
// HACK: deny april fools. my head hurts enough already.
|
||||
QDate now = QDate::currentDate();
|
||||
@ -465,78 +412,15 @@ void InstanceVersion::finalize()
|
||||
finalizeArguments(minecraftArguments, processArguments);
|
||||
}
|
||||
|
||||
void InstanceVersion::installJarMods(QStringList selectedFiles)
|
||||
void MinecraftProfile::installJarMods(QStringList selectedFiles)
|
||||
{
|
||||
for(auto filename: selectedFiles)
|
||||
{
|
||||
installJarModByFilename(filename);
|
||||
}
|
||||
m_strategy->installJarMods(selectedFiles);
|
||||
}
|
||||
|
||||
void InstanceVersion::installJarModByFilename(QString filepath)
|
||||
{
|
||||
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
|
||||
if(!ensureFolderPathExists(patchDir))
|
||||
{
|
||||
// THROW...
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ensureFolderPathExists(m_instance->jarModsDir()))
|
||||
{
|
||||
// THROW...
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo sourceInfo(filepath);
|
||||
auto uuid = QUuid::createUuid();
|
||||
QString id = uuid.toString().remove('{').remove('}');
|
||||
QString target_filename = id + ".jar";
|
||||
QString target_id = "org.multimc.jarmod." + id;
|
||||
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
||||
QString finalPath = PathCombine(m_instance->jarModsDir(), target_filename);
|
||||
|
||||
QFileInfo targetInfo(finalPath);
|
||||
if(targetInfo.exists())
|
||||
{
|
||||
// THROW
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
||||
{
|
||||
// THROW
|
||||
return;
|
||||
}
|
||||
|
||||
auto f = std::make_shared<VersionFile>();
|
||||
auto jarMod = std::make_shared<Jarmod>();
|
||||
jarMod->name = target_filename;
|
||||
f->jarMods.append(jarMod);
|
||||
f->name = target_name;
|
||||
f->fileId = target_id;
|
||||
f->order = getFreeOrderNumber();
|
||||
QString patchFileName = PathCombine(patchDir, target_id + ".json");
|
||||
f->filename = patchFileName;
|
||||
|
||||
QFile file(patchFileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Error opening" << file.fileName()
|
||||
<< "for reading:" << file.errorString();
|
||||
return;
|
||||
// THROW
|
||||
}
|
||||
file.write(f->toJson(true).toJson());
|
||||
file.close();
|
||||
int index = VersionPatches.size();
|
||||
beginInsertRows(QModelIndex(), index, index);
|
||||
VersionPatches.append(f);
|
||||
endInsertRows();
|
||||
saveCurrentOrder();
|
||||
}
|
||||
|
||||
int InstanceVersion::getFreeOrderNumber()
|
||||
/*
|
||||
* TODO: get rid of this. Get rid of all order numbers.
|
||||
*/
|
||||
int MinecraftProfile::getFreeOrderNumber()
|
||||
{
|
||||
int largest = 100;
|
||||
// yes, I do realize this is dumb. The order thing itself is dumb. and to be removed next.
|
@ -25,13 +25,22 @@
|
||||
#include "VersionFile.h"
|
||||
#include "JarMod.h"
|
||||
|
||||
class ProfileStrategy;
|
||||
class OneSixInstance;
|
||||
|
||||
class InstanceVersion : public QAbstractListModel
|
||||
class MinecraftProfile : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class ProfileStrategy;
|
||||
|
||||
public:
|
||||
explicit InstanceVersion(OneSixInstance *instance, QObject *parent = 0);
|
||||
explicit MinecraftProfile(ProfileStrategy *strategy);
|
||||
|
||||
/// construct a MinecraftProfile from a single file
|
||||
static std::shared_ptr<MinecraftProfile> fromJson(const QJsonObject &obj);
|
||||
|
||||
void setStrategy(ProfileStrategy * strategy);
|
||||
ProfileStrategy *strategy();
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
@ -39,57 +48,72 @@ public:
|
||||
virtual int columnCount(const QModelIndex &parent) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
|
||||
void reload(const QStringList &external = QStringList());
|
||||
void clear();
|
||||
/// is this version unchanged by the user?
|
||||
bool isVanilla();
|
||||
|
||||
/// remove any customizations on top of whatever 'vanilla' means
|
||||
bool revertToVanilla();
|
||||
|
||||
/// install more jar mods
|
||||
void installJarMods(QStringList selectedFiles);
|
||||
|
||||
/// DEPRECATED, remove ASAP
|
||||
int getFreeOrderNumber();
|
||||
|
||||
/// Can patch file # be removed?
|
||||
bool canRemove(const int index) const;
|
||||
|
||||
QString versionFileId(const int index) const;
|
||||
|
||||
// is this version unmodded vanilla minecraft?
|
||||
bool isVanilla();
|
||||
// remove any customizations on top of vanilla
|
||||
bool revertToVanilla();
|
||||
|
||||
// does this version consist of obsolete files?
|
||||
bool hasDeprecatedVersionFiles();
|
||||
// remove obsolete files
|
||||
bool removeDeprecatedVersionFiles();
|
||||
|
||||
// does this version have an FTB pack patch file?
|
||||
bool hasFtbPack();
|
||||
// remove FTB pack
|
||||
bool removeFtbPack();
|
||||
|
||||
// does this version have any jar mods?
|
||||
bool hasJarMods();
|
||||
void installJarMods(QStringList selectedFiles);
|
||||
void installJarModByFilename(QString filepath);
|
||||
|
||||
enum MoveDirection { MoveUp, MoveDown };
|
||||
/// move patch file # up or down the list
|
||||
void move(const int index, const MoveDirection direction);
|
||||
void resetOrder();
|
||||
|
||||
// clears and reapplies all version files
|
||||
void reapply(const bool alreadyReseting = false);
|
||||
void finalize();
|
||||
|
||||
public
|
||||
slots:
|
||||
/// remove patch file # - including files/records
|
||||
bool remove(const int index);
|
||||
|
||||
/// remove patch file by id - including files/records
|
||||
bool remove(const QString id);
|
||||
|
||||
void resetOrder();
|
||||
|
||||
/// reload all profile patches from storage, clear the profile and apply the patches
|
||||
void reload();
|
||||
|
||||
/// clear the profile
|
||||
void clear();
|
||||
|
||||
/// apply the patches
|
||||
void reapply();
|
||||
|
||||
/// do a finalization step (should always be done after applying all patches to profile)
|
||||
void finalize();
|
||||
|
||||
public:
|
||||
/// get all java libraries that belong to the classpath
|
||||
QList<std::shared_ptr<OneSixLibrary>> getActiveNormalLibs();
|
||||
|
||||
/// get all native libraries that need to be available to the process
|
||||
QList<std::shared_ptr<OneSixLibrary>> getActiveNativeLibs();
|
||||
|
||||
static std::shared_ptr<InstanceVersion> fromJson(const QJsonObject &obj);
|
||||
/// get file ID of the patch file at #
|
||||
QString versionFileId(const int index) const;
|
||||
|
||||
private:
|
||||
bool preremove(VersionPatchPtr patch);
|
||||
|
||||
// data members
|
||||
public:
|
||||
/// get the profile patch by id
|
||||
ProfilePatchPtr versionPatch(const QString &id);
|
||||
|
||||
/// get the profile patch by index
|
||||
ProfilePatchPtr versionPatch(int index);
|
||||
|
||||
/// save the current patch order
|
||||
void saveCurrentOrder() const;
|
||||
|
||||
public: /* only use in ProfileStrategy */
|
||||
/// Remove all the patches
|
||||
void clearPatches();
|
||||
|
||||
/// Add the patch object to the internal list of patches
|
||||
void appendPatch(ProfilePatchPtr patch);
|
||||
|
||||
public: /* data */
|
||||
/// the ID - determines which jar to use! ACTUALLY IMPORTANT!
|
||||
QString id;
|
||||
|
||||
@ -138,7 +162,7 @@ public:
|
||||
* The applet class, for some very old minecraft releases
|
||||
*/
|
||||
QString appletClass;
|
||||
|
||||
|
||||
/// the list of libs - both active and inactive, native and java
|
||||
QList<OneSixLibraryPtr> libraries;
|
||||
|
||||
@ -171,14 +195,7 @@ public:
|
||||
}
|
||||
*/
|
||||
// QList<Rule> rules;
|
||||
|
||||
QList<VersionPatchPtr> VersionPatches;
|
||||
VersionPatchPtr versionPatch(const QString &id);
|
||||
VersionPatchPtr versionPatch(int index);
|
||||
|
||||
private:
|
||||
QStringList m_externalPatches;
|
||||
OneSixInstance *m_instance;
|
||||
void saveCurrentOrder() const;
|
||||
int getFreeOrderNumber();
|
||||
QList<ProfilePatchPtr> VersionPatches;
|
||||
ProfileStrategy *m_strategy = nullptr;
|
||||
};
|
@ -1,7 +1,8 @@
|
||||
#include "MinecraftVersion.h"
|
||||
#include "InstanceVersion.h"
|
||||
#include "MinecraftProfile.h"
|
||||
#include "VersionBuildError.h"
|
||||
#include "VersionBuilder.h"
|
||||
#include "ProfileUtils.h"
|
||||
#include "MultiMC.h"
|
||||
#include "logic/settings/SettingsObject.h"
|
||||
|
||||
@ -56,15 +57,20 @@ bool MinecraftVersion::isMinecraftVersion()
|
||||
|
||||
// 1. assume the local file is good. load, check. If it's good, apply.
|
||||
// 2. if discrepancies are found, fall out and fail (impossible to apply incomplete version).
|
||||
void MinecraftVersion::applyFileTo(InstanceVersion *version)
|
||||
void MinecraftVersion::applyFileTo(MinecraftProfile *version)
|
||||
{
|
||||
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
|
||||
|
||||
auto versionObj = VersionBuilder::parseBinaryJsonFile(versionFile);
|
||||
versionObj->applyTo(version);
|
||||
getVersionFile()->applyTo(version);
|
||||
}
|
||||
|
||||
void MinecraftVersion::applyTo(InstanceVersion *version)
|
||||
VersionFilePtr MinecraftVersion::getVersionFile()
|
||||
{
|
||||
QFileInfo versionFile(QString("versions/%1/%1.dat").arg(m_descriptor));
|
||||
|
||||
return ProfileUtils::parseBinaryJsonFile(versionFile);
|
||||
}
|
||||
|
||||
|
||||
void MinecraftVersion::applyTo(MinecraftProfile *version)
|
||||
{
|
||||
// do we have this one cached?
|
||||
if (m_versionSource == Local)
|
||||
|
@ -20,15 +20,15 @@
|
||||
#include <QDateTime>
|
||||
|
||||
#include "logic/BaseVersion.h"
|
||||
#include "VersionPatch.h"
|
||||
#include "ProfilePatch.h"
|
||||
#include "VersionFile.h"
|
||||
#include "VersionSource.h"
|
||||
|
||||
class InstanceVersion;
|
||||
class MinecraftProfile;
|
||||
class MinecraftVersion;
|
||||
typedef std::shared_ptr<MinecraftVersion> MinecraftVersionPtr;
|
||||
|
||||
class MinecraftVersion : public BaseVersion, public VersionPatch
|
||||
class MinecraftVersion : public BaseVersion, public ProfilePatch
|
||||
{
|
||||
public: /* methods */
|
||||
bool usesLegacyLauncher();
|
||||
@ -37,9 +37,9 @@ public: /* methods */
|
||||
virtual QString typeString() const override;
|
||||
virtual bool hasJarMods() override;
|
||||
virtual bool isMinecraftVersion() override;
|
||||
virtual void applyTo(InstanceVersion *version) override;
|
||||
virtual int getOrder();
|
||||
virtual void setOrder(int order);
|
||||
virtual void applyTo(MinecraftProfile *version) override;
|
||||
virtual int getOrder() override;
|
||||
virtual void setOrder(int order) override;
|
||||
virtual QList<JarmodPtr> getJarMods() override;
|
||||
virtual QString getPatchID() override;
|
||||
virtual QString getPatchVersion() override;
|
||||
@ -47,10 +47,12 @@ public: /* methods */
|
||||
virtual QString getPatchFilename() override;
|
||||
bool needsUpdate();
|
||||
bool hasUpdate();
|
||||
virtual bool isCustom();
|
||||
virtual bool isCustom() override;
|
||||
|
||||
VersionFilePtr getVersionFile();
|
||||
|
||||
private: /* methods */
|
||||
void applyFileTo(InstanceVersion *version);
|
||||
void applyFileTo(MinecraftProfile *version);
|
||||
|
||||
public: /* data */
|
||||
/// The URL that this version will be downloaded from. maybe.
|
||||
@ -92,7 +94,7 @@ public: /* data */
|
||||
|
||||
/// order of this file... default = -2
|
||||
int order = -2;
|
||||
|
||||
|
||||
/// an update available from Mojang
|
||||
MinecraftVersionPtr upstreamUpdate;
|
||||
};
|
||||
|
@ -25,12 +25,53 @@
|
||||
#include "logic/net/URLConstants.h"
|
||||
|
||||
#include "ParseUtils.h"
|
||||
#include "ProfileUtils.h"
|
||||
#include "VersionBuilder.h"
|
||||
#include <logic/VersionFilterData.h>
|
||||
#include "VersionFilterData.h"
|
||||
|
||||
#include <pathutils.h>
|
||||
|
||||
static const char * localVersionCache = "versions/versions.dat";
|
||||
|
||||
class MCVListLoadTask : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MCVListLoadTask(MinecraftVersionList *vlist);
|
||||
virtual ~MCVListLoadTask() override{};
|
||||
|
||||
virtual void executeTask() override;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void list_downloaded();
|
||||
|
||||
protected:
|
||||
QNetworkReply *vlistReply;
|
||||
MinecraftVersionList *m_list;
|
||||
MinecraftVersion *m_currentStable;
|
||||
};
|
||||
|
||||
class MCVListVersionUpdateTask : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MCVListVersionUpdateTask(MinecraftVersionList *vlist, QString updatedVersion);
|
||||
virtual ~MCVListVersionUpdateTask() override{};
|
||||
virtual void executeTask() override;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void json_downloaded();
|
||||
|
||||
protected:
|
||||
NetJobPtr specificVersionDownloadJob;
|
||||
QString versionToUpdate;
|
||||
MinecraftVersionList *m_list;
|
||||
};
|
||||
|
||||
class ListLoadError : public MMCError
|
||||
{
|
||||
public:
|
||||
@ -442,21 +483,9 @@ void MCVListVersionUpdateTask::json_downloaded()
|
||||
emitFailed(tr("Couldn't process version file: %1").arg(e.cause()));
|
||||
return;
|
||||
}
|
||||
QList<RawLibraryPtr> filteredLibs;
|
||||
QList<RawLibraryPtr> lwjglLibs;
|
||||
|
||||
for (auto lib : file->overwriteLibs)
|
||||
{
|
||||
if (g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
|
||||
{
|
||||
lwjglLibs.append(lib);
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredLibs.append(lib);
|
||||
}
|
||||
}
|
||||
file->overwriteLibs = filteredLibs;
|
||||
// Strip LWJGL from the version file. We use our own.
|
||||
ProfileUtils::removeLwjglFromPatch(file);
|
||||
|
||||
// TODO: recognize and add LWJGL versions here.
|
||||
|
||||
@ -523,7 +552,7 @@ void MinecraftVersionList::saveCachedList()
|
||||
entriesArr.append(entryObj);
|
||||
}
|
||||
toplevel.insert("versions", entriesArr);
|
||||
|
||||
|
||||
{
|
||||
bool someLatest = false;
|
||||
QJsonObject latestObj;
|
||||
@ -542,7 +571,7 @@ void MinecraftVersionList::saveCachedList()
|
||||
toplevel.insert("latest", latestObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QJsonDocument doc(toplevel);
|
||||
QByteArray jsonData = doc.toBinaryData();
|
||||
qint64 result = tfile.write(jsonData);
|
||||
@ -593,3 +622,5 @@ void MinecraftVersionList::finalizeUpdate(QString version)
|
||||
|
||||
saveCachedList();
|
||||
}
|
||||
|
||||
#include "MinecraftVersionList.moc"
|
@ -26,7 +26,6 @@
|
||||
|
||||
class MCVListLoadTask;
|
||||
class MCVListVersionUpdateTask;
|
||||
class QNetworkReply;
|
||||
|
||||
class MinecraftVersionList : public BaseVersionList
|
||||
{
|
||||
@ -67,42 +66,3 @@ protected
|
||||
slots:
|
||||
virtual void updateListData(QList<BaseVersionPtr> versions);
|
||||
};
|
||||
|
||||
class MCVListLoadTask : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MCVListLoadTask(MinecraftVersionList *vlist);
|
||||
virtual ~MCVListLoadTask() override{};
|
||||
|
||||
virtual void executeTask() override;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void list_downloaded();
|
||||
|
||||
protected:
|
||||
QNetworkReply *vlistReply;
|
||||
MinecraftVersionList *m_list;
|
||||
MinecraftVersion *m_currentStable;
|
||||
};
|
||||
|
||||
class MCVListVersionUpdateTask : public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MCVListVersionUpdateTask(MinecraftVersionList *vlist, QString updatedVersion);
|
||||
virtual ~MCVListVersionUpdateTask() override{};
|
||||
virtual void executeTask() override;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void json_downloaded();
|
||||
|
||||
protected:
|
||||
NetJobPtr specificVersionDownloadJob;
|
||||
QString versionToUpdate;
|
||||
MinecraftVersionList *m_list;
|
||||
};
|
||||
|
24
logic/minecraft/NullProfileStrategy.h
Normal file
24
logic/minecraft/NullProfileStrategy.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "ProfileStrategy.h"
|
||||
|
||||
class NullProfileStrategy: public ProfileStrategy
|
||||
{
|
||||
virtual bool installJarMods(QStringList filepaths)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual void load() {};
|
||||
virtual bool removePatch(ProfilePatchPtr jarMod)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool resetOrder()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool saveOrder(ProfileUtils::PatchOrder order)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
@ -18,10 +18,6 @@
|
||||
#include "OneSixLibrary.h"
|
||||
#include "OneSixRule.h"
|
||||
#include "OpSys.h"
|
||||
#include "logic/net/URLConstants.h"
|
||||
#include <pathutils.h>
|
||||
#include <JlCompress.h>
|
||||
#include "logger/QsLog.h"
|
||||
|
||||
OneSixLibrary::OneSixLibrary(RawLibraryPtr base)
|
||||
{
|
||||
|
270
logic/minecraft/OneSixProfileStrategy.cpp
Normal file
270
logic/minecraft/OneSixProfileStrategy.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
#include "logic/minecraft/OneSixProfileStrategy.h"
|
||||
#include "logic/minecraft/VersionBuildError.h"
|
||||
#include "logic/OneSixInstance.h"
|
||||
#include "logic/minecraft/MinecraftVersionList.h"
|
||||
|
||||
#include "MultiMC.h"
|
||||
|
||||
#include <pathutils.h>
|
||||
#include <QDir>
|
||||
#include <QUuid>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
|
||||
OneSixProfileStrategy::OneSixProfileStrategy(OneSixInstance* instance)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
|
||||
void OneSixProfileStrategy::upgradeDeprecatedFiles()
|
||||
{
|
||||
auto versionJsonPath = PathCombine(m_instance->instanceRoot(), "version.json");
|
||||
auto customJsonPath = PathCombine(m_instance->instanceRoot(), "custom.json");
|
||||
auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
|
||||
|
||||
// convert old crap.
|
||||
if(QFile::exists(customJsonPath))
|
||||
{
|
||||
if(!ensureFilePathExists(mcJson))
|
||||
{
|
||||
// WHAT DO???
|
||||
}
|
||||
if(!QFile::rename(customJsonPath, mcJson))
|
||||
{
|
||||
// WHAT DO???
|
||||
}
|
||||
if(QFile::exists(versionJsonPath))
|
||||
{
|
||||
if(!QFile::remove(versionJsonPath))
|
||||
{
|
||||
// WHAT DO???
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(QFile::exists(versionJsonPath))
|
||||
{
|
||||
if(!ensureFilePathExists(mcJson))
|
||||
{
|
||||
// WHAT DO???
|
||||
}
|
||||
if(!QFile::rename(versionJsonPath, mcJson))
|
||||
{
|
||||
// WHAT DO???
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OneSixProfileStrategy::loadDefaultBuiltinPatches()
|
||||
{
|
||||
auto mcJson = PathCombine(m_instance->instanceRoot(), "patches" , "net.minecraft.json");
|
||||
// load up the base minecraft patch
|
||||
ProfilePatchPtr minecraftPatch;
|
||||
if(QFile::exists(mcJson))
|
||||
{
|
||||
auto file = ProfileUtils::parseJsonFile(QFileInfo(mcJson), false);
|
||||
file->fileId = "net.minecraft";
|
||||
file->name = "Minecraft";
|
||||
if(file->version.isEmpty())
|
||||
{
|
||||
file->version = m_instance->intendedVersionId();
|
||||
}
|
||||
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto minecraftList = MMC->minecraftlist();
|
||||
auto mcversion = minecraftList->findVersion(m_instance->intendedVersionId());
|
||||
minecraftPatch = std::dynamic_pointer_cast<ProfilePatch>(mcversion);
|
||||
}
|
||||
if (!minecraftPatch)
|
||||
{
|
||||
throw VersionIncomplete("net.minecraft");
|
||||
}
|
||||
minecraftPatch->setOrder(-2);
|
||||
profile->appendPatch(minecraftPatch);
|
||||
|
||||
|
||||
// TODO: this is obviously fake.
|
||||
QResource LWJGL(":/versions/LWJGL/2.9.1.json");
|
||||
auto lwjgl = ProfileUtils::parseJsonFile(LWJGL.absoluteFilePath(), false, false);
|
||||
auto lwjglPatch = std::dynamic_pointer_cast<ProfilePatch>(lwjgl);
|
||||
if (!lwjglPatch)
|
||||
{
|
||||
throw VersionIncomplete("org.lwjgl");
|
||||
}
|
||||
lwjglPatch->setOrder(-1);
|
||||
lwjgl->setVanilla(true);
|
||||
profile->appendPatch(lwjglPatch);
|
||||
}
|
||||
|
||||
void OneSixProfileStrategy::loadUserPatches()
|
||||
{
|
||||
// load all patches, put into map for ordering, apply in the right order
|
||||
ProfileUtils::PatchOrder userOrder;
|
||||
ProfileUtils::readOverrideOrders(PathCombine(m_instance->instanceRoot(), "order.json"), userOrder);
|
||||
QDir patches(PathCombine(m_instance->instanceRoot(),"patches"));
|
||||
|
||||
// first, load things by sort order.
|
||||
for (auto id : userOrder)
|
||||
{
|
||||
// ignore builtins
|
||||
if (id == "net.minecraft")
|
||||
continue;
|
||||
if (id == "org.lwjgl")
|
||||
continue;
|
||||
// parse the file
|
||||
QString filename = patches.absoluteFilePath(id + ".json");
|
||||
QFileInfo finfo(filename);
|
||||
if(!finfo.exists())
|
||||
{
|
||||
QLOG_INFO() << "Patch file " << filename << " was deleted by external means...";
|
||||
continue;
|
||||
}
|
||||
QLOG_INFO() << "Reading" << filename << "by user order";
|
||||
auto file = ProfileUtils::parseJsonFile(finfo, false);
|
||||
// sanity check. prevent tampering with files.
|
||||
if (file->fileId != id)
|
||||
{
|
||||
throw VersionBuildError(
|
||||
QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId));
|
||||
}
|
||||
profile->appendPatch(file);
|
||||
}
|
||||
// now load the rest by internal preference.
|
||||
QMap<int, QPair<QString, VersionFilePtr>> files;
|
||||
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
||||
{
|
||||
// parse the file
|
||||
QLOG_INFO() << "Reading" << info.fileName();
|
||||
auto file = ProfileUtils::parseJsonFile(info, true);
|
||||
// ignore builtins
|
||||
if (file->fileId == "net.minecraft")
|
||||
continue;
|
||||
if (file->fileId == "org.lwjgl")
|
||||
continue;
|
||||
// do not load what we already loaded in the first pass
|
||||
if (userOrder.contains(file->fileId))
|
||||
continue;
|
||||
if (files.contains(file->order))
|
||||
{
|
||||
// FIXME: do not throw?
|
||||
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];
|
||||
profile->appendPatch(filePair.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OneSixProfileStrategy::load()
|
||||
{
|
||||
profile->clearPatches();
|
||||
|
||||
upgradeDeprecatedFiles();
|
||||
loadDefaultBuiltinPatches();
|
||||
loadUserPatches();
|
||||
|
||||
profile->finalize();
|
||||
}
|
||||
|
||||
bool OneSixProfileStrategy::saveOrder(ProfileUtils::PatchOrder order)
|
||||
{
|
||||
return ProfileUtils::writeOverrideOrders(PathCombine(m_instance->instanceRoot(), "order.json"), order);
|
||||
}
|
||||
|
||||
bool OneSixProfileStrategy::resetOrder()
|
||||
{
|
||||
return QDir(m_instance->instanceRoot()).remove("order.json");
|
||||
}
|
||||
|
||||
bool OneSixProfileStrategy::removePatch(ProfilePatchPtr patch)
|
||||
{
|
||||
bool ok = true;
|
||||
// first, remove the patch file. this ensures it's not used anymore
|
||||
auto fileName = patch->getPatchFilename();
|
||||
|
||||
|
||||
auto preRemoveJarMod = [&](JarmodPtr jarMod) -> bool
|
||||
{
|
||||
QString fullpath = PathCombine(m_instance->jarModsDir(), jarMod->name);
|
||||
QFileInfo finfo (fullpath);
|
||||
if(finfo.exists())
|
||||
{
|
||||
return QFile::remove(fullpath);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
for(auto &jarmod: patch->getJarMods())
|
||||
{
|
||||
ok &= preRemoveJarMod(jarmod);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool OneSixProfileStrategy::installJarMods(QStringList filepaths)
|
||||
{
|
||||
QString patchDir = PathCombine(m_instance->instanceRoot(), "patches");
|
||||
if(!ensureFolderPathExists(patchDir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ensureFolderPathExists(m_instance->jarModsDir()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto filepath:filepaths)
|
||||
{
|
||||
QFileInfo sourceInfo(filepath);
|
||||
auto uuid = QUuid::createUuid();
|
||||
QString id = uuid.toString().remove('{').remove('}');
|
||||
QString target_filename = id + ".jar";
|
||||
QString target_id = "org.multimc.jarmod." + id;
|
||||
QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
|
||||
QString finalPath = PathCombine(m_instance->jarModsDir(), target_filename);
|
||||
|
||||
QFileInfo targetInfo(finalPath);
|
||||
if(targetInfo.exists())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto f = std::make_shared<VersionFile>();
|
||||
auto jarMod = std::make_shared<Jarmod>();
|
||||
jarMod->name = target_filename;
|
||||
f->jarMods.append(jarMod);
|
||||
f->name = target_name;
|
||||
f->fileId = target_id;
|
||||
f->order = profile->getFreeOrderNumber();
|
||||
QString patchFileName = PathCombine(patchDir, target_id + ".json");
|
||||
f->filename = patchFileName;
|
||||
|
||||
QFile file(patchFileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Error opening" << file.fileName()
|
||||
<< "for reading:" << file.errorString();
|
||||
return false;
|
||||
}
|
||||
file.write(f->toJson(true).toJson());
|
||||
file.close();
|
||||
profile->appendPatch(f);
|
||||
}
|
||||
profile->saveCurrentOrder();
|
||||
profile->reapply();
|
||||
return true;
|
||||
}
|
||||
|
24
logic/minecraft/OneSixProfileStrategy.h
Normal file
24
logic/minecraft/OneSixProfileStrategy.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "ProfileStrategy.h"
|
||||
|
||||
class OneSixInstance;
|
||||
|
||||
class OneSixProfileStrategy : public ProfileStrategy
|
||||
{
|
||||
public:
|
||||
OneSixProfileStrategy(OneSixInstance * instance);
|
||||
virtual ~OneSixProfileStrategy() {};
|
||||
virtual void load() override;
|
||||
virtual bool resetOrder() override;
|
||||
virtual bool saveOrder(ProfileUtils::PatchOrder order) override;
|
||||
virtual bool installJarMods(QStringList filepaths) override;
|
||||
virtual bool removePatch(ProfilePatchPtr patch) override;
|
||||
|
||||
protected:
|
||||
void loadDefaultBuiltinPatches();
|
||||
void loadUserPatches();
|
||||
void upgradeDeprecatedFiles();
|
||||
|
||||
protected:
|
||||
OneSixInstance *m_instance;
|
||||
};
|
@ -4,24 +4,24 @@
|
||||
#include <QList>
|
||||
#include "JarMod.h"
|
||||
|
||||
class InstanceVersion;
|
||||
class VersionPatch
|
||||
class MinecraftProfile;
|
||||
class ProfilePatch
|
||||
{
|
||||
public:
|
||||
virtual ~VersionPatch(){};
|
||||
virtual void applyTo(InstanceVersion *version) = 0;
|
||||
|
||||
virtual ~ProfilePatch(){};
|
||||
virtual void applyTo(MinecraftProfile *version) = 0;
|
||||
|
||||
virtual bool isMinecraftVersion() = 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;
|
||||
@ -29,4 +29,4 @@ public:
|
||||
virtual bool isCustom() = 0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<VersionPatch> VersionPatchPtr;
|
||||
typedef std::shared_ptr<ProfilePatch> ProfilePatchPtr;
|
30
logic/minecraft/ProfileStrategy.h
Normal file
30
logic/minecraft/ProfileStrategy.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "ProfileUtils.h"
|
||||
|
||||
class MinecraftProfile;
|
||||
|
||||
class ProfileStrategy
|
||||
{
|
||||
friend class MinecraftProfile;
|
||||
public:
|
||||
virtual ~ProfileStrategy(){};
|
||||
|
||||
/// load the patch files into the profile
|
||||
virtual void load() = 0;
|
||||
|
||||
/// reset the order of patches
|
||||
virtual bool resetOrder() = 0;
|
||||
|
||||
/// save the order of patches, given the order
|
||||
virtual bool saveOrder(ProfileUtils::PatchOrder order) = 0;
|
||||
|
||||
/// install a list of jar mods into the instance
|
||||
virtual bool installJarMods(QStringList filepaths) = 0;
|
||||
|
||||
/// remove any files or records that constitute the version patch
|
||||
virtual bool removePatch(ProfilePatchPtr jarMod) = 0;
|
||||
|
||||
protected:
|
||||
MinecraftProfile *profile;
|
||||
};
|
145
logic/minecraft/ProfileUtils.cpp
Normal file
145
logic/minecraft/ProfileUtils.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "ProfileUtils.h"
|
||||
#include "logic/minecraft/VersionFilterData.h"
|
||||
#include "logic/MMCJson.h"
|
||||
#include "logger/QsLog.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace ProfileUtils
|
||||
{
|
||||
|
||||
static const int currentOrderFileVersion = 1;
|
||||
|
||||
bool writeOverrideOrders(QString path, const PatchOrder &order)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("version", currentOrderFileVersion);
|
||||
QJsonArray orderArray;
|
||||
for(auto str: order)
|
||||
{
|
||||
orderArray.append(str);
|
||||
}
|
||||
obj.insert("order", orderArray);
|
||||
QFile orderFile(path);
|
||||
if (!orderFile.open(QFile::WriteOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||
<< "for writing:" << orderFile.errorString();
|
||||
return false;
|
||||
}
|
||||
orderFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readOverrideOrders(QString path, PatchOrder &order)
|
||||
{
|
||||
QFile orderFile(path);
|
||||
if (!orderFile.exists())
|
||||
{
|
||||
QLOG_WARN() << "Order file doesn't exist. Ignoring.";
|
||||
return false;
|
||||
}
|
||||
if (!orderFile.open(QFile::ReadOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||
<< " for reading:" << orderFile.errorString();
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
return false;
|
||||
}
|
||||
|
||||
// and it's valid JSON
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
return false;
|
||||
}
|
||||
|
||||
// and then read it and process it if all above is true.
|
||||
try
|
||||
{
|
||||
auto obj = MMCJson::ensureObject(doc);
|
||||
// check order file version.
|
||||
auto version = MMCJson::ensureInteger(obj.value("version"), "version");
|
||||
if (version != currentOrderFileVersion)
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
|
||||
.arg(currentOrderFileVersion));
|
||||
}
|
||||
auto orderArray = MMCJson::ensureArray(obj.value("order"));
|
||||
for(auto item: orderArray)
|
||||
{
|
||||
order.append(MMCJson::ensureString(item));
|
||||
}
|
||||
}
|
||||
catch (JSONValidationError &err)
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
order.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB)
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||
.arg(fileInfo.fileName(), file.errorString()));
|
||||
}
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
throw JSONValidationError(
|
||||
QObject::tr("Unable to process the version file %1: %2 at %3.")
|
||||
.arg(fileInfo.fileName(), error.errorString())
|
||||
.arg(error.offset));
|
||||
}
|
||||
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
||||
}
|
||||
|
||||
VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo)
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||
.arg(fileInfo.fileName(), file.errorString()));
|
||||
}
|
||||
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
|
||||
file.close();
|
||||
if (doc.isNull())
|
||||
{
|
||||
file.remove();
|
||||
throw JSONValidationError(
|
||||
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
|
||||
}
|
||||
return VersionFile::fromJson(doc, file.fileName(), false, false);
|
||||
}
|
||||
|
||||
void removeLwjglFromPatch(VersionFilePtr patch)
|
||||
{
|
||||
auto filter = [](QList<RawLibraryPtr>& libs)
|
||||
{
|
||||
QList<RawLibraryPtr> filteredLibs;
|
||||
for (auto lib : libs)
|
||||
{
|
||||
if (!g_VersionFilterData.lwjglWhitelist.contains(lib->artifactPrefix()))
|
||||
{
|
||||
filteredLibs.append(lib);
|
||||
}
|
||||
}
|
||||
libs = filteredLibs;
|
||||
};
|
||||
filter(patch->addLibs);
|
||||
filter(patch->overwriteLibs);
|
||||
}
|
||||
}
|
25
logic/minecraft/ProfileUtils.h
Normal file
25
logic/minecraft/ProfileUtils.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "RawLibrary.h"
|
||||
#include "VersionFile.h"
|
||||
|
||||
namespace ProfileUtils
|
||||
{
|
||||
typedef QStringList PatchOrder;
|
||||
|
||||
/// Read and parse a OneSix format order file
|
||||
bool readOverrideOrders(QString path, PatchOrder &order);
|
||||
|
||||
/// Write a OneSix format order file
|
||||
bool writeOverrideOrders(QString path, const PatchOrder &order);
|
||||
|
||||
|
||||
/// Parse a version file in JSON format
|
||||
VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
|
||||
|
||||
/// Parse a version file in binary JSON format
|
||||
VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
|
||||
|
||||
/// Remove LWJGL from a patch file. This is applied to all Mojang-like profile files.
|
||||
void removeLwjglFromPatch(VersionFilePtr patch);
|
||||
|
||||
}
|
@ -24,15 +24,17 @@
|
||||
#include <QDir>
|
||||
#include <qresource.h>
|
||||
#include <modutils.h>
|
||||
#include <pathutils.h>
|
||||
|
||||
#include "MultiMC.h"
|
||||
#include "logic/minecraft/VersionBuilder.h"
|
||||
#include "logic/minecraft/InstanceVersion.h"
|
||||
#include "logic/minecraft/MinecraftProfile.h"
|
||||
#include "logic/minecraft/OneSixRule.h"
|
||||
#include "logic/minecraft/VersionPatch.h"
|
||||
#include "logic/minecraft/ProfilePatch.h"
|
||||
#include "logic/minecraft/VersionFile.h"
|
||||
#include "VersionBuildError.h"
|
||||
#include "MinecraftVersionList.h"
|
||||
#include "ProfileUtils.h"
|
||||
|
||||
#include "logic/OneSixInstance.h"
|
||||
#include "logic/MMCJson.h"
|
||||
@ -43,17 +45,15 @@ VersionBuilder::VersionBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
void VersionBuilder::build(InstanceVersion *version, OneSixInstance *instance,
|
||||
const QStringList &external)
|
||||
void VersionBuilder::build(MinecraftProfile *version, OneSixInstance *instance)
|
||||
{
|
||||
VersionBuilder builder;
|
||||
builder.m_version = version;
|
||||
builder.m_instance = instance;
|
||||
builder.external_patches = external;
|
||||
builder.buildInternal();
|
||||
}
|
||||
|
||||
void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj)
|
||||
void VersionBuilder::readJsonAndApplyToVersion(MinecraftProfile *version, const QJsonObject &obj)
|
||||
{
|
||||
VersionBuilder builder;
|
||||
builder.m_version = version;
|
||||
@ -61,178 +61,6 @@ void VersionBuilder::readJsonAndApplyToVersion(InstanceVersion *version, const Q
|
||||
builder.readJsonAndApply(obj);
|
||||
}
|
||||
|
||||
void VersionBuilder::buildFromCustomJson()
|
||||
{
|
||||
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);
|
||||
m_version->finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
void VersionBuilder::buildFromVersionJson()
|
||||
{
|
||||
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);
|
||||
|
||||
// load all patches, put into map for ordering, apply in the right order
|
||||
readInstancePatches();
|
||||
|
||||
// some final touches
|
||||
m_version->finalize();
|
||||
}
|
||||
|
||||
void VersionBuilder::readInstancePatches()
|
||||
{
|
||||
PatchOrder userOrder;
|
||||
readOverrideOrders(m_instance, userOrder);
|
||||
QDir patches(instance_root.absoluteFilePath("patches/"));
|
||||
|
||||
// first, load things by sort order.
|
||||
for (auto id : userOrder)
|
||||
{
|
||||
// ignore builtins
|
||||
if (id == "net.minecraft")
|
||||
continue;
|
||||
if (id == "org.lwjgl")
|
||||
continue;
|
||||
// parse the file
|
||||
QString filename = patches.absoluteFilePath(id + ".json");
|
||||
QFileInfo finfo(filename);
|
||||
if(!finfo.exists())
|
||||
{
|
||||
QLOG_INFO() << "Patch file " << filename << " was deleted by external means...";
|
||||
continue;
|
||||
}
|
||||
QLOG_INFO() << "Reading" << filename << "by user order";
|
||||
auto file = parseJsonFile(finfo, false);
|
||||
// sanity check. prevent tampering with files.
|
||||
if (file->fileId != id)
|
||||
{
|
||||
throw VersionBuildError(
|
||||
QObject::tr("load id %1 does not match internal id %2").arg(id, file->fileId));
|
||||
}
|
||||
m_version->VersionPatches.append(file);
|
||||
}
|
||||
// now load the rest by internal preference.
|
||||
QMap<int, QPair<QString, VersionFilePtr>> files;
|
||||
for (auto info : patches.entryInfoList(QStringList() << "*.json", QDir::Files))
|
||||
{
|
||||
// parse the file
|
||||
QLOG_INFO() << "Reading" << info.fileName();
|
||||
auto file = parseJsonFile(info, true);
|
||||
// ignore builtins
|
||||
if (file->fileId == "net.minecraft")
|
||||
continue;
|
||||
if (file->fileId == "org.lwjgl")
|
||||
continue;
|
||||
// do not load what we already loaded in the first pass
|
||||
if (userOrder.contains(file->fileId))
|
||||
continue;
|
||||
if (files.contains(file->order))
|
||||
{
|
||||
// FIXME: do not throw?
|
||||
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);
|
||||
|
||||
// TODO: this is obviously fake.
|
||||
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);
|
||||
lwjgl->setVanilla(true);
|
||||
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)
|
||||
{
|
||||
m_version->clear();
|
||||
@ -240,121 +68,17 @@ void VersionBuilder::readJsonAndApply(const QJsonObject &obj)
|
||||
auto file = VersionFile::fromJson(QJsonDocument(obj), QString(), false);
|
||||
|
||||
file->applyTo(m_version);
|
||||
m_version->VersionPatches.append(file);
|
||||
m_version->appendPatch(file);
|
||||
}
|
||||
|
||||
VersionFilePtr VersionBuilder::parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder,
|
||||
bool isFTB)
|
||||
|
||||
void VersionBuilder::readInstancePatches()
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||
.arg(fileInfo.fileName(), file.errorString()));
|
||||
}
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
throw JSONValidationError(
|
||||
QObject::tr("Unable to process the version file %1: %2 at %3.")
|
||||
.arg(fileInfo.fileName(), error.errorString())
|
||||
.arg(error.offset));
|
||||
}
|
||||
return VersionFile::fromJson(doc, file.fileName(), requireOrder, isFTB);
|
||||
|
||||
}
|
||||
|
||||
VersionFilePtr VersionBuilder::parseBinaryJsonFile(const QFileInfo &fileInfo)
|
||||
void VersionBuilder::buildInternal()
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Unable to open the version file %1: %2.")
|
||||
.arg(fileInfo.fileName(), file.errorString()));
|
||||
}
|
||||
QJsonDocument doc = QJsonDocument::fromBinaryData(file.readAll());
|
||||
file.close();
|
||||
if (doc.isNull())
|
||||
{
|
||||
file.remove();
|
||||
throw JSONValidationError(
|
||||
QObject::tr("Unable to process the version file %1.").arg(fileInfo.fileName()));
|
||||
}
|
||||
return VersionFile::fromJson(doc, file.fileName(), false, false);
|
||||
|
||||
}
|
||||
|
||||
static const int currentOrderFileVersion = 1;
|
||||
|
||||
bool VersionBuilder::readOverrideOrders(OneSixInstance *instance, PatchOrder &order)
|
||||
{
|
||||
QFile orderFile(instance->instanceRoot() + "/order.json");
|
||||
if (!orderFile.exists())
|
||||
{
|
||||
QLOG_WARN() << "Order file doesn't exist. Ignoring.";
|
||||
return false;
|
||||
}
|
||||
if (!orderFile.open(QFile::ReadOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||
<< " for reading:" << orderFile.errorString();
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
return false;
|
||||
}
|
||||
|
||||
// and it's valid JSON
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(orderFile.readAll(), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ":" << error.errorString();
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
return false;
|
||||
}
|
||||
|
||||
// and then read it and process it if all above is true.
|
||||
try
|
||||
{
|
||||
auto obj = MMCJson::ensureObject(doc);
|
||||
// check order file version.
|
||||
auto version = MMCJson::ensureInteger(obj.value("version"), "version");
|
||||
if (version != currentOrderFileVersion)
|
||||
{
|
||||
throw JSONValidationError(QObject::tr("Invalid order file version, expected %1")
|
||||
.arg(currentOrderFileVersion));
|
||||
}
|
||||
auto orderArray = MMCJson::ensureArray(obj.value("order"));
|
||||
for(auto item: orderArray)
|
||||
{
|
||||
order.append(MMCJson::ensureString(item));
|
||||
}
|
||||
}
|
||||
catch (JSONValidationError &err)
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't parse" << orderFile.fileName() << ": bad file format";
|
||||
QLOG_WARN() << "Ignoring overriden order";
|
||||
order.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VersionBuilder::writeOverrideOrders(OneSixInstance *instance, const PatchOrder &order)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("version", currentOrderFileVersion);
|
||||
QJsonArray orderArray;
|
||||
for(auto str: order)
|
||||
{
|
||||
orderArray.append(str);
|
||||
}
|
||||
obj.insert("order", orderArray);
|
||||
QFile orderFile(instance->instanceRoot() + "/order.json");
|
||||
if (!orderFile.open(QFile::WriteOnly))
|
||||
{
|
||||
QLOG_ERROR() << "Couldn't open" << orderFile.fileName()
|
||||
<< "for writing:" << orderFile.errorString();
|
||||
return false;
|
||||
}
|
||||
orderFile.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||
return true;
|
||||
}
|
||||
|
@ -19,38 +19,25 @@
|
||||
#include <QMap>
|
||||
#include "VersionFile.h"
|
||||
|
||||
class InstanceVersion;
|
||||
class MinecraftProfile;
|
||||
class OneSixInstance;
|
||||
class QJsonObject;
|
||||
class QFileInfo;
|
||||
|
||||
typedef QStringList PatchOrder;
|
||||
|
||||
class VersionBuilder
|
||||
{
|
||||
VersionBuilder();
|
||||
public:
|
||||
static void build(InstanceVersion *version, OneSixInstance *instance, const QStringList &external);
|
||||
static void readJsonAndApplyToVersion(InstanceVersion *version, const QJsonObject &obj);
|
||||
static VersionFilePtr parseJsonFile(const QFileInfo &fileInfo, const bool requireOrder, bool isFTB = false);
|
||||
static VersionFilePtr parseBinaryJsonFile(const QFileInfo &fileInfo);
|
||||
|
||||
bool readOverrideOrders(OneSixInstance *instance, PatchOrder &order);
|
||||
static bool writeOverrideOrders(OneSixInstance *instance, const PatchOrder &order);
|
||||
static void build(MinecraftProfile *version, OneSixInstance *instance);
|
||||
static void readJsonAndApplyToVersion(MinecraftProfile *version, const QJsonObject &obj);
|
||||
|
||||
private:
|
||||
InstanceVersion *m_version;
|
||||
MinecraftProfile *m_version;
|
||||
OneSixInstance *m_instance;
|
||||
QStringList external_patches;
|
||||
QDir instance_root;
|
||||
|
||||
|
||||
void buildInternal();
|
||||
void buildFromExternalPatches();
|
||||
void buildFromCustomJson();
|
||||
void buildFromVersionJson();
|
||||
void buildFromMultilayer();
|
||||
|
||||
|
||||
void readInstancePatches();
|
||||
|
||||
|
||||
void readJsonAndApply(const QJsonObject &obj);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "logic/minecraft/VersionFile.h"
|
||||
#include "logic/minecraft/OneSixLibrary.h"
|
||||
#include "logic/minecraft/InstanceVersion.h"
|
||||
#include "logic/minecraft/MinecraftProfile.h"
|
||||
#include "logic/minecraft/JarMod.h"
|
||||
#include "ParseUtils.h"
|
||||
|
||||
@ -256,8 +256,7 @@ QJsonDocument VersionFile::toJson(bool saveOrder)
|
||||
|
||||
bool VersionFile::isMinecraftVersion()
|
||||
{
|
||||
return (fileId == "org.multimc.version.json") || (fileId == "net.minecraft") ||
|
||||
(fileId == "org.multimc.custom.json");
|
||||
return fileId == "net.minecraft";
|
||||
}
|
||||
|
||||
bool VersionFile::hasJarMods()
|
||||
@ -265,7 +264,7 @@ bool VersionFile::hasJarMods()
|
||||
return !jarMods.isEmpty();
|
||||
}
|
||||
|
||||
void VersionFile::applyTo(InstanceVersion *version)
|
||||
void VersionFile::applyTo(MinecraftProfile *version)
|
||||
{
|
||||
if (minimumLauncherVersion != -1)
|
||||
{
|
||||
|
@ -6,23 +6,23 @@
|
||||
#include <memory>
|
||||
#include "logic/minecraft/OpSys.h"
|
||||
#include "logic/minecraft/OneSixRule.h"
|
||||
#include "VersionPatch.h"
|
||||
#include "ProfilePatch.h"
|
||||
#include "MMCError.h"
|
||||
#include "OneSixLibrary.h"
|
||||
#include "JarMod.h"
|
||||
|
||||
class InstanceVersion;
|
||||
class MinecraftProfile;
|
||||
class VersionFile;
|
||||
|
||||
typedef std::shared_ptr<VersionFile> VersionFilePtr;
|
||||
class VersionFile : public VersionPatch
|
||||
class VersionFile : public ProfilePatch
|
||||
{
|
||||
public: /* methods */
|
||||
static VersionFilePtr fromJson(const QJsonDocument &doc, const QString &filename,
|
||||
const bool requireOrder, const bool isFTB = false);
|
||||
QJsonDocument toJson(bool saveOrder);
|
||||
|
||||
virtual void applyTo(InstanceVersion *version) override;
|
||||
virtual void applyTo(MinecraftProfile *version) override;
|
||||
virtual bool isMinecraftVersion() override;
|
||||
virtual bool hasJarMods() override;
|
||||
virtual int getOrder() override
|
||||
|
72
logic/minecraft/VersionFilterData.cpp
Normal file
72
logic/minecraft/VersionFilterData.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "VersionFilterData.h"
|
||||
#include "ParseUtils.h"
|
||||
|
||||
VersionFilterData g_VersionFilterData = VersionFilterData();
|
||||
|
||||
VersionFilterData::VersionFilterData()
|
||||
{
|
||||
// 1.3.*
|
||||
auto libs13 =
|
||||
QList<FMLlib>{{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
|
||||
{"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
|
||||
{"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false}};
|
||||
|
||||
fmlLibsMapping["1.3.2"] = libs13;
|
||||
|
||||
// 1.4.*
|
||||
auto libs14 = QList<FMLlib>{
|
||||
{"argo-2.25.jar", "bb672829fde76cb163004752b86b0484bd0a7f4b", false},
|
||||
{"guava-12.0.1.jar", "b8e78b9af7bf45900e14c6f958486b6ca682195f", false},
|
||||
{"asm-all-4.0.jar", "98308890597acb64047f7e896638e0d98753ae82", false},
|
||||
{"bcprov-jdk15on-147.jar", "b6f5d9926b0afbde9f4dbe3db88c5247be7794bb", false}};
|
||||
|
||||
fmlLibsMapping["1.4"] = libs14;
|
||||
fmlLibsMapping["1.4.1"] = libs14;
|
||||
fmlLibsMapping["1.4.2"] = libs14;
|
||||
fmlLibsMapping["1.4.3"] = libs14;
|
||||
fmlLibsMapping["1.4.4"] = libs14;
|
||||
fmlLibsMapping["1.4.5"] = libs14;
|
||||
fmlLibsMapping["1.4.6"] = libs14;
|
||||
fmlLibsMapping["1.4.7"] = libs14;
|
||||
|
||||
// 1.5
|
||||
fmlLibsMapping["1.5"] = QList<FMLlib>{
|
||||
{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
|
||||
{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
|
||||
{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
|
||||
{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
|
||||
{"deobfuscation_data_1.5.zip", "5f7c142d53776f16304c0bbe10542014abad6af8", false},
|
||||
{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
|
||||
|
||||
// 1.5.1
|
||||
fmlLibsMapping["1.5.1"] = QList<FMLlib>{
|
||||
{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
|
||||
{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
|
||||
{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
|
||||
{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
|
||||
{"deobfuscation_data_1.5.1.zip", "22e221a0d89516c1f721d6cab056a7e37471d0a6", false},
|
||||
{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
|
||||
|
||||
// 1.5.2
|
||||
fmlLibsMapping["1.5.2"] = QList<FMLlib>{
|
||||
{"argo-small-3.2.jar", "58912ea2858d168c50781f956fa5b59f0f7c6b51", false},
|
||||
{"guava-14.0-rc3.jar", "931ae21fa8014c3ce686aaa621eae565fefb1a6a", false},
|
||||
{"asm-all-4.1.jar", "054986e962b88d8660ae4566475658469595ef58", false},
|
||||
{"bcprov-jdk15on-148.jar", "960dea7c9181ba0b17e8bab0c06a43f0a5f04e65", true},
|
||||
{"deobfuscation_data_1.5.2.zip", "446e55cd986582c70fcf12cb27bc00114c5adfd9", false},
|
||||
{"scala-library.jar", "458d046151ad179c85429ed7420ffb1eaf6ddf85", true}};
|
||||
|
||||
// don't use installers for those.
|
||||
forgeInstallerBlacklist = QSet<QString>({"1.5.2"});
|
||||
// these won't show up in version lists because they are extremely bad and dangerous
|
||||
legacyBlacklist = QSet<QString>({"rd-160052"});
|
||||
/*
|
||||
* nothing older than this will be accepted from Mojang servers
|
||||
* (these versions need to be tested by us first)
|
||||
*/
|
||||
legacyCutoffDate = timeFromS3Time("2013-06-25T15:08:56+02:00");
|
||||
lwjglWhitelist =
|
||||
QSet<QString>{"net.java.jinput:jinput", "net.java.jinput:jinput-platform",
|
||||
"net.java.jutils:jutils", "org.lwjgl.lwjgl:lwjgl",
|
||||
"org.lwjgl.lwjgl:lwjgl_util", "org.lwjgl.lwjgl:lwjgl-platform"};
|
||||
}
|
28
logic/minecraft/VersionFilterData.h
Normal file
28
logic/minecraft/VersionFilterData.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
#include <QDateTime>
|
||||
|
||||
struct FMLlib
|
||||
{
|
||||
QString filename;
|
||||
QString checksum;
|
||||
bool ours;
|
||||
};
|
||||
|
||||
struct VersionFilterData
|
||||
{
|
||||
VersionFilterData();
|
||||
// mapping between minecraft versions and FML libraries required
|
||||
QMap<QString, QList<FMLlib>> fmlLibsMapping;
|
||||
// set of minecraft versions for which using forge installers is blacklisted
|
||||
QSet<QString> forgeInstallerBlacklist;
|
||||
// set of 'legacy' versions that will not show up in the version lists.
|
||||
QSet<QString> legacyBlacklist;
|
||||
// no new versions below this date will be accepted from Mojang servers
|
||||
QDateTime legacyCutoffDate;
|
||||
// Libraries that belong to LWJGL
|
||||
QSet<QString> lwjglWhitelist;
|
||||
};
|
||||
extern VersionFilterData g_VersionFilterData;
|
Reference in New Issue
Block a user