mirror of
https://github.com/UltimMC/Launcher.git
synced 2025-12-26 02:25:03 +00:00
@@ -451,6 +451,13 @@ set(FLAME_SOURCES
|
||||
modplatform/flame/FileResolvingTask.cpp
|
||||
)
|
||||
|
||||
set(MODPACKSCH_SOURCES
|
||||
modplatform/modpacksch/FTBPackInstallTask.h
|
||||
modplatform/modpacksch/FTBPackInstallTask.cpp
|
||||
modplatform/modpacksch/FTBPackManifest.h
|
||||
modplatform/modpacksch/FTBPackManifest.cpp
|
||||
)
|
||||
|
||||
add_unit_test(Index
|
||||
SOURCES meta/Index_test.cpp
|
||||
LIBS MultiMC_logic
|
||||
@@ -481,6 +488,7 @@ set(LOGIC_SOURCES
|
||||
${ICONS_SOURCES}
|
||||
${FTB_SOURCES}
|
||||
${FLAME_SOURCES}
|
||||
${MODPACKSCH_SOURCES}
|
||||
)
|
||||
|
||||
add_library(MultiMC_logic SHARED ${LOGIC_SOURCES})
|
||||
|
||||
@@ -97,6 +97,7 @@ void Env::initHttpMetaCache()
|
||||
m_metacache->addBase("liteloader", QDir("mods/liteloader").absolutePath());
|
||||
m_metacache->addBase("general", QDir("cache").absolutePath());
|
||||
m_metacache->addBase("FTBPacks", QDir("cache/FTBPacks").absolutePath());
|
||||
m_metacache->addBase("ModpacksCHPacks", QDir("cache/ModpacksCHPacks").absolutePath());
|
||||
m_metacache->addBase("TwitchPacks", QDir("cache/TwitchPacks").absolutePath());
|
||||
m_metacache->addBase("skins", QDir("accounts/skins").absolutePath());
|
||||
m_metacache->addBase("root", QDir::currentPath());
|
||||
|
||||
@@ -115,7 +115,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
}
|
||||
}
|
||||
|
||||
if(!results.contains("os.arch") || !results.contains("java.version") || !success)
|
||||
if(!results.contains("os.arch") || !results.contains("java.version") || !results.contains("java.vendor") || !success)
|
||||
{
|
||||
result.validity = JavaCheckResult::Validity::ReturnedInvalidData;
|
||||
emit checkFinished(result);
|
||||
@@ -124,6 +124,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
|
||||
auto os_arch = results["os.arch"];
|
||||
auto java_version = results["java.version"];
|
||||
auto java_vendor = results["java.vendor"];
|
||||
bool is_64 = os_arch == "x86_64" || os_arch == "amd64";
|
||||
|
||||
|
||||
@@ -132,6 +133,7 @@ void JavaChecker::finished(int exitcode, QProcess::ExitStatus status)
|
||||
result.mojangPlatform = is_64 ? "64" : "32";
|
||||
result.realPlatform = os_arch;
|
||||
result.javaVersion = java_version;
|
||||
result.javaVendor = java_vendor;
|
||||
qDebug() << "Java checker succeeded.";
|
||||
emit checkFinished(result);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ struct MULTIMC_LOGIC_EXPORT JavaCheckResult
|
||||
QString mojangPlatform;
|
||||
QString realPlatform;
|
||||
JavaVersion javaVersion;
|
||||
QString javaVendor;
|
||||
QString outLog;
|
||||
QString errorLog;
|
||||
bool is_64bit = false;
|
||||
|
||||
@@ -33,17 +33,17 @@ void CheckJava::executeTask()
|
||||
if (perInstance)
|
||||
{
|
||||
emit logLine(
|
||||
tr("The java binary \"%1\" couldn't be found. Please fix the java path "
|
||||
QString("The java binary \"%1\" couldn't be found. Please fix the java path "
|
||||
"override in the instance's settings or disable it.").arg(m_javaPath),
|
||||
MessageLevel::Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit logLine(tr("The java binary \"%1\" couldn't be found. Please set up java in "
|
||||
emit logLine(QString("The java binary \"%1\" couldn't be found. Please set up java in "
|
||||
"the settings.").arg(m_javaPath),
|
||||
MessageLevel::Warning);
|
||||
}
|
||||
emitFailed(tr("Java path is not valid."));
|
||||
emitFailed(QString("Java path is not valid."));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -56,12 +56,13 @@ void CheckJava::executeTask()
|
||||
auto storedUnixTime = settings->get("JavaTimestamp").toLongLong();
|
||||
auto storedArchitecture = settings->get("JavaArchitecture").toString();
|
||||
auto storedVersion = settings->get("JavaVersion").toString();
|
||||
auto storedVendor = settings->get("JavaVendor").toString();
|
||||
m_javaUnixTime = javaUnixTime;
|
||||
// if timestamps are not the same, or something is missing, check!
|
||||
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0)
|
||||
if (javaUnixTime != storedUnixTime || storedVersion.size() == 0 || storedArchitecture.size() == 0 || storedVendor.size() == 0)
|
||||
{
|
||||
m_JavaChecker = new JavaChecker();
|
||||
emit logLine(tr("Checking Java version..."), MessageLevel::MultiMC);
|
||||
emit logLine(QString("Checking Java version..."), MessageLevel::MultiMC);
|
||||
connect(m_JavaChecker.get(), &JavaChecker::checkFinished, this, &CheckJava::checkJavaFinished);
|
||||
m_JavaChecker->m_path = realJavaPath;
|
||||
m_JavaChecker->performCheck();
|
||||
@@ -71,7 +72,8 @@ void CheckJava::executeTask()
|
||||
{
|
||||
auto verString = instance->settings()->get("JavaVersion").toString();
|
||||
auto archString = instance->settings()->get("JavaArchitecture").toString();
|
||||
printJavaInfo(verString, archString);
|
||||
auto vendorString = instance->settings()->get("JavaVendor").toString();
|
||||
printJavaInfo(verString, archString, vendorString);
|
||||
}
|
||||
emitSucceeded();
|
||||
}
|
||||
@@ -83,16 +85,16 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
case JavaCheckResult::Validity::Errored:
|
||||
{
|
||||
// Error message displayed if java can't start
|
||||
emit logLine(tr("Could not start java:"), MessageLevel::Error);
|
||||
emit logLine(QString("Could not start java:"), MessageLevel::Error);
|
||||
emit logLines(result.errorLog.split('\n'), MessageLevel::Error);
|
||||
emit logLine("\nCheck your MultiMC Java settings.", MessageLevel::MultiMC);
|
||||
printSystemInfo(false, false);
|
||||
emitFailed(tr("Could not start java!"));
|
||||
emitFailed(QString("Could not start java!"));
|
||||
return;
|
||||
}
|
||||
case JavaCheckResult::Validity::ReturnedInvalidData:
|
||||
{
|
||||
emit logLine(tr("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
|
||||
emit logLine(QString("Java checker returned some invalid data MultiMC doesn't understand:"), MessageLevel::Error);
|
||||
emit logLines(result.outLog.split('\n'), MessageLevel::Warning);
|
||||
emit logLine("\nMinecraft might not start properly.", MessageLevel::MultiMC);
|
||||
printSystemInfo(false, false);
|
||||
@@ -102,9 +104,10 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
case JavaCheckResult::Validity::Valid:
|
||||
{
|
||||
auto instance = m_parent->instance();
|
||||
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform);
|
||||
printJavaInfo(result.javaVersion.toString(), result.mojangPlatform, result.javaVendor);
|
||||
instance->settings()->set("JavaVersion", result.javaVersion.toString());
|
||||
instance->settings()->set("JavaArchitecture", result.mojangPlatform);
|
||||
instance->settings()->set("JavaVendor", result.javaVendor);
|
||||
instance->settings()->set("JavaTimestamp", m_javaUnixTime);
|
||||
emitSucceeded();
|
||||
return;
|
||||
@@ -112,9 +115,9 @@ void CheckJava::checkJavaFinished(JavaCheckResult result)
|
||||
}
|
||||
}
|
||||
|
||||
void CheckJava::printJavaInfo(const QString& version, const QString& architecture)
|
||||
void CheckJava::printJavaInfo(const QString& version, const QString& architecture, const QString & vendor)
|
||||
{
|
||||
emit logLine(tr("Java is version %1, using %2-bit architecture.\n\n").arg(version, architecture), MessageLevel::MultiMC);
|
||||
emit logLine(QString("Java is version %1, using %2-bit architecture, from %3.\n\n").arg(version, architecture, vendor), MessageLevel::MultiMC);
|
||||
printSystemInfo(true, architecture == "64");
|
||||
}
|
||||
|
||||
@@ -124,13 +127,13 @@ void CheckJava::printSystemInfo(bool javaIsKnown, bool javaIs64bit)
|
||||
auto system64 = Sys::isSystem64bit();
|
||||
if(cpu64 != system64)
|
||||
{
|
||||
emit logLine(tr("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
|
||||
emit logLine(QString("Your CPU architecture is not matching your system architecture. You might want to install a 64bit Operating System.\n\n"), MessageLevel::Error);
|
||||
}
|
||||
if(javaIsKnown)
|
||||
{
|
||||
if(javaIs64bit != system64)
|
||||
{
|
||||
emit logLine(tr("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
|
||||
emit logLine(QString("Your Java architecture is not matching your system architecture. You might want to install a 64bit Java version.\n\n"), MessageLevel::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ private slots:
|
||||
void checkJavaFinished(JavaCheckResult result);
|
||||
|
||||
private:
|
||||
void printJavaInfo(const QString & version, const QString & architecture);
|
||||
void printJavaInfo(const QString & version, const QString & architecture, const QString & vendor);
|
||||
void printSystemInfo(bool javaIsKnown, bool javaIs64bit);
|
||||
|
||||
private:
|
||||
|
||||
@@ -100,6 +100,11 @@ MinecraftInstance::MinecraftInstance(SettingsObjectPtr globalSettings, SettingsO
|
||||
auto launchMethodOverride = m_settings->registerSetting("OverrideMCLaunchMethod", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("MCLaunchMethod"), launchMethodOverride);
|
||||
|
||||
// Native library workarounds
|
||||
auto nativeLibraryWorkaroundsOverride = m_settings->registerSetting("OverrideNativeWorkarounds", false);
|
||||
m_settings->registerOverride(globalSettings->getSetting("UseNativeOpenAL"), nativeLibraryWorkaroundsOverride);
|
||||
m_settings->registerOverride(globalSettings->getSetting("UseNativeGLFW"), nativeLibraryWorkaroundsOverride);
|
||||
|
||||
// DEPRECATED: Read what versions the user configuration thinks should be used
|
||||
m_settings->registerSetting({"IntendedVersion", "MinecraftVersion"}, "");
|
||||
m_settings->registerSetting("LWJGLVersion", "");
|
||||
|
||||
@@ -138,14 +138,31 @@ void World::repath(const QFileInfo &file)
|
||||
m_folderName = file.fileName();
|
||||
if(file.isFile() && file.suffix() == "zip")
|
||||
{
|
||||
m_iconFile = QString();
|
||||
readFromZip(file);
|
||||
}
|
||||
else if(file.isDir())
|
||||
{
|
||||
QFileInfo assumedIconPath(file.absoluteFilePath() + "/icon.png");
|
||||
if(assumedIconPath.exists()) {
|
||||
m_iconFile = assumedIconPath.absoluteFilePath();
|
||||
}
|
||||
readFromFS(file);
|
||||
}
|
||||
}
|
||||
|
||||
bool World::resetIcon()
|
||||
{
|
||||
if(m_iconFile.isNull()) {
|
||||
return false;
|
||||
}
|
||||
if(QFile(m_iconFile).remove()) {
|
||||
m_iconFile = QString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void World::readFromFS(const QFileInfo &file)
|
||||
{
|
||||
auto bytes = getLevelDatDataFromFS(file);
|
||||
|
||||
@@ -40,6 +40,10 @@ public:
|
||||
{
|
||||
return m_actualName;
|
||||
}
|
||||
QString iconFile() const
|
||||
{
|
||||
return m_iconFile;
|
||||
}
|
||||
QDateTime lastPlayed() const
|
||||
{
|
||||
return m_lastPlayed;
|
||||
@@ -70,6 +74,8 @@ public:
|
||||
bool replace(World &with);
|
||||
// change the world's filesystem path (used by world lists for *MAGIC* purposes)
|
||||
void repath(const QFileInfo &file);
|
||||
// remove the icon file, if any
|
||||
bool resetIcon();
|
||||
|
||||
bool rename(const QString &to);
|
||||
bool install(const QString &to, const QString &name= QString());
|
||||
@@ -88,6 +94,7 @@ protected:
|
||||
QString m_containerOffsetPath;
|
||||
QString m_folderName;
|
||||
QString m_actualName;
|
||||
QString m_iconFile;
|
||||
QDateTime levelDatTime;
|
||||
QDateTime m_lastPlayed;
|
||||
int64_t m_randomSeed = 0;
|
||||
|
||||
@@ -136,6 +136,19 @@ bool WorldList::deleteWorlds(int first, int last)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldList::resetIcon(int row)
|
||||
{
|
||||
if (row >= worlds.size() || row < 0)
|
||||
return false;
|
||||
World &m = worlds[row];
|
||||
if(m.resetIcon()) {
|
||||
emit dataChanged(index(row), index(row), {WorldList::IconFileRole});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int WorldList::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 3;
|
||||
@@ -195,6 +208,10 @@ QVariant WorldList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
return world.lastPlayed();
|
||||
}
|
||||
case IconFileRole:
|
||||
{
|
||||
return world.iconFile();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ public:
|
||||
SeedRole,
|
||||
NameRole,
|
||||
GameModeRole,
|
||||
LastPlayedRole
|
||||
LastPlayedRole,
|
||||
IconFileRole
|
||||
};
|
||||
|
||||
WorldList(const QString &dir);
|
||||
@@ -81,6 +82,9 @@ public:
|
||||
/// Deletes the mod at the given index.
|
||||
virtual bool deleteWorld(int index);
|
||||
|
||||
/// Removes the world icon, if any
|
||||
virtual bool resetIcon(int index);
|
||||
|
||||
/// Deletes all the selected mods
|
||||
virtual bool deleteWorlds(int first, int last);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ static QString replaceSuffix (QString target, const QString &suffix, const QStri
|
||||
return target + replacement;
|
||||
}
|
||||
|
||||
static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack)
|
||||
static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack, bool nativeOpenAL, bool nativeGLFW)
|
||||
{
|
||||
QuaZip zip(source);
|
||||
if(!zip.open(QuaZip::mdUnzip))
|
||||
@@ -48,6 +48,13 @@ static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibH
|
||||
do
|
||||
{
|
||||
QString name = zip.getCurrentFileName();
|
||||
auto lowercase = name.toLower();
|
||||
if (nativeGLFW && name.contains("glfw")) {
|
||||
continue;
|
||||
}
|
||||
if (nativeOpenAL && name.contains("openal")) {
|
||||
continue;
|
||||
}
|
||||
if(applyJnilibHack)
|
||||
{
|
||||
name = replaceSuffix(name, ".jnilib", ".dylib");
|
||||
@@ -76,12 +83,16 @@ void ExtractNatives::executeTask()
|
||||
emitSucceeded();
|
||||
return;
|
||||
}
|
||||
auto settings = minecraftInstance->settings();
|
||||
bool nativeOpenAL = settings->get("UseNativeOpenAL").toBool();
|
||||
bool nativeGLFW = settings->get("UseNativeGLFW").toBool();
|
||||
|
||||
auto outputPath = minecraftInstance->getNativePath();
|
||||
auto javaVersion = minecraftInstance->getJavaVersion();
|
||||
bool jniHackEnabled = javaVersion.major() >= 8;
|
||||
for(const auto &source: toExtract)
|
||||
{
|
||||
if(!unzipNatives(source, outputPath, jniHackEnabled))
|
||||
if(!unzipNatives(source, outputPath, jniHackEnabled, nativeOpenAL, nativeGLFW))
|
||||
{
|
||||
auto reason = tr("Couldn't extract native jar '%1' to destination '%2'").arg(source, outputPath);
|
||||
emit logLine(reason, MessageLevel::Fatal);
|
||||
|
||||
150
api/logic/modplatform/modpacksch/FTBPackInstallTask.cpp
Normal file
150
api/logic/modplatform/modpacksch/FTBPackInstallTask.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "FTBPackInstallTask.h"
|
||||
|
||||
#include "BuildConfig.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Json.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
|
||||
namespace ModpacksCH {
|
||||
|
||||
PackInstallTask::PackInstallTask(Modpack pack, QString version)
|
||||
{
|
||||
m_pack = pack;
|
||||
m_version_name = version;
|
||||
}
|
||||
|
||||
bool PackInstallTask::abort()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void PackInstallTask::executeTask()
|
||||
{
|
||||
// Find pack version
|
||||
bool found = false;
|
||||
VersionInfo version;
|
||||
|
||||
for(auto vInfo : m_pack.versions) {
|
||||
if (vInfo.name == m_version_name) {
|
||||
found = true;
|
||||
version = vInfo;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
emitFailed("failed to find pack version " + m_version_name);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *netJob = new NetJob("ModpacksCH::VersionFetch");
|
||||
auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/modpack/%1/%2")
|
||||
.arg(m_pack.id).arg(version.id);
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl(searchUrl), &response));
|
||||
jobPtr = netJob;
|
||||
jobPtr->start();
|
||||
|
||||
QObject::connect(netJob, &NetJob::succeeded, this, &PackInstallTask::onDownloadSucceeded);
|
||||
QObject::connect(netJob, &NetJob::failed, this, &PackInstallTask::onDownloadFailed);
|
||||
}
|
||||
|
||||
void PackInstallTask::onDownloadSucceeded()
|
||||
{
|
||||
jobPtr.reset();
|
||||
|
||||
QJsonParseError parse_error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(response, &parse_error);
|
||||
if(parse_error.error != QJsonParseError::NoError) {
|
||||
qWarning() << "Error while parsing JSON response from FTB at " << parse_error.offset << " reason: " << parse_error.errorString();
|
||||
qWarning() << response;
|
||||
return;
|
||||
}
|
||||
|
||||
auto obj = doc.object();
|
||||
|
||||
ModpacksCH::Version version;
|
||||
try
|
||||
{
|
||||
ModpacksCH::loadVersion(version, obj);
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||
return;
|
||||
}
|
||||
m_version = version;
|
||||
|
||||
install();
|
||||
}
|
||||
|
||||
void PackInstallTask::onDownloadFailed(QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
}
|
||||
|
||||
void PackInstallTask::install()
|
||||
{
|
||||
setStatus(tr("Installing modpack"));
|
||||
|
||||
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
|
||||
instanceSettings->registerSetting("InstanceType", "Legacy");
|
||||
instanceSettings->set("InstanceType", "OneSix");
|
||||
|
||||
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||
auto components = instance.getPackProfile();
|
||||
components->buildingFromScratch();
|
||||
|
||||
for(auto target : m_version.targets) {
|
||||
if(target.type == "game" && target.name == "minecraft") {
|
||||
components->setComponentVersion("net.minecraft", target.version, true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto target : m_version.targets) {
|
||||
if(target.type == "modloader" && target.name == "forge") {
|
||||
components->setComponentVersion("net.minecraftforge", target.version, true);
|
||||
}
|
||||
}
|
||||
components->saveNow();
|
||||
|
||||
jobPtr.reset(new NetJob(tr("Mod download")));
|
||||
for(auto file : m_version.files) {
|
||||
if(file.serverOnly) continue;
|
||||
|
||||
auto relpath = FS::PathCombine("minecraft", file.path, file.name);
|
||||
auto path = FS::PathCombine(m_stagingPath , relpath);
|
||||
|
||||
qDebug() << "Will download" << file.url << "to" << path;
|
||||
auto dl = Net::Download::makeFile(file.url, path);
|
||||
jobPtr->addNetAction(dl);
|
||||
}
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, [&]()
|
||||
{
|
||||
jobPtr.reset();
|
||||
emitSucceeded();
|
||||
});
|
||||
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason)
|
||||
{
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total)
|
||||
{
|
||||
setProgress(current, total);
|
||||
});
|
||||
|
||||
setStatus(tr("Downloading mods..."));
|
||||
jobPtr->start();
|
||||
|
||||
instance.setName(m_instName);
|
||||
instance.setIconKey(m_instIcon);
|
||||
instanceSettings->resumeSave();
|
||||
}
|
||||
|
||||
}
|
||||
41
api/logic/modplatform/modpacksch/FTBPackInstallTask.h
Normal file
41
api/logic/modplatform/modpacksch/FTBPackInstallTask.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "FTBPackManifest.h"
|
||||
|
||||
#include "InstanceTask.h"
|
||||
#include "multimc_logic_export.h"
|
||||
#include "net/NetJob.h"
|
||||
|
||||
namespace ModpacksCH {
|
||||
|
||||
class MULTIMC_LOGIC_EXPORT PackInstallTask : public InstanceTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PackInstallTask(Modpack pack, QString version);
|
||||
virtual ~PackInstallTask(){}
|
||||
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
virtual void executeTask() override;
|
||||
|
||||
private slots:
|
||||
void onDownloadSucceeded();
|
||||
void onDownloadFailed(QString reason);
|
||||
|
||||
private:
|
||||
void install();
|
||||
|
||||
private:
|
||||
NetJobPtr jobPtr;
|
||||
QByteArray response;
|
||||
|
||||
Modpack m_pack;
|
||||
QString m_version_name;
|
||||
Version m_version;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
156
api/logic/modplatform/modpacksch/FTBPackManifest.cpp
Normal file
156
api/logic/modplatform/modpacksch/FTBPackManifest.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "FTBPackManifest.h"
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
static void loadSpecs(ModpacksCH::Specs & s, QJsonObject & obj)
|
||||
{
|
||||
s.id = Json::requireInteger(obj, "id");
|
||||
s.minimum = Json::requireInteger(obj, "minimum");
|
||||
s.recommended = Json::requireInteger(obj, "recommended");
|
||||
}
|
||||
|
||||
static void loadTag(ModpacksCH::Tag & t, QJsonObject & obj)
|
||||
{
|
||||
t.id = Json::requireInteger(obj, "id");
|
||||
t.name = Json::requireString(obj, "name");
|
||||
}
|
||||
|
||||
static void loadArt(ModpacksCH::Art & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.url = Json::requireString(obj, "url");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.width = Json::requireInteger(obj, "width");
|
||||
a.height = Json::requireInteger(obj, "height");
|
||||
a.compressed = Json::requireBoolean(obj, "compressed");
|
||||
a.sha1 = Json::requireString(obj, "sha1");
|
||||
a.size = Json::requireInteger(obj, "size");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadAuthor(ModpacksCH::Author & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.website = Json::requireString(obj, "website");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionInfo(ModpacksCH::VersionInfo & v, QJsonObject & obj)
|
||||
{
|
||||
v.id = Json::requireInteger(obj, "id");
|
||||
v.name = Json::requireString(obj, "name");
|
||||
v.type = Json::requireString(obj, "type");
|
||||
v.updated = Json::requireInteger(obj, "updated");
|
||||
auto specs = Json::requireObject(obj, "specs");
|
||||
loadSpecs(v.specs, specs);
|
||||
}
|
||||
|
||||
void ModpacksCH::loadModpack(ModpacksCH::Modpack & m, QJsonObject & obj)
|
||||
{
|
||||
m.id = Json::requireInteger(obj, "id");
|
||||
m.name = Json::requireString(obj, "name");
|
||||
m.synopsis = Json::requireString(obj, "synopsis");
|
||||
m.description = Json::requireString(obj, "description");
|
||||
m.type = Json::requireString(obj, "type");
|
||||
m.featured = Json::requireBoolean(obj, "featured");
|
||||
m.installs = Json::requireInteger(obj, "installs");
|
||||
m.plays = Json::requireInteger(obj, "plays");
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
m.refreshed = Json::requireInteger(obj, "refreshed");
|
||||
auto artArr = Json::requireArray(obj, "art");
|
||||
for (const auto & artRaw : artArr)
|
||||
{
|
||||
auto artObj = Json::requireObject(artRaw);
|
||||
ModpacksCH::Art art;
|
||||
loadArt(art, artObj);
|
||||
m.art.append(art);
|
||||
}
|
||||
auto authorArr = Json::requireArray(obj, "authors");
|
||||
for (const auto & authorRaw : authorArr)
|
||||
{
|
||||
auto authorObj = Json::requireObject(authorRaw);
|
||||
ModpacksCH::Author author;
|
||||
loadAuthor(author, authorObj);
|
||||
m.authors.append(author);
|
||||
}
|
||||
auto versionArr = Json::requireArray(obj, "versions");
|
||||
for (const auto & versionRaw : versionArr)
|
||||
{
|
||||
auto versionObj = Json::requireObject(versionRaw);
|
||||
ModpacksCH::VersionInfo version;
|
||||
loadVersionInfo(version, versionObj);
|
||||
m.versions.append(version);
|
||||
}
|
||||
auto tagArr = Json::requireArray(obj, "tags");
|
||||
for (const auto & tagRaw : tagArr)
|
||||
{
|
||||
auto tagObj = Json::requireObject(tagRaw);
|
||||
ModpacksCH::Tag tag;
|
||||
loadTag(tag, tagObj);
|
||||
m.tags.append(tag);
|
||||
}
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionTarget(ModpacksCH::VersionTarget & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.version = Json::requireString(obj, "version");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
static void loadVersionFile(ModpacksCH::VersionFile & a, QJsonObject & obj)
|
||||
{
|
||||
a.id = Json::requireInteger(obj, "id");
|
||||
a.type = Json::requireString(obj, "type");
|
||||
a.path = Json::requireString(obj, "path");
|
||||
a.name = Json::requireString(obj, "name");
|
||||
a.version = Json::requireString(obj, "version");
|
||||
a.url = Json::requireString(obj, "url");
|
||||
a.sha1 = Json::requireString(obj, "sha1");
|
||||
a.size = Json::requireInteger(obj, "size");
|
||||
a.clientOnly = Json::requireBoolean(obj, "clientonly");
|
||||
a.serverOnly = Json::requireBoolean(obj, "serveronly");
|
||||
a.optional = Json::requireBoolean(obj, "optional");
|
||||
a.updated = Json::requireInteger(obj, "updated");
|
||||
}
|
||||
|
||||
void ModpacksCH::loadVersion(ModpacksCH::Version & m, QJsonObject & obj)
|
||||
{
|
||||
m.id = Json::requireInteger(obj, "id");
|
||||
m.parent = Json::requireInteger(obj, "parent");
|
||||
m.name = Json::requireString(obj, "name");
|
||||
m.type = Json::requireString(obj, "type");
|
||||
m.installs = Json::requireInteger(obj, "installs");
|
||||
m.plays = Json::requireInteger(obj, "plays");
|
||||
m.updated = Json::requireInteger(obj, "updated");
|
||||
m.refreshed = Json::requireInteger(obj, "refreshed");
|
||||
auto specs = Json::requireObject(obj, "specs");
|
||||
loadSpecs(m.specs, specs);
|
||||
auto targetArr = Json::requireArray(obj, "targets");
|
||||
for (const auto & targetRaw : targetArr)
|
||||
{
|
||||
auto versionObj = Json::requireObject(targetRaw);
|
||||
ModpacksCH::VersionTarget target;
|
||||
loadVersionTarget(target, versionObj);
|
||||
m.targets.append(target);
|
||||
}
|
||||
auto fileArr = Json::requireArray(obj, "files");
|
||||
for (const auto & fileRaw : fileArr)
|
||||
{
|
||||
auto fileObj = Json::requireObject(fileRaw);
|
||||
ModpacksCH::VersionFile file;
|
||||
loadVersionFile(file, fileObj);
|
||||
m.files.append(file);
|
||||
}
|
||||
}
|
||||
|
||||
//static void loadVersionChangelog(ModpacksCH::VersionChangelog & m, QJsonObject & obj)
|
||||
//{
|
||||
// m.content = Json::requireString(obj, "content");
|
||||
// m.updated = Json::requireInteger(obj, "updated");
|
||||
//}
|
||||
127
api/logic/modplatform/modpacksch/FTBPackManifest.h
Normal file
127
api/logic/modplatform/modpacksch/FTBPackManifest.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QUrl>
|
||||
#include <QJsonObject>
|
||||
#include <QMetaType>
|
||||
|
||||
#include "multimc_logic_export.h"
|
||||
|
||||
namespace ModpacksCH
|
||||
{
|
||||
|
||||
struct Specs
|
||||
{
|
||||
int id;
|
||||
int minimum;
|
||||
int recommended;
|
||||
};
|
||||
|
||||
struct Tag
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct Art
|
||||
{
|
||||
int id;
|
||||
QString url;
|
||||
QString type;
|
||||
int width;
|
||||
int height;
|
||||
bool compressed;
|
||||
QString sha1;
|
||||
int size;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct Author
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString type;
|
||||
QString website;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct VersionInfo
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString type;
|
||||
int64_t updated;
|
||||
Specs specs;
|
||||
};
|
||||
|
||||
struct Modpack
|
||||
{
|
||||
int id;
|
||||
QString name;
|
||||
QString synopsis;
|
||||
QString description;
|
||||
QString type;
|
||||
bool featured;
|
||||
int installs;
|
||||
int plays;
|
||||
int64_t updated;
|
||||
int64_t refreshed;
|
||||
QVector<Art> art;
|
||||
QVector<Author> authors;
|
||||
QVector<VersionInfo> versions;
|
||||
QVector<Tag> tags;
|
||||
};
|
||||
|
||||
struct VersionTarget
|
||||
{
|
||||
int id;
|
||||
QString type;
|
||||
QString name;
|
||||
QString version;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct VersionFile
|
||||
{
|
||||
int id;
|
||||
QString type;
|
||||
QString path;
|
||||
QString name;
|
||||
QString version;
|
||||
QString url;
|
||||
QString sha1;
|
||||
int size;
|
||||
bool clientOnly;
|
||||
bool serverOnly;
|
||||
bool optional;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
struct Version
|
||||
{
|
||||
int id;
|
||||
int parent;
|
||||
QString name;
|
||||
QString type;
|
||||
int installs;
|
||||
int plays;
|
||||
int64_t updated;
|
||||
int64_t refreshed;
|
||||
Specs specs;
|
||||
QVector<VersionTarget> targets;
|
||||
QVector<VersionFile> files;
|
||||
};
|
||||
|
||||
struct VersionChangelog
|
||||
{
|
||||
QString content;
|
||||
int64_t updated;
|
||||
};
|
||||
|
||||
MULTIMC_LOGIC_EXPORT void loadModpack(Modpack & m, QJsonObject & obj);
|
||||
|
||||
MULTIMC_LOGIC_EXPORT void loadVersion(Version & m, QJsonObject & obj);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(ModpacksCH::Modpack)
|
||||
Reference in New Issue
Block a user