NOISSUE Remove FTB and Curse integration

This has been requested by Slowpoke, on behalf of both FTB and OverWolf.

Import from locally installed packs from the official clients will be
the replacement, but for now, you will have to do that manually.

It was nice while it lasted.
This commit is contained in:
Petr Mrázek
2022-05-19 20:42:03 +02:00
parent 3304798aa7
commit 0a827ba70e
33 changed files with 0 additions and 3351 deletions

View File

@@ -1,63 +0,0 @@
#include "FileResolvingTask.h"
#include "Json.h"
namespace {
const char * metabase = "https://cursemeta.dries007.net";
}
Flame::FileResolvingTask::FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest& toProcess)
: m_network(network), m_toProcess(toProcess)
{
}
void Flame::FileResolvingTask::executeTask()
{
setStatus(tr("Resolving mod IDs..."));
setProgress(0, m_toProcess.files.size());
m_dljob = new NetJob("Mod id resolver", m_network);
results.resize(m_toProcess.files.size());
int index = 0;
for(auto & file: m_toProcess.files)
{
auto projectIdStr = QString::number(file.projectId);
auto fileIdStr = QString::number(file.fileId);
QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results[index]);
m_dljob->addNetAction(dl);
index ++;
}
connect(m_dljob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::netJobFinished);
m_dljob->start();
}
void Flame::FileResolvingTask::netJobFinished()
{
bool failed = false;
int index = 0;
for(auto & bytes: results)
{
auto & out = m_toProcess.files[index];
try
{
failed &= (!out.parseFromBytes(bytes));
}
catch (const JSONValidationError &e)
{
qCritical() << "Resolving of" << out.projectId << out.fileId << "failed because of a parsing error:";
qCritical() << e.cause();
qCritical() << "JSON:";
qCritical() << bytes;
failed = true;
}
index++;
}
if(!failed)
{
emitSucceeded();
}
else
{
emitFailed(tr("Some mod ID resolving tasks failed."));
}
}

View File

@@ -1,33 +0,0 @@
#pragma once
#include "tasks/Task.h"
#include "net/NetJob.h"
#include "PackManifest.h"
namespace Flame
{
class FileResolvingTask : public Task
{
Q_OBJECT
public:
explicit FileResolvingTask(shared_qobject_ptr<QNetworkAccessManager> network, Flame::Manifest &toProcess);
virtual ~FileResolvingTask() {};
const Flame::Manifest &getResults() const
{
return m_toProcess;
}
protected:
virtual void executeTask() override;
protected slots:
void netJobFinished();
private: /* data */
shared_qobject_ptr<QNetworkAccessManager> m_network;
Flame::Manifest m_toProcess;
QVector<QByteArray> results;
NetJob::Ptr m_dljob;
};
}

View File

