refactor: move modrinth modpack import to separate file
Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
parent
941d75824a
commit
4441b37338
@ -495,6 +495,8 @@ set(MODRINTH_SOURCES
|
|||||||
modplatform/modrinth/ModrinthPackManifest.h
|
modplatform/modrinth/ModrinthPackManifest.h
|
||||||
modplatform/modrinth/ModrinthCheckUpdate.cpp
|
modplatform/modrinth/ModrinthCheckUpdate.cpp
|
||||||
modplatform/modrinth/ModrinthCheckUpdate.h
|
modplatform/modrinth/ModrinthCheckUpdate.h
|
||||||
|
modplatform/modrinth/ModrinthInstanceCreationTask.cpp
|
||||||
|
modplatform/modrinth/ModrinthInstanceCreationTask.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MODPACKSCH_SOURCES
|
set(MODPACKSCH_SOURCES
|
||||||
|
@ -52,8 +52,8 @@
|
|||||||
#include "minecraft/PackProfile.h"
|
#include "minecraft/PackProfile.h"
|
||||||
#include "modplatform/flame/FileResolvingTask.h"
|
#include "modplatform/flame/FileResolvingTask.h"
|
||||||
#include "modplatform/flame/PackManifest.h"
|
#include "modplatform/flame/PackManifest.h"
|
||||||
#include "modplatform/modrinth/ModrinthPackManifest.h"
|
|
||||||
#include "modplatform/technic/TechnicPackProcessor.h"
|
#include "modplatform/technic/TechnicPackProcessor.h"
|
||||||
|
#include "modplatform/modrinth/ModrinthInstanceCreationTask.h"
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "icons/IconList.h"
|
#include "icons/IconList.h"
|
||||||
@ -256,6 +256,7 @@ void InstanceImportTask::extractFinished()
|
|||||||
void InstanceImportTask::extractAborted()
|
void InstanceImportTask::extractAborted()
|
||||||
{
|
{
|
||||||
emitFailed(tr("Instance import has been aborted."));
|
emitFailed(tr("Instance import has been aborted."));
|
||||||
|
emit aborted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,198 +585,23 @@ void InstanceImportTask::processMultiMC()
|
|||||||
emitSucceeded();
|
emitSucceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.modrinth.com/docs/modpacks/format_definition/
|
|
||||||
void InstanceImportTask::processModrinth()
|
void InstanceImportTask::processModrinth()
|
||||||
{
|
{
|
||||||
std::vector<Modrinth::File> files;
|
auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, m_sourceUrl.toString());
|
||||||
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion;
|
|
||||||
try {
|
|
||||||
QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json");
|
|
||||||
auto doc = Json::requireDocument(indexPath);
|
|
||||||
auto obj = Json::requireObject(doc, "modrinth.index.json");
|
|
||||||
int formatVersion = Json::requireInteger(obj, "formatVersion", "modrinth.index.json");
|
|
||||||
if (formatVersion == 1) {
|
|
||||||
auto game = Json::requireString(obj, "game", "modrinth.index.json");
|
|
||||||
if (game != "minecraft") {
|
|
||||||
throw JSONValidationError("Unknown game: " + game);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto jsonFiles = Json::requireIsArrayOf<QJsonObject>(obj, "files", "modrinth.index.json");
|
inst_creation_task->setName(m_instName);
|
||||||
bool had_optional = false;
|
inst_creation_task->setIcon(m_instIcon);
|
||||||
for (auto modInfo : jsonFiles) {
|
inst_creation_task->setGroup(m_instGroup);
|
||||||
Modrinth::File file;
|
|
||||||
file.path = Json::requireString(modInfo, "path");
|
|
||||||
|
|
||||||
auto env = Json::ensureObject(modInfo, "env");
|
connect(inst_creation_task, &Task::succeeded, this, &InstanceImportTask::emitSucceeded);
|
||||||
// 'env' field is optional
|
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
|
||||||
if (!env.isEmpty()) {
|
connect(inst_creation_task, &Task::progress, this, &InstanceImportTask::setProgress);
|
||||||
QString support = Json::ensureString(env, "client", "unsupported");
|
connect(inst_creation_task, &Task::status, this, &InstanceImportTask::setStatus);
|
||||||
if (support == "unsupported") {
|
connect(inst_creation_task, &Task::finished, this, [inst_creation_task]{ inst_creation_task->deleteLater(); });
|
||||||
continue;
|
|
||||||
} else if (support == "optional") {
|
|
||||||
// TODO: Make a review dialog for choosing which ones the user wants!
|
|
||||||
if (!had_optional) {
|
|
||||||
had_optional = true;
|
|
||||||
auto info = CustomMessageBox::selectable(
|
|
||||||
m_parent, tr("Optional mod detected!"),
|
|
||||||
tr("One or more mods from this modpack are optional. They will be downloaded, but disabled by default!"),
|
|
||||||
QMessageBox::Information);
|
|
||||||
info->exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.path.endsWith(".jar"))
|
connect(this, &Task::aborted, inst_creation_task, [inst_creation_task] {
|
||||||
file.path += ".disabled";
|
inst_creation_task->abort();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject hashes = Json::requireObject(modInfo, "hashes");
|
|
||||||
QString hash;
|
|
||||||
QCryptographicHash::Algorithm hashAlgorithm;
|
|
||||||
hash = Json::ensureString(hashes, "sha1");
|
|
||||||
hashAlgorithm = QCryptographicHash::Sha1;
|
|
||||||
if (hash.isEmpty()) {
|
|
||||||
hash = Json::ensureString(hashes, "sha512");
|
|
||||||
hashAlgorithm = QCryptographicHash::Sha512;
|
|
||||||
if (hash.isEmpty()) {
|
|
||||||
hash = Json::ensureString(hashes, "sha256");
|
|
||||||
hashAlgorithm = QCryptographicHash::Sha256;
|
|
||||||
if (hash.isEmpty()) {
|
|
||||||
throw JSONValidationError("No hash found for: " + file.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.hash = QByteArray::fromHex(hash.toLatin1());
|
|
||||||
file.hashAlgorithm = hashAlgorithm;
|
|
||||||
|
|
||||||
// Do not use requireUrl, which uses StrictMode, instead use QUrl's default TolerantMode
|
|
||||||
// (as Modrinth seems to incorrectly handle spaces)
|
|
||||||
|
|
||||||
auto download_arr = Json::ensureArray(modInfo, "downloads");
|
|
||||||
for(auto download : download_arr) {
|
|
||||||
qWarning() << download.toString();
|
|
||||||
bool is_last = download.toString() == download_arr.last().toString();
|
|
||||||
|
|
||||||
auto download_url = QUrl(download.toString());
|
|
||||||
|
|
||||||
if (!download_url.isValid()) {
|
|
||||||
qDebug() << QString("Download URL (%1) for %2 is not a correctly formatted URL")
|
|
||||||
.arg(download_url.toString(), file.path);
|
|
||||||
if(is_last && file.downloads.isEmpty())
|
|
||||||
throw JSONValidationError(tr("Download URL for %1 is not a correctly formatted URL").arg(file.path));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file.downloads.push_back(download_url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files.push_back(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dependencies = Json::requireObject(obj, "dependencies", "modrinth.index.json");
|
|
||||||
for (auto it = dependencies.begin(), end = dependencies.end(); it != end; ++it) {
|
|
||||||
QString name = it.key();
|
|
||||||
if (name == "minecraft") {
|
|
||||||
minecraftVersion = Json::requireString(*it, "Minecraft version");
|
|
||||||
}
|
|
||||||
else if (name == "fabric-loader") {
|
|
||||||
fabricVersion = Json::requireString(*it, "Fabric Loader version");
|
|
||||||
}
|
|
||||||
else if (name == "quilt-loader") {
|
|
||||||
quiltVersion = Json::requireString(*it, "Quilt Loader version");
|
|
||||||
}
|
|
||||||
else if (name == "forge") {
|
|
||||||
forgeVersion = Json::requireString(*it, "Forge version");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw JSONValidationError("Unknown dependency type: " + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw JSONValidationError(QStringLiteral("Unknown format version: %s").arg(formatVersion));
|
|
||||||
}
|
|
||||||
QFile::remove(indexPath);
|
|
||||||
} catch (const JSONValidationError& e) {
|
|
||||||
emitFailed(tr("Could not understand pack index:\n") + e.cause());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mcPath = FS::PathCombine(m_stagingPath, ".minecraft");
|
|
||||||
|
|
||||||
auto override_path = FS::PathCombine(m_stagingPath, "overrides");
|
|
||||||
if (QFile::exists(override_path)) {
|
|
||||||
if (!QFile::rename(override_path, mcPath)) {
|
|
||||||
emitFailed(tr("Could not rename the overrides folder:\n") + "overrides");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do client overrides
|
|
||||||
auto client_override_path = FS::PathCombine(m_stagingPath, "client-overrides");
|
|
||||||
if (QFile::exists(client_override_path)) {
|
|
||||||
if (!FS::overrideFolder(mcPath, client_override_path)) {
|
|
||||||
emitFailed(tr("Could not rename the client overrides folder:\n") + "client overrides");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
|
||||||
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
|
||||||
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
|
||||||
auto components = instance.getPackProfile();
|
|
||||||
components->buildingFromScratch();
|
|
||||||
components->setComponentVersion("net.minecraft", minecraftVersion, true);
|
|
||||||
if (!fabricVersion.isEmpty())
|
|
||||||
components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
|
|
||||||
if (!quiltVersion.isEmpty())
|
|
||||||
components->setComponentVersion("org.quiltmc.quilt-loader", quiltVersion);
|
|
||||||
if (!forgeVersion.isEmpty())
|
|
||||||
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
|
||||||
if (m_instIcon != "default")
|
|
||||||
{
|
|
||||||
instance.setIconKey(m_instIcon);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
instance.setIconKey("modrinth");
|
|
||||||
}
|
|
||||||
instance.setName(m_instName);
|
|
||||||
instance.saveNow();
|
|
||||||
|
|
||||||
m_filesNetJob = new NetJob(tr("Mod download"), APPLICATION->network());
|
|
||||||
for (auto file : files)
|
|
||||||
{
|
|
||||||
auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path);
|
|
||||||
qDebug() << "Will try to download" << file.downloads.front() << "to" << path;
|
|
||||||
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
|
|
||||||
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
|
|
||||||
m_filesNetJob->addNetAction(dl);
|
|
||||||
|
|
||||||
if (file.downloads.size() > 0) {
|
|
||||||
// FIXME: This really needs to be put into a ConcurrentTask of
|
|
||||||
// MultipleOptionsTask's , once those exist :)
|
|
||||||
connect(dl.get(), &NetAction::failed, [this, &file, path, dl]{
|
|
||||||
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
|
|
||||||
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
|
|
||||||
m_filesNetJob->addNetAction(dl);
|
|
||||||
dl->succeeded();
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
inst_creation_task->start();
|
||||||
connect(m_filesNetJob.get(), &NetJob::succeeded, this, [&]()
|
|
||||||
{
|
|
||||||
m_filesNetJob.reset();
|
|
||||||
emitSucceeded();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
connect(m_filesNetJob.get(), &NetJob::failed, [&](const QString &reason)
|
|
||||||
{
|
|
||||||
m_filesNetJob.reset();
|
|
||||||
emitFailed(reason);
|
|
||||||
});
|
|
||||||
connect(m_filesNetJob.get(), &NetJob::progress, [&](qint64 current, qint64 total)
|
|
||||||
{
|
|
||||||
setProgress(current, total);
|
|
||||||
});
|
|
||||||
setStatus(tr("Downloading mods..."));
|
|
||||||
m_filesNetJob->start();
|
|
||||||
}
|
}
|
||||||
|
225
launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
Normal file
225
launcher/modplatform/modrinth/ModrinthInstanceCreationTask.cpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
#include "ModrinthInstanceCreationTask.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "Json.h"
|
||||||
|
|
||||||
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "minecraft/PackProfile.h"
|
||||||
|
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include "net/ChecksumValidator.h"
|
||||||
|
|
||||||
|
#include "settings/INISettingsObject.h"
|
||||||
|
|
||||||
|
#include "ui/dialogs/CustomMessageBox.h"
|
||||||
|
|
||||||
|
bool ModrinthCreationTask::createInstance()
|
||||||
|
{
|
||||||
|
QEventLoop loop;
|
||||||
|
|
||||||
|
if (m_files.empty() && !parseManifest())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto mcPath = FS::PathCombine(m_stagingPath, ".minecraft");
|
||||||
|
|
||||||
|
auto override_path = FS::PathCombine(m_stagingPath, "overrides");
|
||||||
|
if (QFile::exists(override_path)) {
|
||||||
|
if (!QFile::rename(override_path, mcPath)) {
|
||||||
|
setError(tr("Could not rename the overrides folder:\n") + "overrides");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do client overrides
|
||||||
|
auto client_override_path = FS::PathCombine(m_stagingPath, "client-overrides");
|
||||||
|
if (QFile::exists(client_override_path)) {
|
||||||
|
if (!FS::overrideFolder(mcPath, client_override_path)) {
|
||||||
|
setError(tr("Could not rename the client overrides folder:\n") + "client overrides");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString configPath = FS::PathCombine(m_stagingPath, "instance.cfg");
|
||||||
|
auto instanceSettings = std::make_shared<INISettingsObject>(configPath);
|
||||||
|
MinecraftInstance instance(m_globalSettings, instanceSettings, m_stagingPath);
|
||||||
|
auto components = instance.getPackProfile();
|
||||||
|
components->buildingFromScratch();
|
||||||
|
components->setComponentVersion("net.minecraft", minecraftVersion, true);
|
||||||
|
|
||||||
|
if (!fabricVersion.isEmpty())
|
||||||
|
components->setComponentVersion("net.fabricmc.fabric-loader", fabricVersion);
|
||||||
|
if (!quiltVersion.isEmpty())
|
||||||
|
components->setComponentVersion("org.quiltmc.quilt-loader", quiltVersion);
|
||||||
|
if (!forgeVersion.isEmpty())
|
||||||
|
components->setComponentVersion("net.minecraftforge", forgeVersion);
|
||||||
|
if (m_instIcon != "default") {
|
||||||
|
instance.setIconKey(m_instIcon);
|
||||||
|
} else {
|
||||||
|
instance.setIconKey("modrinth");
|
||||||
|
}
|
||||||
|
instance.setName(m_instName);
|
||||||
|
instance.setManagedPack("modrinth", getManagedPackID(), m_managed_name, m_managed_id, {});
|
||||||
|
instance.saveNow();
|
||||||
|
|
||||||
|
m_files_job = new NetJob(tr("Mod download"), APPLICATION->network());
|
||||||
|
|
||||||
|
for (auto file : m_files) {
|
||||||
|
auto path = FS::PathCombine(m_stagingPath, ".minecraft", file.path);
|
||||||
|
qDebug() << "Will try to download" << file.downloads.front() << "to" << path;
|
||||||
|
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
|
||||||
|
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
|
||||||
|
m_files_job->addNetAction(dl);
|
||||||
|
|
||||||
|
if (file.downloads.size() > 0) {
|
||||||
|
// FIXME: This really needs to be put into a ConcurrentTask of
|
||||||
|
// MultipleOptionsTask's , once those exist :)
|
||||||
|
connect(dl.get(), &NetAction::failed, [this, &file, path, dl] {
|
||||||
|
auto dl = Net::Download::makeFile(file.downloads.dequeue(), path);
|
||||||
|
dl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
|
||||||
|
m_files_job->addNetAction(dl);
|
||||||
|
dl->succeeded();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ended_well = false;
|
||||||
|
|
||||||
|
connect(m_files_job.get(), &NetJob::succeeded, this, [&]() { ended_well = true; });
|
||||||
|
connect(m_files_job.get(), &NetJob::failed, [&](const QString& reason) {
|
||||||
|
ended_well = false;
|
||||||
|
setError(reason);
|
||||||
|
});
|
||||||
|
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
|
||||||
|
connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); });
|
||||||
|
|
||||||
|
setStatus(tr("Downloading mods..."));
|
||||||
|
m_files_job->start();
|
||||||
|
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
return ended_well;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModrinthCreationTask::parseManifest()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
QString indexPath = FS::PathCombine(m_stagingPath, "modrinth.index.json");
|
||||||
|
auto doc = Json::requireDocument(indexPath);
|
||||||
|
auto obj = Json::requireObject(doc, "modrinth.index.json");
|
||||||
|
int formatVersion = Json::requireInteger(obj, "formatVersion", "modrinth.index.json");
|
||||||
|
if (formatVersion == 1) {
|
||||||
|
auto game = Json::requireString(obj, "game", "modrinth.index.json");
|
||||||
|
if (game != "minecraft") {
|
||||||
|
throw JSONValidationError("Unknown game: " + game);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_managed_version_id = Json::ensureString(obj, "versionId", "Managed ID");
|
||||||
|
m_managed_name = Json::ensureString(obj, "name", "Managed Name");
|
||||||
|
|
||||||
|
auto jsonFiles = Json::requireIsArrayOf<QJsonObject>(obj, "files", "modrinth.index.json");
|
||||||
|
bool had_optional = false;
|
||||||
|
for (auto modInfo : jsonFiles) {
|
||||||
|
Modrinth::File file;
|
||||||
|
file.path = Json::requireString(modInfo, "path");
|
||||||
|
|
||||||
|
auto env = Json::ensureObject(modInfo, "env");
|
||||||
|
// 'env' field is optional
|
||||||
|
if (!env.isEmpty()) {
|
||||||
|
QString support = Json::ensureString(env, "client", "unsupported");
|
||||||
|
if (support == "unsupported") {
|
||||||
|
continue;
|
||||||
|
} else if (support == "optional") {
|
||||||
|
// TODO: Make a review dialog for choosing which ones the user wants!
|
||||||
|
if (!had_optional) {
|
||||||
|
had_optional = true;
|
||||||
|
auto info = CustomMessageBox::selectable(
|
||||||
|
m_parent, tr("Optional mod detected!"),
|
||||||
|
tr("One or more mods from this modpack are optional. They will be downloaded, but disabled by default!"),
|
||||||
|
QMessageBox::Information);
|
||||||
|
info->exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.path.endsWith(".jar"))
|
||||||
|
file.path += ".disabled";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject hashes = Json::requireObject(modInfo, "hashes");
|
||||||
|
QString hash;
|
||||||
|
QCryptographicHash::Algorithm hashAlgorithm;
|
||||||
|
hash = Json::ensureString(hashes, "sha1");
|
||||||
|
hashAlgorithm = QCryptographicHash::Sha1;
|
||||||
|
if (hash.isEmpty()) {
|
||||||
|
hash = Json::ensureString(hashes, "sha512");
|
||||||
|
hashAlgorithm = QCryptographicHash::Sha512;
|
||||||
|
if (hash.isEmpty()) {
|
||||||
|
hash = Json::ensureString(hashes, "sha256");
|
||||||
|
hashAlgorithm = QCryptographicHash::Sha256;
|
||||||
|
if (hash.isEmpty()) {
|
||||||
|
throw JSONValidationError("No hash found for: " + file.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.hash = QByteArray::fromHex(hash.toLatin1());
|
||||||
|
file.hashAlgorithm = hashAlgorithm;
|
||||||
|
|
||||||
|
// Do not use requireUrl, which uses StrictMode, instead use QUrl's default TolerantMode
|
||||||
|
// (as Modrinth seems to incorrectly handle spaces)
|
||||||
|
|
||||||
|
auto download_arr = Json::ensureArray(modInfo, "downloads");
|
||||||
|
for (auto download : download_arr) {
|
||||||
|
qWarning() << download.toString();
|
||||||
|
bool is_last = download.toString() == download_arr.last().toString();
|
||||||
|
|
||||||
|
auto download_url = QUrl(download.toString());
|
||||||
|
|
||||||
|
if (!download_url.isValid()) {
|
||||||
|
qDebug()
|
||||||
|
<< QString("Download URL (%1) for %2 is not a correctly formatted URL").arg(download_url.toString(), file.path);
|
||||||
|
if (is_last && file.downloads.isEmpty())
|
||||||
|
throw JSONValidationError(tr("Download URL for %1 is not a correctly formatted URL").arg(file.path));
|
||||||
|
} else {
|
||||||
|
file.downloads.push_back(download_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_files.push_back(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dependencies = Json::requireObject(obj, "dependencies", "modrinth.index.json");
|
||||||
|
for (auto it = dependencies.begin(), end = dependencies.end(); it != end; ++it) {
|
||||||
|
QString name = it.key();
|
||||||
|
if (name == "minecraft") {
|
||||||
|
minecraftVersion = Json::requireString(*it, "Minecraft version");
|
||||||
|
} else if (name == "fabric-loader") {
|
||||||
|
fabricVersion = Json::requireString(*it, "Fabric Loader version");
|
||||||
|
} else if (name == "quilt-loader") {
|
||||||
|
quiltVersion = Json::requireString(*it, "Quilt Loader version");
|
||||||
|
} else if (name == "forge") {
|
||||||
|
forgeVersion = Json::requireString(*it, "Forge version");
|
||||||
|
} else {
|
||||||
|
throw JSONValidationError("Unknown dependency type: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw JSONValidationError(QStringLiteral("Unknown format version: %s").arg(formatVersion));
|
||||||
|
}
|
||||||
|
QFile::remove(indexPath);
|
||||||
|
} catch (const JSONValidationError& e) {
|
||||||
|
setError(tr("Could not understand pack index:\n") + e.cause());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ModrinthCreationTask::getManagedPackID() const
|
||||||
|
{
|
||||||
|
if (!m_source_url.isEmpty()) {
|
||||||
|
QRegularExpression regex(R"(data\/(.*)\/versions)");
|
||||||
|
return regex.match(m_source_url).captured(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
39
launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h
Normal file
39
launcher/modplatform/modrinth/ModrinthInstanceCreationTask.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InstanceCreationTask.h"
|
||||||
|
|
||||||
|
#include "modplatform/modrinth/ModrinthPackManifest.h"
|
||||||
|
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
|
||||||
|
class ModrinthCreationTask final : public InstanceCreationTask {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString source_url = {})
|
||||||
|
: InstanceCreationTask(), m_parent(parent)
|
||||||
|
{
|
||||||
|
setStagingPath(staging_path);
|
||||||
|
setParentSettings(global_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool abort() override;
|
||||||
|
bool canAbort() const override { return true; }
|
||||||
|
|
||||||
|
bool updateInstance() override;
|
||||||
|
bool createInstance() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool parseManifest();
|
||||||
|
QString getManagedPackID() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget* m_parent = nullptr;
|
||||||
|
|
||||||
|
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion;
|
||||||
|
QString m_managed_id, m_managed_version_id, m_managed_name;
|
||||||
|
QString m_source_url;
|
||||||
|
|
||||||
|
std::vector<Modrinth::File> m_files;
|
||||||
|
NetJob::Ptr m_files_job;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user