@@ -1,92 +0,0 @@
#include "FlamePackIndex.h"
#include "Json.h"
void Flame::loadIndexedPack(Flame::IndexedPack & pack, QJsonObject & obj)
{
pack.addonId = Json::requireInteger(obj, "id");
pack.name = Json::requireString(obj, "name");
pack.websiteUrl = Json::ensureString(obj, "websiteUrl", "");
pack.description = Json::ensureString(obj, "summary", "");
bool thumbnailFound = false;
auto attachments = Json::requireArray(obj, "attachments");
for(auto attachmentRaw: attachments) {
auto attachmentObj = Json::requireObject(attachmentRaw);
bool isDefault = attachmentObj.value("isDefault").toBool(false);
if(isDefault) {
thumbnailFound = true;
pack.logoName = Json::requireString(attachmentObj, "title");
pack.logoUrl = Json::requireString(attachmentObj, "thumbnailUrl");
break;
}
}
if(!thumbnailFound) {
throw JSONValidationError(QString("Pack without an icon, skipping: %1").arg(pack.name));
}
auto authors = Json::requireArray(obj, "authors");
for(auto authorIter: authors) {
auto author = Json::requireObject(authorIter);
Flame::ModpackAuthor packAuthor;
packAuthor.name = Json::requireString(author, "name");
packAuthor.url = Json::requireString(author, "url");
pack.authors.append(packAuthor);
}
int defaultFileId = Json::requireInteger(obj, "defaultFileId");
bool found = false;
// check if there are some files before adding the pack
auto files = Json::requireArray(obj, "latestFiles");
for(auto fileIter: files) {
auto file = Json::requireObject(fileIter);
int id = Json::requireInteger(file, "id");
// NOTE: for now, ignore everything that's not the default...
if(id != defaultFileId) {
continue;
}
auto versionArray = Json::requireArray(file, "gameVersion");
if(versionArray.size() < 1) {
continue;
}
found = true;
break;
}
if(!found) {
throw JSONValidationError(QString("Pack with no good file, skipping: %1").arg(pack.name));
}
}
void Flame::loadIndexedPackVersions(Flame::IndexedPack & pack, QJsonArray & arr)
{
QVector<Flame::IndexedVersion> unsortedVersions;
for(auto versionIter: arr) {
auto version = Json::requireObject(versionIter);
Flame::IndexedVersion file;
file.addonId = pack.addonId;
file.fileId = Json::requireInteger(version, "id");
auto versionArray = Json::requireArray(version, "gameVersion");
if(versionArray.size() < 1) {
continue;
}
// pick the latest version supported
file.mcVersion = versionArray[0].toString();
file.version = Json::requireString(version, "displayName");
file.downloadUrl = Json::requireString(version, "downloadUrl");
unsortedVersions.append(file);
}
auto orderSortPredicate = [](const IndexedVersion & a, const IndexedVersion & b) -> bool
{
return a.fileId > b.fileId;
};
std::sort(unsortedVersions.begin(), unsortedVersions.end(), orderSortPredicate);
pack.versions = unsortedVersions;
pack.versionsLoaded = true;
}

View File

@@ -1,41 +0,0 @@
#pragma once
#include <QList>
#include <QMetaType>
#include <QString>
#include <QVector>
namespace Flame {
struct ModpackAuthor {
QString name;
QString url;
};
struct IndexedVersion {
int addonId;
int fileId;
QString version;
QString mcVersion;
QString downloadUrl;
};
struct IndexedPack
{
int addonId;
QString name;
QString description;
QList<ModpackAuthor> authors;
QString logoName;
QString logoUrl;
QString websiteUrl;
bool versionsLoaded = false;
QVector<IndexedVersion> versions;
};
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
void loadIndexedPackVersions(IndexedPack & m, QJsonArray & arr);
}
Q_DECLARE_METATYPE(Flame::IndexedPack)

View File

@@ -1,126 +0,0 @@
#include "PackManifest.h"
#include "Json.h"
static void loadFileV1(Flame::File & f, QJsonObject & file)
{
f.projectId = Json::requireInteger(file, "projectID");
f.fileId = Json::requireInteger(file, "fileID");
f.required = Json::ensureBoolean(file, QString("required"), true);
}
static void loadModloaderV1(Flame::Modloader & m, QJsonObject & modLoader)
{
m.id = Json::requireString(modLoader, "id");
m.primary = Json::ensureBoolean(modLoader, QString("primary"), false);
}
static void loadMinecraftV1(Flame::Minecraft & m, QJsonObject & minecraft)
{
m.version = Json::requireString(minecraft, "version");
// extra libraries... apparently only used for a custom Minecraft launcher in the 1.2.5 FTB retro pack
// intended use is likely hardcoded in the 'Flame' client, the manifest says nothing
m.libraries = Json::ensureString(minecraft, QString("libraries"), QString());
auto arr = Json::ensureArray(minecraft, "modLoaders", QJsonArray());
for (QJsonValueRef item : arr)
{
auto obj = Json::requireObject(item);
Flame::Modloader loader;
loadModloaderV1(loader, obj);
m.modLoaders.append(loader);
}
}
static void loadManifestV1(Flame::Manifest & m, QJsonObject & manifest)
{
auto mc = Json::requireObject(manifest, "minecraft");
loadMinecraftV1(m.minecraft, mc);
m.name = Json::ensureString(manifest, QString("name"), "Unnamed");
m.version = Json::ensureString(manifest, QString("version"), QString());
m.author = Json::ensureString(manifest, QString("author"), "Anonymous Coward");
auto arr = Json::ensureArray(manifest, "files", QJsonArray());
for (QJsonValueRef item : arr)
{
auto obj = Json::requireObject(item);
Flame::File file;
loadFileV1(file, obj);
m.files.append(file);
}
m.overrides = Json::ensureString(manifest, "overrides", "overrides");
}
void Flame::loadManifest(Flame::Manifest & m, const QString &filepath)
{
auto doc = Json::requireDocument(filepath);
auto obj = Json::requireObject(doc);
m.manifestType = Json::requireString(obj, "manifestType");
if(m.manifestType != "minecraftModpack")
{
throw JSONValidationError("Not a modpack manifest!");
}
m.manifestVersion = Json::requireInteger(obj, "manifestVersion");
if(m.manifestVersion != 1)
{
throw JSONValidationError(QString("Unknown manifest version (%1)").arg(m.manifestVersion));
}
loadManifestV1(m, obj);
}
bool Flame::File::parseFromBytes(const QByteArray& bytes)
{
auto doc = Json::requireDocument(bytes);
auto obj = Json::requireObject(doc);
// result code signifies true failure.
if(obj.contains("code"))
{
qCritical() << "Resolving of" << projectId << fileId << "failed because of a negative result:";
qCritical() << bytes;
return false;
}
fileName = Json::requireString(obj, "FileNameOnDisk");
QString rawUrl = Json::requireString(obj, "DownloadURL");
url = QUrl(rawUrl, QUrl::TolerantMode);
if(!url.isValid())
{
throw JSONValidationError(QString("Invalid URL: %1").arg(rawUrl));
}
// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
// It is also optional
QJsonObject projObj = Json::ensureObject(obj, "_Project", {});
if(!projObj.isEmpty())
{
QString strType = Json::ensureString(projObj, "PackageType", "mod").toLower();
if(strType == "singlefile")
{
type = File::Type::SingleFile;
}
else if(strType == "ctoc")
{
type = File::Type::Ctoc;
}
else if(strType == "cmod2")
{
type = File::Type::Cmod2;
}
else if(strType == "mod")
{
type = File::Type::Mod;
}
else if(strType == "folder")
{
type = File::Type::Folder;
}
else if(strType == "modpack")
{
type = File::Type::Modpack;
}
else
{
qCritical() << "Resolving of" << projectId << fileId << "failed because of unknown file type:" << strType;
type = File::Type::Unknown;
return false;
}
targetFolder = Json::ensureString(projObj, "Path", "mods");
}
resolved = true;
return true;
}

View File

@@ -1,62 +0,0 @@
#pragma once
#include <QString>
#include <QVector>
#include <QUrl>
namespace Flame
{
struct File
{
// NOTE: throws JSONValidationError
bool parseFromBytes(const QByteArray &bytes);
int projectId = 0;
int fileId = 0;
// NOTE: the opposite to 'optional'. This is at the time of writing unused.
bool required = true;
// our
bool resolved = false;
QString fileName;
QUrl url;
QString targetFolder = QLatin1Literal("mods");
enum class Type
{
Unknown,
Folder,
Ctoc,
SingleFile,
Cmod2,
Modpack,
Mod
} type = Type::Mod;
};
struct Modloader
{
QString id;
bool primary = false;
};
struct Minecraft
{
QString version;
QString libraries;
QVector<Flame::Modloader> modLoaders;
};
struct Manifest
{
QString manifestType;
int manifestVersion = 0;
Flame::Minecraft minecraft;
QString name;
QString version;
QString author;
QVector<Flame::File> files;
QString overrides;
};
void loadManifest(Flame::Manifest & m, const QString &filepath);
}

View File

@@ -1,259 +0,0 @@
/*
* Copyright 2020-2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright 2020-2021 Petr Mrazek <peterix@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 "FTBPackInstallTask.h"
#include "FileSystem.h"
#include "Json.h"
#include "MMCZip.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
#include "net/ChecksumValidator.h"
#include "settings/INISettingsObject.h"
#include "BuildConfig.h"
#include "Application.h"
namespace ModpacksCH {
PackInstallTask::PackInstallTask(Modpack pack, QString version, PackType type)
{
m_pack = pack;
m_version_name = version;
m_pack_type = type;
}
bool PackInstallTask::abort()
{
if(abortable)
{
return jobPtr->abort();
}
return false;
}
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;
break;
}
}
if(!found) {
emitFailed(tr("Failed to find pack version %1").arg(m_version_name));
return;
}
auto *netJob = new NetJob("ModpacksCH::VersionFetch", APPLICATION->network());
auto searchUrl = QString(BuildConfig.MODPACKSCH_API_BASE_URL + "public/%1/%2/%3")
.arg(getRealmForPackType(m_pack_type))
.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 ModpacksCH 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;
downloadPack();
}
void PackInstallTask::onDownloadFailed(QString reason)
{
jobPtr.reset();
emitFailed(reason);
}
void PackInstallTask::downloadPack()
{
setStatus(tr("Downloading mods..."));
jobPtr = new NetJob(tr("Mod download"), APPLICATION->network());
for(auto file : m_version.files) {
if(file.serverOnly) continue;
QFileInfo fileName(file.name);
auto cacheName = fileName.completeBaseName() + "-" + file.sha1 + "." + fileName.suffix();
auto entry = APPLICATION->metacache()->resolveEntry("ModpacksCHPacks", cacheName);
entry->setStale(true);
if (file.type == "cf-extract") {
filesToExtract[entry->getFullPath()] = file;
}
else {
auto relpath = FS::PathCombine("minecraft", file.path, file.name);
auto path = FS::PathCombine(m_stagingPath, relpath);
if (filesToCopy.contains(path)) {
qWarning() << "Ignoring" << file.url << "as a file of that path is already downloading.";
continue;
}
qDebug() << "Will download" << file.url << "to" << path;
filesToCopy[path] = entry->getFullPath();
}
auto dl = Net::Download::makeCached(file.url, entry);
if (!file.sha1.isEmpty()) {
auto rawSha1 = QByteArray::fromHex(file.sha1.toLatin1());
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
}
jobPtr->addNetAction(dl);
}
connect(jobPtr.get(), &NetJob::succeeded, this, [&]()
{
abortable = false;
jobPtr.reset();
install();
});
connect(jobPtr.get(), &NetJob::failed, [&](QString reason)
{
abortable = false;
jobPtr.reset();
emitFailed(reason);
});
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total)
{
abortable = true;
setProgress(current, total);
});
jobPtr->start();
}
void PackInstallTask::install()
{
if (!filesToCopy.isEmpty()) {
setStatus(tr("Copying modpack files"));
for (auto iter = filesToCopy.begin(); iter != filesToCopy.end(); iter++) {
auto& to = iter.key();
auto& from = iter.value();
FS::copy fileCopyOperation(from, to);
if (!fileCopyOperation()) {
qWarning() << "Failed to copy" << from << "to" << to;
emitFailed(tr("Failed to copy files"));
return;
}
}
}
if (!filesToExtract.isEmpty()) {
setStatus(tr("Extracting modpack files"));
for (auto iter = filesToExtract.begin(); iter != filesToExtract.end(); iter++) {
auto& filePath = iter.key();
auto& file = iter.value();
auto relpath = FS::PathCombine("minecraft", file.path);
auto path = FS::PathCombine(m_stagingPath, relpath);
if (!MMCZip::extractDir(filePath, "overrides/", path)) {
qWarning() << "Failed to extract files from" << filePath << "to" << path;
emitFailed(tr("Failed to extract files"));
return;
}
}
}
setStatus(tr("Installing modpack"));
auto instanceConfigPath = FS::PathCombine(m_stagingPath, "instance.cfg");
auto instanceSettings = std::make_shared<INISettingsObject>(instanceConfigPath);
instanceSettings->suspendSave();
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);
break;
}
}
for(auto target : m_version.targets) {
if(target.type != "modloader") continue;
if(target.name == "forge") {
components->setComponentVersion("net.minecraftforge", target.version, true);
}
else if(target.name == "fabric") {
components->setComponentVersion("net.fabricmc.fabric-loader", target.version, true);
}
}
// install any jar mods
QDir jarModsDir(FS::PathCombine(m_stagingPath, "minecraft", "jarmods"));
if (jarModsDir.exists()) {
QStringList jarMods;
for (const auto& info : jarModsDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) {
jarMods.push_back(info.absoluteFilePath());
}
components->installJarMods(jarMods);
}
components->saveNow();
instance.setName(m_instName);
instance.setIconKey(m_instIcon);
instanceSettings->resumeSave();
emitSucceeded();
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright 2020-2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright 2020-2021 Petr Mrazek <peterix@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 "FTBPackManifest.h"
#include "MCHPackType.h"
#include "InstanceTask.h"
#include "net/NetJob.h"
namespace ModpacksCH {
class PackInstallTask : public InstanceTask
{
Q_OBJECT
public:
explicit PackInstallTask(Modpack pack, QString version, PackType type = PackType::FTB);
virtual ~PackInstallTask(){}
bool canAbort() const override { return true; }
bool abort() override;
protected:
virtual void executeTask() override;
private slots:
void onDownloadSucceeded();
void onDownloadFailed(QString reason);
private:
void downloadPack();
void install();
private:
bool abortable = false;
NetJob::Ptr jobPtr;
QByteArray response;
Modpack m_pack;
QString m_version_name;
Version m_version;
PackType m_pack_type;
QMap<QString, VersionFile> filesToExtract;
QMap<QString, QString> filesToCopy;
};
}

View File

@@ -1,194 +0,0 @@
/*
* Copyright 2020-2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright 2020-2021 Petr Mrazek <peterix@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 "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");
// CurseForge packs don't have specs.
if (obj.contains("specs")) {
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 (QJsonValueRef artRaw : artArr)
{
auto artObj = Json::requireObject(artRaw);
ModpacksCH::Art art;
loadArt(art, artObj);
m.art.append(art);
}
auto authorArr = Json::requireArray(obj, "authors");
for (QJsonValueRef authorRaw : authorArr)
{
auto authorObj = Json::requireObject(authorRaw);
ModpacksCH::Author author;
loadAuthor(author, authorObj);
m.authors.append(author);
}
auto versionArr = Json::requireArray(obj, "versions");
for (QJsonValueRef versionRaw : versionArr)
{
auto versionObj = Json::requireObject(versionRaw);
ModpacksCH::VersionInfo version;
loadVersionInfo(version, versionObj);
m.versions.append(version);
}
auto tagArr = Json::requireArray(obj, "tags");
for (QJsonValueRef 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");
// This will be an integer with CurseForge packs.
auto versionVal = obj.value("version");
if (versionVal.isString()) {
a.version = versionVal.toString();
}
else if (versionVal.isDouble()) {
a.version = QString(versionVal.toInt());
}
else {
throw Json::JsonException("'version' is not a string or integer");
}
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");
// CurseForge packs don't have specs.
if (obj.contains("specs")) {
auto specs = Json::requireObject(obj, "specs");
loadSpecs(m.specs, specs);
}
auto targetArr = Json::requireArray(obj, "targets");
for (QJsonValueRef targetRaw : targetArr)
{
auto versionObj = Json::requireObject(targetRaw);
ModpacksCH::VersionTarget target;
loadVersionTarget(target, versionObj);
m.targets.append(target);
}
auto fileArr = Json::requireArray(obj, "files");
for (QJsonValueRef 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");
//}

View File

@@ -1,144 +0,0 @@
/*
* Copyright 2020-2021 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright 2020 Petr Mrazek <peterix@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 <QVector>
#include <QUrl>
#include <QJsonObject>
#include <QMetaType>
#include "MCHPackType.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
{
PackType packType = PackType::FTB;
int id = 0;
QString name;
QString synopsis;
QString description;
QString type;
bool featured = false;
int installs = 0;
int plays = 0;
int64_t updated = 0;
int64_t refreshed = 0;
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;
};
void loadModpack(Modpack & m, QJsonObject & obj);
void loadVersion(Version & m, QJsonObject & obj);
}
Q_DECLARE_METATYPE(ModpacksCH::Modpack)

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* 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 "MCHPackType.h"
#include <QString>
namespace ModpacksCH {
QString getRealmForPackType(PackType type)
{
switch (type) {
case PackType::FTB:
return "modpack";
case PackType::CurseForge:
return "curseforge";
}
return "unknown";
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2022 Jamie Mansfield <jmansfield@cadixdev.org>
*
* 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>
namespace ModpacksCH {
enum class PackType {
FTB,
CurseForge,
};
QString getRealmForPackType(PackType type);
}