@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "minecraft/mod/Mod.h"
|
||||
#include "modplatform/ResourceAPI.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
#include "modplatform/ResourceAPI.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
class ResourceDownloadTask;
|
||||
@ -12,8 +12,11 @@ class CheckUpdateTask : public Task {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckUpdateTask(QList<Mod*>& mods, std::list<Version>& mcVersions, std::optional<ResourceAPI::ModLoaderTypes> loaders, std::shared_ptr<ModFolderModel> mods_folder)
|
||||
: Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder) {};
|
||||
CheckUpdateTask(QList<Mod*>& mods,
|
||||
std::list<Version>& mcVersions,
|
||||
std::optional<ResourceAPI::ModLoaderTypes> loaders,
|
||||
std::shared_ptr<ModFolderModel> mods_folder)
|
||||
: Task(nullptr), m_mods(mods), m_game_versions(mcVersions), m_loaders(loaders), m_mods_folder(mods_folder){};
|
||||
|
||||
struct UpdatableMod {
|
||||
QString name;
|
||||
@ -25,7 +28,13 @@ class CheckUpdateTask : public Task {
|
||||
shared_qobject_ptr<ResourceDownloadTask> download;
|
||||
|
||||
public:
|
||||
UpdatableMod(QString name, QString old_h, QString old_v, QString new_v, QString changelog, ModPlatform::ResourceProvider p, shared_qobject_ptr<ResourceDownloadTask> t)
|
||||
UpdatableMod(QString name,
|
||||
QString old_h,
|
||||
QString old_v,
|
||||
QString new_v,
|
||||
QString changelog,
|
||||
ModPlatform::ResourceProvider p,
|
||||
shared_qobject_ptr<ResourceDownloadTask> t)
|
||||
: name(name), old_hash(old_h), old_version(old_v), new_version(new_v), changelog(changelog), provider(p), download(t)
|
||||
{}
|
||||
};
|
||||
|
@ -35,10 +35,7 @@ class EnsureMetadataTask : public Task {
|
||||
auto flameProjectsTask() -> Task::Ptr;
|
||||
|
||||
// Helpers
|
||||
enum class RemoveFromList {
|
||||
Yes,
|
||||
No
|
||||
};
|
||||
enum class RemoveFromList { Yes, No };
|
||||
void emitReady(Mod*, QString key = {}, RemoveFromList = RemoveFromList::Yes);
|
||||
void emitFail(Mod*, QString key = {}, RemoveFromList = RemoveFromList::Yes);
|
||||
|
||||
|
@ -1,20 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
|
@ -144,12 +144,10 @@ inline auto getOverrideDeps() -> QList<OverrideDep>
|
||||
|
||||
{ "qvIfYCYJ", "P7dR8mSH", "API", ModPlatform::ResourceProvider::MODRINTH },
|
||||
{ "lwVhp9o5", "Ha28R6CL", "KotlinLibraries", ModPlatform::ResourceProvider::MODRINTH } };
|
||||
|
||||
}
|
||||
|
||||
QString getMetaURL(ResourceProvider provider, QVariant projectID);
|
||||
|
||||
|
||||
} // namespace ModPlatform
|
||||
|
||||
Q_DECLARE_METATYPE(ModPlatform::IndexedPack)
|
||||
|
@ -131,12 +131,14 @@ class ResourceAPI {
|
||||
qWarning() << "TODO: ResourceAPI::searchProjects";
|
||||
return nullptr;
|
||||
}
|
||||
[[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId, [[maybe_unused]] std::shared_ptr<QByteArray> response) const
|
||||
[[nodiscard]] virtual Task::Ptr getProject([[maybe_unused]] QString addonId,
|
||||
[[maybe_unused]] std::shared_ptr<QByteArray> response) const
|
||||
{
|
||||
qWarning() << "TODO: ResourceAPI::getProject";
|
||||
return nullptr;
|
||||
}
|
||||
[[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds, [[maybe_unused]] std::shared_ptr<QByteArray> response) const
|
||||
[[nodiscard]] virtual Task::Ptr getProjects([[maybe_unused]] QStringList addonIds,
|
||||
[[maybe_unused]] std::shared_ptr<QByteArray> response) const
|
||||
{
|
||||
qWarning() << "TODO: ResourceAPI::getProjects";
|
||||
return nullptr;
|
||||
|
@ -21,23 +21,20 @@
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
static void loadIndexedVersion(ATLauncher::IndexedVersion & v, QJsonObject & obj)
|
||||
static void loadIndexedVersion(ATLauncher::IndexedVersion& v, QJsonObject& obj)
|
||||
{
|
||||
v.version = Json::requireString(obj, "version");
|
||||
v.minecraft = Json::requireString(obj, "minecraft");
|
||||
}
|
||||
|
||||
void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack & m, QJsonObject & obj)
|
||||
void ATLauncher::loadIndexedPack(ATLauncher::IndexedPack& m, QJsonObject& obj)
|
||||
{
|
||||
m.id = Json::requireInteger(obj, "id");
|
||||
m.position = Json::requireInteger(obj, "position");
|
||||
m.name = Json::requireString(obj, "name");
|
||||
m.type = Json::requireString(obj, "type") == "private" ?
|
||||
ATLauncher::PackType::Private :
|
||||
ATLauncher::PackType::Public;
|
||||
m.type = Json::requireString(obj, "type") == "private" ? ATLauncher::PackType::Private : ATLauncher::PackType::Public;
|
||||
auto versionsArr = Json::requireArray(obj, "versions");
|
||||
for (const auto versionRaw : versionsArr)
|
||||
{
|
||||
for (const auto versionRaw : versionsArr) {
|
||||
auto versionObj = Json::requireObject(versionRaw);
|
||||
ATLauncher::IndexedVersion version;
|
||||
loadIndexedVersion(version, versionObj);
|
||||
|
@ -18,21 +18,18 @@
|
||||
|
||||
#include "ATLPackManifest.h"
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace ATLauncher
|
||||
{
|
||||
namespace ATLauncher {
|
||||
|
||||
struct IndexedVersion
|
||||
{
|
||||
struct IndexedVersion {
|
||||
QString version;
|
||||
QString minecraft;
|
||||
};
|
||||
|
||||
struct IndexedPack
|
||||
{
|
||||
struct IndexedPack {
|
||||
int id;
|
||||
int position;
|
||||
QString name;
|
||||
@ -44,7 +41,7 @@ struct IndexedPack
|
||||
QString safeName;
|
||||
};
|
||||
|
||||
void loadIndexedPack(IndexedPack & m, QJsonObject & obj);
|
||||
}
|
||||
void loadIndexedPack(IndexedPack& m, QJsonObject& obj);
|
||||
} // namespace ATLauncher
|
||||
|
||||
Q_DECLARE_METATYPE(ATLauncher::IndexedPack)
|
||||
|
@ -40,29 +40,29 @@
|
||||
|
||||
#include <quazip/quazip.h>
|
||||
|
||||
#include "MMCZip.h"
|
||||
#include "minecraft/OneSixVersionFormat.h"
|
||||
#include "Version.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Json.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
#include "MMCZip.h"
|
||||
#include "Version.h"
|
||||
#include "meta/Index.h"
|
||||
#include "meta/Version.h"
|
||||
#include "meta/VersionList.h"
|
||||
#include "minecraft/MinecraftInstance.h"
|
||||
#include "minecraft/OneSixVersionFormat.h"
|
||||
#include "minecraft/PackProfile.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
#include "BuildConfig.h"
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
namespace ATLauncher {
|
||||
|
||||
static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString& version);
|
||||
|
||||
PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packName, QString version, InstallMode installMode)
|
||||
PackInstallTask::PackInstallTask(UserInteractionSupport* support, QString packName, QString version, InstallMode installMode)
|
||||
{
|
||||
m_support = support;
|
||||
m_pack_name = packName;
|
||||
@ -73,8 +73,7 @@ PackInstallTask::PackInstallTask(UserInteractionSupport *support, QString packNa
|
||||
|
||||
bool PackInstallTask::abort()
|
||||
{
|
||||
if(abortable)
|
||||
{
|
||||
if (abortable) {
|
||||
return jobPtr->abort();
|
||||
}
|
||||
return false;
|
||||
@ -84,7 +83,7 @@ void PackInstallTask::executeTask()
|
||||
{
|
||||
qDebug() << "PackInstallTask::executeTask: " << QThread::currentThreadId();
|
||||
NetJob::Ptr netJob{ new NetJob("ATLauncher::VersionFetch", APPLICATION->network()) };
|
||||
auto searchUrl =
|
||||
auto searchUrl =
|
||||
QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.json").arg(m_pack_safe_name).arg(m_version_name);
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(QUrl(searchUrl), response));
|
||||
|
||||
@ -112,12 +111,9 @@ void PackInstallTask::onDownloadSucceeded()
|
||||
auto obj = doc.object();
|
||||
|
||||
ATLauncher::PackVersion version;
|
||||
try
|
||||
{
|
||||
try {
|
||||
ATLauncher::loadVersion(version, obj);
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
} catch (const JSONValidationError& e) {
|
||||
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||
return;
|
||||
}
|
||||
@ -128,20 +124,20 @@ void PackInstallTask::onDownloadSucceeded()
|
||||
bool resetDirectory;
|
||||
|
||||
switch (m_install_mode) {
|
||||
case InstallMode::Reinstall:
|
||||
case InstallMode::Update:
|
||||
message = m_version.messages.update;
|
||||
resetDirectory = true;
|
||||
break;
|
||||
case InstallMode::Reinstall:
|
||||
case InstallMode::Update:
|
||||
message = m_version.messages.update;
|
||||
resetDirectory = true;
|
||||
break;
|
||||
|
||||
case InstallMode::Install:
|
||||
message = m_version.messages.install;
|
||||
resetDirectory = false;
|
||||
break;
|
||||
case InstallMode::Install:
|
||||
message = m_version.messages.install;
|
||||
resetDirectory = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
emitFailed(tr("Unsupported installation mode"));
|
||||
return;
|
||||
default:
|
||||
emitFailed(tr("Unsupported installation mode"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Display message if one exists
|
||||
@ -159,10 +155,9 @@ void PackInstallTask::onDownloadSucceeded()
|
||||
deleteExistingFiles();
|
||||
}
|
||||
|
||||
if(m_version.noConfigs) {
|
||||
if (m_version.noConfigs) {
|
||||
downloadMods();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
installConfigs();
|
||||
}
|
||||
}
|
||||
@ -214,11 +209,9 @@ void PackInstallTask::deleteExistingFiles()
|
||||
|
||||
if (base == "root") {
|
||||
return minecraftPath;
|
||||
}
|
||||
else if (base == "config") {
|
||||
} else if (base == "config") {
|
||||
return FS::PathCombine(minecraftPath, "config");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
qWarning() << "Unrecognised base path" << base;
|
||||
return minecraftPath;
|
||||
}
|
||||
@ -340,19 +333,18 @@ QString PackInstallTask::getDirForModType(ModType type, QString raw)
|
||||
|
||||
QString PackInstallTask::getVersionForLoader(QString uid)
|
||||
{
|
||||
if(m_version.loader.recommended || m_version.loader.latest || m_version.loader.choose) {
|
||||
if (m_version.loader.recommended || m_version.loader.latest || m_version.loader.choose) {
|
||||
auto vlist = APPLICATION->metadataIndex()->get(uid);
|
||||
if(!vlist)
|
||||
{
|
||||
if (!vlist) {
|
||||
emitFailed(tr("Failed to get local metadata index for %1").arg(uid));
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
if(!vlist->isLoaded()) {
|
||||
if (!vlist->isLoaded()) {
|
||||
vlist->load(Net::Mode::Online);
|
||||
}
|
||||
|
||||
if(m_version.loader.recommended || m_version.loader.latest) {
|
||||
if (m_version.loader.recommended || m_version.loader.latest) {
|
||||
for (int i = 0; i < vlist->versions().size(); i++) {
|
||||
auto version = vlist->versions().at(i);
|
||||
auto reqs = version->requiredSet();
|
||||
@ -361,16 +353,17 @@ QString PackInstallTask::getVersionForLoader(QString uid)
|
||||
// not all mod loaders depend on a given Minecraft version, so we won't do this
|
||||
// filtering for those loaders.
|
||||
if (m_version.loader.type != "fabric") {
|
||||
auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require &req) {
|
||||
return req.uid == "net.minecraft";
|
||||
});
|
||||
if (iter == reqs.end()) continue;
|
||||
if (iter->equalsVersion != m_version.minecraft) continue;
|
||||
auto iter = std::find_if(reqs.begin(), reqs.end(), [](const Meta::Require& req) { return req.uid == "net.minecraft"; });
|
||||
if (iter == reqs.end())
|
||||
continue;
|
||||
if (iter->equalsVersion != m_version.minecraft)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_version.loader.recommended) {
|
||||
// first recommended build we find, we use.
|
||||
if (!version->isRecommended()) continue;
|
||||
if (!version->isRecommended())
|
||||
continue;
|
||||
}
|
||||
|
||||
return version->descriptor();
|
||||
@ -378,8 +371,7 @@ QString PackInstallTask::getVersionForLoader(QString uid)
|
||||
|
||||
emitFailed(tr("Failed to find version for %1 loader").arg(m_version.loader.type));
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
else if(m_version.loader.choose) {
|
||||
} else if (m_version.loader.choose) {
|
||||
// Fabric Loader doesn't depend on a given Minecraft version.
|
||||
if (m_version.loader.type == "fabric") {
|
||||
return m_support->chooseVersion(vlist, Q_NULLPTR);
|
||||
@ -416,15 +408,14 @@ QString PackInstallTask::detectLibrary(VersionLibrary library)
|
||||
return group + ":" + artefact + ":" + version;
|
||||
}
|
||||
|
||||
if(library.file.contains("-")) {
|
||||
if (library.file.contains("-")) {
|
||||
auto lastSlash = library.file.lastIndexOf("-");
|
||||
auto name = library.file.mid(0, lastSlash);
|
||||
auto version = library.file.mid(lastSlash + 1).remove(".jar");
|
||||
|
||||
if(name == QString("guava")) {
|
||||
if (name == QString("guava")) {
|
||||
return "com.google.guava:guava:" + version;
|
||||
}
|
||||
else if(name == QString("commons-lang3")) {
|
||||
} else if (name == QString("commons-lang3")) {
|
||||
return "org.apache.commons:commons-lang3:" + version;
|
||||
}
|
||||
}
|
||||
@ -434,22 +425,22 @@ QString PackInstallTask::detectLibrary(VersionLibrary library)
|
||||
|
||||
bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared_ptr<PackProfile> profile)
|
||||
{
|
||||
if(m_version.libraries.isEmpty()) {
|
||||
if (m_version.libraries.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<GradleSpecifier> exempt;
|
||||
for(const auto & componentUid : componentsToInstall.keys()) {
|
||||
for (const auto& componentUid : componentsToInstall.keys()) {
|
||||
auto componentVersion = componentsToInstall.value(componentUid);
|
||||
|
||||
for(const auto & library : componentVersion->data()->libraries) {
|
||||
for (const auto& library : componentVersion->data()->libraries) {
|
||||
GradleSpecifier lib(library->rawName());
|
||||
exempt.append(lib);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for(const auto & library : minecraftVersion->data()->libraries) {
|
||||
for (const auto& library : minecraftVersion->data()->libraries) {
|
||||
GradleSpecifier lib(library->rawName());
|
||||
exempt.append(lib);
|
||||
}
|
||||
@ -460,8 +451,7 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared
|
||||
auto target_id = "org.multimc.atlauncher." + id;
|
||||
|
||||
auto patchDir = FS::PathCombine(instanceRoot, "patches");
|
||||
if(!FS::ensureFolderPathExists(patchDir))
|
||||
{
|
||||
if (!FS::ensureFolderPathExists(patchDir)) {
|
||||
return false;
|
||||
}
|
||||
auto patchFileName = FS::PathCombine(patchDir, target_id + ".json");
|
||||
@ -470,38 +460,24 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared
|
||||
f->name = m_pack_name + " " + m_version_name + " (libraries)";
|
||||
|
||||
const static QMap<QString, QString> liteLoaderMap = {
|
||||
{ "61179803bcd5fb7790789b790908663d", "1.12-SNAPSHOT" },
|
||||
{ "1420785ecbfed5aff4a586c5c9dd97eb", "1.12.2-SNAPSHOT" },
|
||||
{ "073f68e2fcb518b91fd0d99462441714", "1.6.2_03" },
|
||||
{ "10a15b52fc59b1bfb9c05b56de1097d6", "1.6.2_02" },
|
||||
{ "b52f90f08303edd3d4c374e268a5acf1", "1.6.2_04" },
|
||||
{ "ea747e24e03e24b7cad5bc8a246e0319", "1.6.2_01" },
|
||||
{ "55785ccc82c07ff0ba038fe24be63ea2", "1.7.10_01" },
|
||||
{ "63ada46e033d0cb6782bada09ad5ca4e", "1.7.10_04" },
|
||||
{ "7983e4b28217c9ae8569074388409c86", "1.7.10_03" },
|
||||
{ "c09882458d74fe0697c7681b8993097e", "1.7.10_02" },
|
||||
{ "db7235aefd407ac1fde09a7baba50839", "1.7.10_00" },
|
||||
{ "6e9028816027f53957bd8fcdfabae064", "1.8" },
|
||||
{ "5e732dc446f9fe2abe5f9decaec40cde", "1.10-SNAPSHOT" },
|
||||
{ "3a98b5ed95810bf164e71c1a53be568d", "1.11.2-SNAPSHOT" },
|
||||
{ "ba8e6285966d7d988a96496f48cbddaa", "1.8.9-SNAPSHOT" },
|
||||
{ "8524af3ac3325a82444cc75ae6e9112f", "1.11-SNAPSHOT" },
|
||||
{ "53639d52340479ccf206a04f5e16606f", "1.5.2_01" },
|
||||
{ "1fcdcf66ce0a0806b7ad8686afdce3f7", "1.6.4_00" },
|
||||
{ "531c116f71ae2b11033f9a11a0f8e668", "1.6.4_01" },
|
||||
{ "4009eeb99c9068f608d3483a6439af88", "1.7.2_03" },
|
||||
{ "66f343354b8417abce1a10d557d2c6e9", "1.7.2_04" },
|
||||
{ "ab554c21f28fbc4ae9b098bcb5f4cceb", "1.7.2_05" },
|
||||
{ "e1d76a05a3723920e2f80a5e66c45f16", "1.7.2_02" },
|
||||
{ "00318cb0c787934d523f63cdfe8ddde4", "1.9-SNAPSHOT" },
|
||||
{ "986fd1ee9525cb0dcab7609401cef754", "1.9.4-SNAPSHOT" },
|
||||
{ "571ad5e6edd5ff40259570c9be588bb5", "1.9.4" },
|
||||
{ "1cdd72f7232e45551f16cc8ffd27ccf3", "1.10.2-SNAPSHOT" },
|
||||
{ "8a7c21f32d77ee08b393dd3921ced8eb", "1.10.2" },
|
||||
{ "b9bef8abc8dc309069aeba6fbbe58980", "1.12.1-SNAPSHOT" }
|
||||
{ "61179803bcd5fb7790789b790908663d", "1.12-SNAPSHOT" }, { "1420785ecbfed5aff4a586c5c9dd97eb", "1.12.2-SNAPSHOT" },
|
||||
{ "073f68e2fcb518b91fd0d99462441714", "1.6.2_03" }, { "10a15b52fc59b1bfb9c05b56de1097d6", "1.6.2_02" },
|
||||
{ "b52f90f08303edd3d4c374e268a5acf1", "1.6.2_04" }, { "ea747e24e03e24b7cad5bc8a246e0319", "1.6.2_01" },
|
||||
{ "55785ccc82c07ff0ba038fe24be63ea2", "1.7.10_01" }, { "63ada46e033d0cb6782bada09ad5ca4e", "1.7.10_04" },
|
||||
{ "7983e4b28217c9ae8569074388409c86", "1.7.10_03" }, { "c09882458d74fe0697c7681b8993097e", "1.7.10_02" },
|
||||
{ "db7235aefd407ac1fde09a7baba50839", "1.7.10_00" }, { "6e9028816027f53957bd8fcdfabae064", "1.8" },
|
||||
{ "5e732dc446f9fe2abe5f9decaec40cde", "1.10-SNAPSHOT" }, { "3a98b5ed95810bf164e71c1a53be568d", "1.11.2-SNAPSHOT" },
|
||||
{ "ba8e6285966d7d988a96496f48cbddaa", "1.8.9-SNAPSHOT" }, { "8524af3ac3325a82444cc75ae6e9112f", "1.11-SNAPSHOT" },
|
||||
{ "53639d52340479ccf206a04f5e16606f", "1.5.2_01" }, { "1fcdcf66ce0a0806b7ad8686afdce3f7", "1.6.4_00" },
|
||||
{ "531c116f71ae2b11033f9a11a0f8e668", "1.6.4_01" }, { "4009eeb99c9068f608d3483a6439af88", "1.7.2_03" },
|
||||
{ "66f343354b8417abce1a10d557d2c6e9", "1.7.2_04" }, { "ab554c21f28fbc4ae9b098bcb5f4cceb", "1.7.2_05" },
|
||||
{ "e1d76a05a3723920e2f80a5e66c45f16", "1.7.2_02" }, { "00318cb0c787934d523f63cdfe8ddde4", "1.9-SNAPSHOT" },
|
||||
{ "986fd1ee9525cb0dcab7609401cef754", "1.9.4-SNAPSHOT" }, { "571ad5e6edd5ff40259570c9be588bb5", "1.9.4" },
|
||||
{ "1cdd72f7232e45551f16cc8ffd27ccf3", "1.10.2-SNAPSHOT" }, { "8a7c21f32d77ee08b393dd3921ced8eb", "1.10.2" },
|
||||
{ "b9bef8abc8dc309069aeba6fbbe58980", "1.12.1-SNAPSHOT" }
|
||||
};
|
||||
|
||||
for(const auto & lib : m_version.libraries) {
|
||||
for (const auto& lib : m_version.libraries) {
|
||||
// If the library is LiteLoader, we need to ignore it and handle it separately.
|
||||
if (liteLoaderMap.contains(lib.md5)) {
|
||||
auto ver = getComponentVersion("com.mumfrey.liteloader", liteLoaderMap.value(lib.md5));
|
||||
@ -515,18 +491,19 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared
|
||||
GradleSpecifier libSpecifier(libName);
|
||||
|
||||
bool libExempt = false;
|
||||
for(const auto & existingLib : exempt) {
|
||||
if(libSpecifier.matchName(existingLib)) {
|
||||
for (const auto& existingLib : exempt) {
|
||||
if (libSpecifier.matchName(existingLib)) {
|
||||
// If the pack specifies a newer version of the lib, use that!
|
||||
libExempt = Version(libSpecifier.version()) >= Version(existingLib.version());
|
||||
}
|
||||
}
|
||||
if(libExempt) continue;
|
||||
if (libExempt)
|
||||
continue;
|
||||
|
||||
auto library = std::make_shared<Library>();
|
||||
library->setRawName(libName);
|
||||
|
||||
switch(lib.download) {
|
||||
switch (lib.download) {
|
||||
case DownloadType::Server:
|
||||
library->setAbsoluteUrl(BuildConfig.ATL_DOWNLOAD_SERVER_URL + lib.url);
|
||||
break;
|
||||
@ -542,15 +519,13 @@ bool PackInstallTask::createLibrariesComponent(QString instanceRoot, std::shared
|
||||
f->libraries.append(library);
|
||||
}
|
||||
|
||||
if(f->libraries.isEmpty()) {
|
||||
if (f->libraries.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QFile file(patchFileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
qCritical() << "Error opening" << file.fileName()
|
||||
<< "for reading:" << file.errorString();
|
||||
if (!file.open(QFile::WriteOnly)) {
|
||||
qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString();
|
||||
return false;
|
||||
}
|
||||
file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
|
||||
@ -595,18 +570,17 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr<
|
||||
auto target_id = "org.multimc.atlauncher." + id;
|
||||
|
||||
auto patchDir = FS::PathCombine(instanceRoot, "patches");
|
||||
if(!FS::ensureFolderPathExists(patchDir))
|
||||
{
|
||||
if (!FS::ensureFolderPathExists(patchDir)) {
|
||||
return false;
|
||||
}
|
||||
auto patchFileName = FS::PathCombine(patchDir, target_id + ".json");
|
||||
|
||||
QStringList mainClasses;
|
||||
QStringList tweakers;
|
||||
for(const auto & componentUid : componentsToInstall.keys()) {
|
||||
for (const auto& componentUid : componentsToInstall.keys()) {
|
||||
auto componentVersion = componentsToInstall.value(componentUid);
|
||||
|
||||
if(componentVersion->data()->mainClass != QString("")) {
|
||||
if (componentVersion->data()->mainClass != QString("")) {
|
||||
mainClasses.append(componentVersion->data()->mainClass);
|
||||
}
|
||||
tweakers.append(componentVersion->data()->addTweakers);
|
||||
@ -621,25 +595,24 @@ bool PackInstallTask::createPackComponent(QString instanceRoot, std::shared_ptr<
|
||||
// Parse out tweakers
|
||||
auto args = extraArguments.split(" ");
|
||||
QString previous;
|
||||
for(auto arg : args) {
|
||||
if(arg.startsWith("--tweakClass=") || previous == "--tweakClass") {
|
||||
for (auto arg : args) {
|
||||
if (arg.startsWith("--tweakClass=") || previous == "--tweakClass") {
|
||||
auto tweakClass = arg.remove("--tweakClass=");
|
||||
if(tweakers.contains(tweakClass)) continue;
|
||||
if (tweakers.contains(tweakClass))
|
||||
continue;
|
||||
|
||||
f->addTweakers.append(tweakClass);
|
||||
}
|
||||
previous = arg;
|
||||
}
|
||||
|
||||
if(f->mainClass == QString() && f->addTweakers.isEmpty()) {
|
||||
if (f->mainClass == QString() && f->addTweakers.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QFile file(patchFileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
qCritical() << "Error opening" << file.fileName()
|
||||
<< "for reading:" << file.errorString();
|
||||
if (!file.open(QFile::WriteOnly)) {
|
||||
qCritical() << "Error opening" << file.fileName() << "for reading:" << file.errorString();
|
||||
return false;
|
||||
}
|
||||
file.write(OneSixVersionFormat::versionFileToJson(f).toJson());
|
||||
@ -656,8 +629,7 @@ void PackInstallTask::installConfigs()
|
||||
jobPtr.reset(new NetJob(tr("Config download"), APPLICATION->network()));
|
||||
|
||||
auto path = QString("Configs/%1/%2.zip").arg(m_pack_safe_name).arg(m_version_name);
|
||||
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.zip")
|
||||
.arg(m_pack_safe_name).arg(m_version_name);
|
||||
auto url = QString(BuildConfig.ATL_DOWNLOAD_SERVER_URL + "packs/%1/versions/%2/Configs.zip").arg(m_pack_safe_name).arg(m_version_name);
|
||||
auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", path);
|
||||
entry->setStale(true);
|
||||
|
||||
@ -669,25 +641,22 @@ void PackInstallTask::installConfigs()
|
||||
jobPtr->addNetAction(dl);
|
||||
archivePath = entry->getFullPath();
|
||||
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, [&]()
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, [&]() {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
extractConfigs();
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason)
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason) {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total)
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
|
||||
abortable = true;
|
||||
setProgress(current, total);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
|
||||
connect(jobPtr.get(), &NetJob::aborted, [&]{
|
||||
connect(jobPtr.get(), &NetJob::aborted, [&] {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitAborted();
|
||||
@ -704,25 +673,20 @@ void PackInstallTask::extractConfigs()
|
||||
QDir extractDir(m_stagingPath);
|
||||
|
||||
QuaZip packZip(archivePath);
|
||||
if(!packZip.open(QuaZip::mdUnzip))
|
||||
{
|
||||
if (!packZip.open(QuaZip::mdUnzip)) {
|
||||
emitFailed(tr("Failed to open pack configs %1!").arg(archivePath));
|
||||
return;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload<QString, QString>::of(MMCZip::extractDir), archivePath, extractDir.absolutePath() + "/minecraft");
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), QOverload<QString, QString>::of(MMCZip::extractDir), archivePath,
|
||||
extractDir.absolutePath() + "/minecraft");
|
||||
#else
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/minecraft");
|
||||
m_extractFuture =
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, archivePath, extractDir.absolutePath() + "/minecraft");
|
||||
#endif
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, [&]()
|
||||
{
|
||||
downloadMods();
|
||||
});
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]()
|
||||
{
|
||||
emitAborted();
|
||||
});
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, [&]() { downloadMods(); });
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]() { emitAborted(); });
|
||||
m_extractFutureWatcher.setFuture(m_extractFuture);
|
||||
}
|
||||
|
||||
@ -753,15 +717,17 @@ void PackInstallTask::downloadMods()
|
||||
|
||||
jarmods.clear();
|
||||
jobPtr.reset(new NetJob(tr("Mod download"), APPLICATION->network()));
|
||||
for(const auto& mod : m_version.mods) {
|
||||
for (const auto& mod : m_version.mods) {
|
||||
// skip non-client mods
|
||||
if(!mod.client) continue;
|
||||
if (!mod.client)
|
||||
continue;
|
||||
|
||||
// skip optional mods that were not selected
|
||||
if(mod.optional && !selectedMods.contains(mod.name)) continue;
|
||||
if (mod.optional && !selectedMods.contains(mod.name))
|
||||
continue;
|
||||
|
||||
QString url;
|
||||
switch(mod.download) {
|
||||
switch (mod.download) {
|
||||
case DownloadType::Server:
|
||||
url = BuildConfig.ATL_DOWNLOAD_SERVER_URL + mod.url;
|
||||
break;
|
||||
@ -790,8 +756,7 @@ void PackInstallTask::downloadMods()
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5));
|
||||
}
|
||||
jobPtr->addNetAction(dl);
|
||||
}
|
||||
else if(mod.type == ModType::Decomp) {
|
||||
} else if (mod.type == ModType::Decomp) {
|
||||
auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName);
|
||||
entry->setStale(true);
|
||||
modsToDecomp.insert(entry->getFullPath(), mod);
|
||||
@ -802,10 +767,10 @@ void PackInstallTask::downloadMods()
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Md5, rawMd5));
|
||||
}
|
||||
jobPtr->addNetAction(dl);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
auto relpath = getDirForModType(mod.type, mod.type_raw);
|
||||
if(relpath == Q_NULLPTR) continue;
|
||||
if (relpath == Q_NULLPTR)
|
||||
continue;
|
||||
|
||||
auto entry = APPLICATION->metacache()->resolveEntry("ATLauncherPacks", cacheName);
|
||||
entry->setStale(true);
|
||||
@ -819,7 +784,7 @@ void PackInstallTask::downloadMods()
|
||||
|
||||
auto path = FS::PathCombine(m_stagingPath, "minecraft", relpath, mod.file);
|
||||
|
||||
if(mod.type == ModType::Forge) {
|
||||
if (mod.type == ModType::Forge) {
|
||||
auto ver = getComponentVersion("net.minecraftforge", mod.version);
|
||||
if (ver) {
|
||||
componentsToInstall.insert("net.minecraftforge", ver);
|
||||
@ -830,7 +795,7 @@ void PackInstallTask::downloadMods()
|
||||
jarmods.push_back(path);
|
||||
}
|
||||
|
||||
if(mod.type == ModType::Jar) {
|
||||
if (mod.type == ModType::Jar) {
|
||||
qDebug() << "Jarmod: " + path;
|
||||
jarmods.push_back(path);
|
||||
}
|
||||
@ -842,21 +807,18 @@ void PackInstallTask::downloadMods()
|
||||
}
|
||||
|
||||
connect(jobPtr.get(), &NetJob::succeeded, this, &PackInstallTask::onModsDownloaded);
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason)
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::failed, [&](QString reason) {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitFailed(reason);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total)
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
|
||||
setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
|
||||
abortable = true;
|
||||
setProgress(current, total);
|
||||
});
|
||||
connect(jobPtr.get(), &NetJob::stepProgress, this, &PackInstallTask::propagateStepProgress);
|
||||
connect(jobPtr.get(), &NetJob::aborted, [&]
|
||||
{
|
||||
connect(jobPtr.get(), &NetJob::aborted, [&] {
|
||||
abortable = false;
|
||||
jobPtr.reset();
|
||||
emitAborted();
|
||||
@ -865,60 +827,56 @@ void PackInstallTask::downloadMods()
|
||||
jobPtr->start();
|
||||
}
|
||||
|
||||
void PackInstallTask::onModsDownloaded() {
|
||||
void PackInstallTask::onModsDownloaded()
|
||||
{
|
||||
abortable = false;
|
||||
|
||||
qDebug() << "PackInstallTask::onModsDownloaded: " << QThread::currentThreadId();
|
||||
jobPtr.reset();
|
||||
|
||||
if(!modsToExtract.empty() || !modsToDecomp.empty() || !modsToCopy.empty()) {
|
||||
if (!modsToExtract.empty() || !modsToDecomp.empty() || !modsToCopy.empty()) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), &PackInstallTask::extractMods, this, modsToExtract, modsToDecomp, modsToCopy);
|
||||
m_modExtractFuture =
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), &PackInstallTask::extractMods, this, modsToExtract, modsToDecomp, modsToCopy);
|
||||
#else
|
||||
m_modExtractFuture = QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy);
|
||||
m_modExtractFuture =
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), this, &PackInstallTask::extractMods, modsToExtract, modsToDecomp, modsToCopy);
|
||||
#endif
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &PackInstallTask::onModsExtracted);
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]()
|
||||
{
|
||||
emitAborted();
|
||||
});
|
||||
connect(&m_modExtractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, [&]() { emitAborted(); });
|
||||
m_modExtractFutureWatcher.setFuture(m_modExtractFuture);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
install();
|
||||
}
|
||||
}
|
||||
|
||||
void PackInstallTask::onModsExtracted() {
|
||||
void PackInstallTask::onModsExtracted()
|
||||
{
|
||||
qDebug() << "PackInstallTask::onModsExtracted: " << QThread::currentThreadId();
|
||||
if(m_modExtractFuture.result()) {
|
||||
if (m_modExtractFuture.result()) {
|
||||
install();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
emitFailed(tr("Failed to extract mods..."));
|
||||
}
|
||||
}
|
||||
|
||||
bool PackInstallTask::extractMods(
|
||||
const QMap<QString, VersionMod> &toExtract,
|
||||
const QMap<QString, VersionMod> &toDecomp,
|
||||
const QMap<QString, QString> &toCopy
|
||||
) {
|
||||
bool PackInstallTask::extractMods(const QMap<QString, VersionMod>& toExtract,
|
||||
const QMap<QString, VersionMod>& toDecomp,
|
||||
const QMap<QString, QString>& toCopy)
|
||||
{
|
||||
qDebug() << "PackInstallTask::extractMods: " << QThread::currentThreadId();
|
||||
|
||||
setStatus(tr("Extracting mods..."));
|
||||
for (auto iter = toExtract.begin(); iter != toExtract.end(); iter++) {
|
||||
auto &modPath = iter.key();
|
||||
auto &mod = iter.value();
|
||||
auto& modPath = iter.key();
|
||||
auto& mod = iter.value();
|
||||
|
||||
QString extractToDir;
|
||||
if(mod.type == ModType::Extract) {
|
||||
if (mod.type == ModType::Extract) {
|
||||
extractToDir = getDirForModType(mod.extractTo, mod.extractTo_raw);
|
||||
}
|
||||
else if(mod.type == ModType::TexturePackExtract) {
|
||||
} else if (mod.type == ModType::TexturePackExtract) {
|
||||
extractToDir = FS::PathCombine("texturepacks", "extracted");
|
||||
}
|
||||
else if(mod.type == ModType::ResourcePackExtract) {
|
||||
} else if (mod.type == ModType::ResourcePackExtract) {
|
||||
extractToDir = FS::PathCombine("resourcepacks", "extracted");
|
||||
}
|
||||
|
||||
@ -926,36 +884,36 @@ bool PackInstallTask::extractMods(
|
||||
auto extractToPath = FS::PathCombine(extractDir.absolutePath(), "minecraft", extractToDir);
|
||||
|
||||
QString folderToExtract = "";
|
||||
if(mod.type == ModType::Extract) {
|
||||
if (mod.type == ModType::Extract) {
|
||||
folderToExtract = mod.extractFolder;
|
||||
folderToExtract.remove(QRegularExpression("^/"));
|
||||
}
|
||||
|
||||
qDebug() << "Extracting " + mod.file + " to " + extractToDir;
|
||||
if(!MMCZip::extractDir(modPath, folderToExtract, extractToPath)) {
|
||||
if (!MMCZip::extractDir(modPath, folderToExtract, extractToPath)) {
|
||||
// assume error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = toDecomp.begin(); iter != toDecomp.end(); iter++) {
|
||||
auto &modPath = iter.key();
|
||||
auto &mod = iter.value();
|
||||
auto& modPath = iter.key();
|
||||
auto& mod = iter.value();
|
||||
auto extractToDir = getDirForModType(mod.decompType, mod.decompType_raw);
|
||||
|
||||
QDir extractDir(m_stagingPath);
|
||||
auto extractToPath = FS::PathCombine(extractDir.absolutePath(), "minecraft", extractToDir, mod.decompFile);
|
||||
|
||||
qDebug() << "Extracting " + mod.decompFile + " to " + extractToDir;
|
||||
if(!MMCZip::extractFile(modPath, mod.decompFile, extractToPath)) {
|
||||
if (!MMCZip::extractFile(modPath, mod.decompFile, extractToPath)) {
|
||||
qWarning() << "Failed to extract" << mod.decompFile;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = toCopy.begin(); iter != toCopy.end(); iter++) {
|
||||
auto &from = iter.key();
|
||||
auto &to = iter.value();
|
||||
auto& from = iter.key();
|
||||
auto& to = iter.value();
|
||||
|
||||
// If the file already exists, assume the mod is the correct copy - and remove
|
||||
// the copy from the Configs.zip
|
||||
@ -968,7 +926,7 @@ bool PackInstallTask::extractMods(
|
||||
}
|
||||
|
||||
FS::copy fileCopyOperation(from, to);
|
||||
if(!fileCopyOperation()) {
|
||||
if (!fileCopyOperation()) {
|
||||
qWarning() << "Failed to copy" << from << "to" << to;
|
||||
return false;
|
||||
}
|
||||
@ -990,7 +948,7 @@ void PackInstallTask::install()
|
||||
components->buildingFromScratch();
|
||||
|
||||
// Use a component to add libraries BEFORE Minecraft
|
||||
if(!createLibrariesComponent(instance.instanceRoot(), components)) {
|
||||
if (!createLibrariesComponent(instance.instanceRoot(), components)) {
|
||||
emitFailed(tr("Failed to create libraries component"));
|
||||
return;
|
||||
}
|
||||
@ -999,27 +957,24 @@ void PackInstallTask::install()
|
||||
components->setComponentVersion("net.minecraft", m_version.minecraft, true);
|
||||
|
||||
// Loader
|
||||
if(m_version.loader.type == QString("forge"))
|
||||
{
|
||||
if (m_version.loader.type == QString("forge")) {
|
||||
auto version = getVersionForLoader("net.minecraftforge");
|
||||
if(version == Q_NULLPTR) return;
|
||||
if (version == Q_NULLPTR)
|
||||
return;
|
||||
|
||||
components->setComponentVersion("net.minecraftforge", version);
|
||||
}
|
||||
else if(m_version.loader.type == QString("fabric"))
|
||||
{
|
||||
} else if (m_version.loader.type == QString("fabric")) {
|
||||
auto version = getVersionForLoader("net.fabricmc.fabric-loader");
|
||||
if(version == Q_NULLPTR) return;
|
||||
if (version == Q_NULLPTR)
|
||||
return;
|
||||
|
||||
components->setComponentVersion("net.fabricmc.fabric-loader", version);
|
||||
}
|
||||
else if(m_version.loader.type != QString())
|
||||
{
|
||||
} else if (m_version.loader.type != QString()) {
|
||||
emitFailed(tr("Unknown loader type: ") + m_version.loader.type);
|
||||
return;
|
||||
}
|
||||
|
||||
for(const auto & componentUid : componentsToInstall.keys()) {
|
||||
for (const auto& componentUid : componentsToInstall.keys()) {
|
||||
auto version = componentsToInstall.value(componentUid);
|
||||
components->setComponentVersion(componentUid, version->version());
|
||||
}
|
||||
@ -1028,7 +983,7 @@ void PackInstallTask::install()
|
||||
|
||||
// Use a component to fill in the rest of the data
|
||||
// todo: use more detection
|
||||
if(!createPackComponent(instance.instanceRoot(), components)) {
|
||||
if (!createPackComponent(instance.instanceRoot(), components)) {
|
||||
emitFailed(tr("Failed to create pack component"));
|
||||
return;
|
||||
}
|
||||
@ -1063,4 +1018,4 @@ static Meta::Version::Ptr getComponentVersion(const QString& uid, const QString&
|
||||
return ver;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace ATLauncher
|
||||
|
@ -38,84 +38,67 @@
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
static ATLauncher::DownloadType parseDownloadType(QString rawType) {
|
||||
if(rawType == QString("server")) {
|
||||
static ATLauncher::DownloadType parseDownloadType(QString rawType)
|
||||
{
|
||||
if (rawType == QString("server")) {
|
||||
return ATLauncher::DownloadType::Server;
|
||||
}
|
||||
else if(rawType == QString("browser")) {
|
||||
} else if (rawType == QString("browser")) {
|
||||
return ATLauncher::DownloadType::Browser;
|
||||
}
|
||||
else if(rawType == QString("direct")) {
|
||||
} else if (rawType == QString("direct")) {
|
||||
return ATLauncher::DownloadType::Direct;
|
||||
}
|
||||
|
||||
return ATLauncher::DownloadType::Unknown;
|
||||
}
|
||||
|
||||
static ATLauncher::ModType parseModType(QString rawType) {
|
||||
static ATLauncher::ModType parseModType(QString rawType)
|
||||
{
|
||||
// See https://wiki.atlauncher.com/mod_types
|
||||
if(rawType == QString("root")) {
|
||||
if (rawType == QString("root")) {
|
||||
return ATLauncher::ModType::Root;
|
||||
}
|
||||
else if(rawType == QString("forge")) {
|
||||
} else if (rawType == QString("forge")) {
|
||||
return ATLauncher::ModType::Forge;
|
||||
}
|
||||
else if(rawType == QString("jar")) {
|
||||
} else if (rawType == QString("jar")) {
|
||||
return ATLauncher::ModType::Jar;
|
||||
}
|
||||
else if(rawType == QString("mods")) {
|
||||
} else if (rawType == QString("mods")) {
|
||||
return ATLauncher::ModType::Mods;
|
||||
}
|
||||
else if(rawType == QString("flan")) {
|
||||
} else if (rawType == QString("flan")) {
|
||||
return ATLauncher::ModType::Flan;
|
||||
}
|
||||
else if(rawType == QString("dependency") || rawType == QString("depandency")) {
|
||||
} else if (rawType == QString("dependency") || rawType == QString("depandency")) {
|
||||
return ATLauncher::ModType::Dependency;
|
||||
}
|
||||
else if(rawType == QString("ic2lib")) {
|
||||
} else if (rawType == QString("ic2lib")) {
|
||||
return ATLauncher::ModType::Ic2Lib;
|
||||
}
|
||||
else if(rawType == QString("denlib")) {
|
||||
} else if (rawType == QString("denlib")) {
|
||||
return ATLauncher::ModType::DenLib;
|
||||
}
|
||||
else if(rawType == QString("coremods")) {
|
||||
} else if (rawType == QString("coremods")) {
|
||||
return ATLauncher::ModType::Coremods;
|
||||
}
|
||||
else if(rawType == QString("mcpc")) {
|
||||
} else if (rawType == QString("mcpc")) {
|
||||
return ATLauncher::ModType::MCPC;
|
||||
}
|
||||
else if(rawType == QString("plugins")) {
|
||||
} else if (rawType == QString("plugins")) {
|
||||
return ATLauncher::ModType::Plugins;
|
||||
}
|
||||
else if(rawType == QString("extract")) {
|
||||
} else if (rawType == QString("extract")) {
|
||||
return ATLauncher::ModType::Extract;
|
||||
}
|
||||
else if(rawType == QString("decomp")) {
|
||||
} else if (rawType == QString("decomp")) {
|
||||
return ATLauncher::ModType::Decomp;
|
||||
}
|
||||
else if(rawType == QString("texturepack")) {
|
||||
} else if (rawType == QString("texturepack")) {
|
||||
return ATLauncher::ModType::TexturePack;
|
||||
}
|
||||
else if(rawType == QString("resourcepack")) {
|
||||
} else if (rawType == QString("resourcepack")) {
|
||||
return ATLauncher::ModType::ResourcePack;
|
||||
}
|
||||
else if(rawType == QString("shaderpack")) {
|
||||
} else if (rawType == QString("shaderpack")) {
|
||||
return ATLauncher::ModType::ShaderPack;
|
||||
}
|
||||
else if(rawType == QString("texturepackextract")) {
|
||||
} else if (rawType == QString("texturepackextract")) {
|
||||
return ATLauncher::ModType::TexturePackExtract;
|
||||
}
|
||||
else if(rawType == QString("resourcepackextract")) {
|
||||
} else if (rawType == QString("resourcepackextract")) {
|
||||
return ATLauncher::ModType::ResourcePackExtract;
|
||||
}
|
||||
else if(rawType == QString("millenaire")) {
|
||||
} else if (rawType == QString("millenaire")) {
|
||||
return ATLauncher::ModType::Millenaire;
|
||||
}
|
||||
|
||||
return ATLauncher::ModType::Unknown;
|
||||
}
|
||||
|
||||
static void loadVersionLoader(ATLauncher::VersionLoader & p, QJsonObject & obj) {
|
||||
static void loadVersionLoader(ATLauncher::VersionLoader& p, QJsonObject& obj)
|
||||
{
|
||||
p.type = Json::requireString(obj, "type");
|
||||
p.choose = Json::ensureBoolean(obj, QString("choose"), false);
|
||||
|
||||
@ -134,7 +117,8 @@ static void loadVersionLoader(ATLauncher::VersionLoader & p, QJsonObject & obj)
|
||||
}
|
||||
}
|
||||
|
||||
static void loadVersionLibrary(ATLauncher::VersionLibrary & p, QJsonObject & obj) {
|
||||
static void loadVersionLibrary(ATLauncher::VersionLibrary& p, QJsonObject& obj)
|
||||
{
|
||||
p.url = Json::requireString(obj, "url");
|
||||
p.file = Json::requireString(obj, "file");
|
||||
p.md5 = Json::requireString(obj, "md5");
|
||||
@ -145,12 +129,14 @@ static void loadVersionLibrary(ATLauncher::VersionLibrary & p, QJsonObject & obj
|
||||
p.server = Json::ensureString(obj, "server", "");
|
||||
}
|
||||
|
||||
static void loadVersionConfigs(ATLauncher::VersionConfigs & p, QJsonObject & obj) {
|
||||
static void loadVersionConfigs(ATLauncher::VersionConfigs& p, QJsonObject& obj)
|
||||
{
|
||||
p.filesize = Json::requireInteger(obj, "filesize");
|
||||
p.sha1 = Json::requireString(obj, "sha1");
|
||||
}
|
||||
|
||||
static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) {
|
||||
static void loadVersionMod(ATLauncher::VersionMod& p, QJsonObject& obj)
|
||||
{
|
||||
p.name = Json::requireString(obj, "name");
|
||||
p.version = Json::requireString(obj, "version");
|
||||
p.url = Json::requireString(obj, "url");
|
||||
@ -167,18 +153,18 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) {
|
||||
// when the mod represents Forge. As there is little difference between "Jar" and "Forge, some
|
||||
// packs regretfully use "Jar". This will correct the type to "Forge" in these cases (as best
|
||||
// it can).
|
||||
if(p.name == QString("Minecraft Forge") && p.type == ATLauncher::ModType::Jar) {
|
||||
if (p.name == QString("Minecraft Forge") && p.type == ATLauncher::ModType::Jar) {
|
||||
p.type_raw = "forge";
|
||||
p.type = ATLauncher::ModType::Forge;
|
||||
}
|
||||
|
||||
if(obj.contains("extractTo")) {
|
||||
if (obj.contains("extractTo")) {
|
||||
p.extractTo_raw = Json::requireString(obj, "extractTo");
|
||||
p.extractTo = parseModType(p.extractTo_raw);
|
||||
p.extractFolder = Json::ensureString(obj, "extractFolder", "").replace("%s%", "/");
|
||||
}
|
||||
|
||||
if(obj.contains("decompType")) {
|
||||
if (obj.contains("decompType")) {
|
||||
p.decompType_raw = Json::requireString(obj, "decompType");
|
||||
p.decompType = parseModType(p.decompType_raw);
|
||||
p.decompFile = Json::requireString(obj, "decompFile");
|
||||
@ -191,7 +177,7 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) {
|
||||
p.hidden = Json::ensureBoolean(obj, QString("hidden"), false);
|
||||
p.library = Json::ensureBoolean(obj, QString("library"), false);
|
||||
p.group = Json::ensureString(obj, QString("group"), "");
|
||||
if(obj.contains("depends")) {
|
||||
if (obj.contains("depends")) {
|
||||
auto dependsArr = Json::requireArray(obj, "depends");
|
||||
for (const auto depends : dependsArr) {
|
||||
p.depends.append(Json::requireString(depends));
|
||||
@ -282,31 +268,30 @@ static void loadVersionDeletes(ATLauncher::VersionDeletes& d, QJsonObject& obj)
|
||||
}
|
||||
}
|
||||
|
||||
void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)
|
||||
void ATLauncher::loadVersion(PackVersion& v, QJsonObject& obj)
|
||||
{
|
||||
v.version = Json::requireString(obj, "version");
|
||||
v.minecraft = Json::requireString(obj, "minecraft");
|
||||
v.noConfigs = Json::ensureBoolean(obj, QString("noConfigs"), false);
|
||||
|
||||
if(obj.contains("mainClass")) {
|
||||
if (obj.contains("mainClass")) {
|
||||
auto main = Json::requireObject(obj, "mainClass");
|
||||
loadVersionMainClass(v.mainClass, main);
|
||||
}
|
||||
|
||||
if(obj.contains("extraArguments")) {
|
||||
if (obj.contains("extraArguments")) {
|
||||
auto arguments = Json::requireObject(obj, "extraArguments");
|
||||
loadVersionExtraArguments(v.extraArguments, arguments);
|
||||
}
|
||||
|
||||
if(obj.contains("loader")) {
|
||||
if (obj.contains("loader")) {
|
||||
auto loader = Json::requireObject(obj, "loader");
|
||||
loadVersionLoader(v.loader, loader);
|
||||
}
|
||||
|
||||
if(obj.contains("libraries")) {
|
||||
if (obj.contains("libraries")) {
|
||||
auto libraries = Json::requireArray(obj, "libraries");
|
||||
for (const auto libraryRaw : libraries)
|
||||
{
|
||||
for (const auto libraryRaw : libraries) {
|
||||
auto libraryObj = Json::requireObject(libraryRaw);
|
||||
ATLauncher::VersionLibrary target;
|
||||
loadVersionLibrary(target, libraryObj);
|
||||
@ -314,10 +299,9 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)
|
||||
}
|
||||
}
|
||||
|
||||
if(obj.contains("mods")) {
|
||||
if (obj.contains("mods")) {
|
||||
auto mods = Json::requireArray(obj, "mods");
|
||||
for (const auto modRaw : mods)
|
||||
{
|
||||
for (const auto modRaw : mods) {
|
||||
auto modObj = Json::requireObject(modRaw);
|
||||
ATLauncher::VersionMod mod;
|
||||
loadVersionMod(mod, modObj);
|
||||
@ -325,18 +309,18 @@ void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)
|
||||
}
|
||||
}
|
||||
|
||||
if(obj.contains("configs")) {
|
||||
if (obj.contains("configs")) {
|
||||
auto configsObj = Json::requireObject(obj, "configs");
|
||||
loadVersionConfigs(v.configs, configsObj);
|
||||
}
|
||||
|
||||
auto colourObj = Json::ensureObject(obj, "colours");
|
||||
for (const auto &key : colourObj.keys()) {
|
||||
for (const auto& key : colourObj.keys()) {
|
||||
v.colours[key] = Json::requireString(colourObj.value(key), "colour");
|
||||
}
|
||||
|
||||
auto warningsObj = Json::ensureObject(obj, "warnings");
|
||||
for (const auto &key : warningsObj.keys()) {
|
||||
for (const auto& key : warningsObj.keys()) {
|
||||
v.warnings[key] = Json::requireString(warningsObj.value(key), "warning");
|
||||
}
|
||||
|
||||
|
@ -40,17 +40,11 @@
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
namespace ATLauncher
|
||||
{
|
||||
namespace ATLauncher {
|
||||
|
||||
enum class PackType
|
||||
{
|
||||
Public,
|
||||
Private
|
||||
};
|
||||
enum class PackType { Public, Private };
|
||||
|
||||
enum class ModType
|
||||
{
|
||||
enum class ModType {
|
||||
Root,
|
||||
Forge,
|
||||
Jar,
|
||||
@ -73,16 +67,9 @@ enum class ModType
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum class DownloadType
|
||||
{
|
||||
Server,
|
||||
Browser,
|
||||
Direct,
|
||||
Unknown
|
||||
};
|
||||
enum class DownloadType { Server, Browser, Direct, Unknown };
|
||||
|
||||
struct VersionLoader
|
||||
{
|
||||
struct VersionLoader {
|
||||
QString type;
|
||||
bool latest;
|
||||
bool recommended;
|
||||
@ -91,8 +78,7 @@ struct VersionLoader
|
||||
QString version;
|
||||
};
|
||||
|
||||
struct VersionLibrary
|
||||
{
|
||||
struct VersionLibrary {
|
||||
QString url;
|
||||
QString file;
|
||||
QString server;
|
||||
@ -101,8 +87,7 @@ struct VersionLibrary
|
||||
QString download_raw;
|
||||
};
|
||||
|
||||
struct VersionMod
|
||||
{
|
||||
struct VersionMod {
|
||||
QString name;
|
||||
QString version;
|
||||
QString url;
|
||||
@ -138,14 +123,12 @@ struct VersionMod
|
||||
bool effectively_hidden;
|
||||
};
|
||||
|
||||
struct VersionConfigs
|
||||
{
|
||||
struct VersionConfigs {
|
||||
int filesize;
|
||||
QString sha1;
|
||||
};
|
||||
|
||||
struct VersionMessages
|
||||
{
|
||||
struct VersionMessages {
|
||||
QString install;
|
||||
QString update;
|
||||
};
|
||||
@ -170,20 +153,17 @@ struct VersionDeletes {
|
||||
QVector<VersionDelete> folders;
|
||||
};
|
||||
|
||||
struct PackVersionMainClass
|
||||
{
|
||||
struct PackVersionMainClass {
|
||||
QString mainClass;
|
||||
QString depends;
|
||||
};
|
||||
|
||||
struct PackVersionExtraArguments
|
||||
{
|
||||
struct PackVersionExtraArguments {
|
||||
QString arguments;
|
||||
QString depends;
|
||||
};
|
||||
|
||||
struct PackVersion
|
||||
{
|
||||
struct PackVersion {
|
||||
QString version;
|
||||
QString minecraft;
|
||||
bool noConfigs;
|
||||
@ -203,6 +183,6 @@ struct PackVersion
|
||||
VersionDeletes deletes;
|
||||
};
|
||||
|
||||
void loadVersion(PackVersion & v, QJsonObject & obj);
|
||||
void loadVersion(PackVersion& v, QJsonObject& obj);
|
||||
|
||||
}
|
||||
} // namespace ATLauncher
|
||||
|
@ -57,4 +57,4 @@ void loadShareCodeResponse(ShareCodeResponse& r, QJsonObject& obj)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace ATLauncher
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace ATLauncher {
|
||||
|
||||
@ -44,4 +44,4 @@ struct ShareCodeResponse {
|
||||
|
||||
void loadShareCodeResponse(ShareCodeResponse& r, QJsonObject& obj);
|
||||
|
||||
}
|
||||
} // namespace ATLauncher
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "FileResolvingTask.h"
|
||||
|
||||
#include "Json.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ApiUpload.h"
|
||||
#include "net/Upload.h"
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
#include "modplatform/modrinth/ModrinthPackIndex.h"
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
#include "Json.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ApiUpload.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/Upload.h"
|
||||
|
||||
Task::Ptr FlameAPI::matchFingerprints(const QList<uint>& fingerprints, std::shared_ptr<QByteArray> response)
|
||||
@ -75,8 +75,8 @@ auto FlameAPI::getModDescription(int modId) -> QString
|
||||
|
||||
auto netJob = makeShared<NetJob>(QString("Flame::ModDescription"), APPLICATION->network());
|
||||
auto response = std::make_shared<QByteArray>();
|
||||
netJob->addNetAction(
|
||||
Net::ApiDownload::makeByteArray(QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response));
|
||||
netJob->addNetAction(Net::ApiDownload::makeByteArray(
|
||||
QString("https://api.curseforge.com/v1/mods/%1/description").arg(QString::number(modId)), response));
|
||||
|
||||
QObject::connect(netJob.get(), &NetJob::succeeded, [&netJob, response, &description] {
|
||||
QJsonParseError parse_error{};
|
||||
|
@ -8,7 +8,10 @@ class FlameCheckUpdate : public CheckUpdateTask {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FlameCheckUpdate(QList<Mod*>& mods, std::list<Version>& mcVersions, std::optional<ResourceAPI::ModLoaderTypes> loaders, std::shared_ptr<ModFolderModel> mods_folder)
|
||||
FlameCheckUpdate(QList<Mod*>& mods,
|
||||
std::list<Version>& mcVersions,
|
||||
std::optional<ResourceAPI::ModLoaderTypes> loaders,
|
||||
std::shared_ptr<ModFolderModel> mods_folder)
|
||||
: CheckUpdateTask(mods, mcVersions, loaders, mods_folder)
|
||||
{}
|
||||
|
||||
|
@ -194,4 +194,3 @@ ModPlatform::IndexedVersion FlameMod::loadDependencyVersions(const ModPlatform::
|
||||
std::sort(versions.begin(), versions.end(), orderSortPredicate);
|
||||
return versions.front();
|
||||
}
|
||||
|
||||
|
@ -54,23 +54,22 @@ void Flame::loadIndexedInfo(IndexedPack& pack, QJsonObject& obj)
|
||||
auto links_obj = Json::ensureObject(obj, "links");
|
||||
|
||||
pack.extra.websiteUrl = Json::ensureString(links_obj, "websiteUrl");
|
||||
if(pack.extra.websiteUrl.endsWith('/'))
|
||||
if (pack.extra.websiteUrl.endsWith('/'))
|
||||
pack.extra.websiteUrl.chop(1);
|
||||
|
||||
pack.extra.issuesUrl = Json::ensureString(links_obj, "issuesUrl");
|
||||
if(pack.extra.issuesUrl.endsWith('/'))
|
||||
if (pack.extra.issuesUrl.endsWith('/'))
|
||||
pack.extra.issuesUrl.chop(1);
|
||||
|
||||
pack.extra.sourceUrl = Json::ensureString(links_obj, "sourceUrl");
|
||||
if(pack.extra.sourceUrl.endsWith('/'))
|
||||
if (pack.extra.sourceUrl.endsWith('/'))
|
||||
pack.extra.sourceUrl.chop(1);
|
||||
|
||||
pack.extra.wikiUrl = Json::ensureString(links_obj, "wikiUrl");
|
||||
if(pack.extra.wikiUrl.endsWith('/'))
|
||||
if (pack.extra.wikiUrl.endsWith('/'))
|
||||
pack.extra.wikiUrl.chop(1);
|
||||
|
||||
pack.extraInfoLoaded = true;
|
||||
|
||||
}
|
||||
|
||||
void Flame::loadIndexedPackVersions(Flame::IndexedPack& pack, QJsonArray& arr)
|
||||
|
@ -46,7 +46,7 @@ static void loadManifestV1(Flame::Manifest& pack, QJsonObject& manifest)
|
||||
Flame::File file;
|
||||
loadFileV1(file, obj);
|
||||
|
||||
pack.files.insert(file.fileId,file);
|
||||
pack.files.insert(file.fileId, file);
|
||||
}
|
||||
|
||||
pack.overrides = Json::ensureString(manifest, "overrides", "overrides");
|
||||
@ -69,7 +69,7 @@ void Flame::loadManifest(Flame::Manifest& m, const QString& filepath)
|
||||
loadManifestV1(m, obj);
|
||||
}
|
||||
|
||||
bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked)
|
||||
bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked)
|
||||
{
|
||||
fileName = Json::requireString(obj, "fileName");
|
||||
// This is a piece of a Flame project JSON pulled out into the file metadata (here) for convenience
|
||||
@ -81,7 +81,7 @@ bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked
|
||||
// get the hash
|
||||
hash = QString();
|
||||
auto hashes = Json::ensureArray(obj, "hashes");
|
||||
for(QJsonValueRef item : hashes) {
|
||||
for (QJsonValueRef item : hashes) {
|
||||
auto hobj = Json::requireObject(item);
|
||||
auto algo = Json::requireInteger(hobj, "algo");
|
||||
auto value = Json::requireString(hobj, "value");
|
||||
@ -90,7 +90,6 @@ bool Flame::File::parseFromObject(const QJsonObject& obj, bool throw_on_blocked
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// may throw, if the project is blocked
|
||||
QString rawUrl = Json::ensureString(obj, "downloadUrl");
|
||||
url = QUrl(rawUrl, QUrl::TolerantMode);
|
||||
|
@ -41,10 +41,8 @@
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
namespace Flame
|
||||
{
|
||||
struct File
|
||||
{
|
||||
namespace Flame {
|
||||
struct File {
|
||||
// NOTE: throws JSONValidationError
|
||||
bool parseFromObject(const QJsonObject& object, bool throw_on_blocked = true);
|
||||
|
||||
@ -61,45 +59,33 @@ struct File
|
||||
QString fileName;
|
||||
QUrl url;
|
||||
QString targetFolder = QStringLiteral("mods");
|
||||
enum class Type
|
||||
{
|
||||
Unknown,
|
||||
Folder,
|
||||
Ctoc,
|
||||
SingleFile,
|
||||
Cmod2,
|
||||
Modpack,
|
||||
Mod
|
||||
} type = Type::Mod;
|
||||
enum class Type { Unknown, Folder, Ctoc, SingleFile, Cmod2, Modpack, Mod } type = Type::Mod;
|
||||
};
|
||||
|
||||
struct Modloader
|
||||
{
|
||||
struct Modloader {
|
||||
QString id;
|
||||
bool primary = false;
|
||||
};
|
||||
|
||||
struct Minecraft
|
||||
{
|
||||
struct Minecraft {
|
||||
QString version;
|
||||
QString libraries;
|
||||
QVector<Flame::Modloader> modLoaders;
|
||||
};
|
||||
|
||||
struct Manifest
|
||||
{
|
||||
struct Manifest {
|
||||
QString manifestType;
|
||||
int manifestVersion = 0;
|
||||
Flame::Minecraft minecraft;
|
||||
QString name;
|
||||
QString version;
|
||||
QString author;
|
||||
//File id -> File
|
||||
QMap<int,Flame::File> files;
|
||||
// File id -> File
|
||||
QMap<int, Flame::File> files;
|
||||
QString overrides;
|
||||
|
||||
bool is_loaded = false;
|
||||
};
|
||||
|
||||
void loadManifest(Flame::Manifest & m, const QString &filepath);
|
||||
}
|
||||
void loadManifest(Flame::Manifest& m, const QString& filepath);
|
||||
} // namespace Flame
|
||||
|
@ -148,4 +148,3 @@ Task::Ptr NetworkResourceAPI::getDependencyVersion(DependencySearchArgs&& args,
|
||||
|
||||
return netJob;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,8 @@
|
||||
#include "PrivatePackManager.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include "BuildConfig.h"
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
|
@ -1,22 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace LegacyFTB {
|
||||
|
||||
//Header for structs etc...
|
||||
enum class PackType
|
||||
{
|
||||
Public,
|
||||
ThirdParty,
|
||||
Private
|
||||
};
|
||||
// Header for structs etc...
|
||||
enum class PackType { Public, ThirdParty, Private };
|
||||
|
||||
struct Modpack
|
||||
{
|
||||
struct Modpack {
|
||||
QString name;
|
||||
QString description;
|
||||
QString author;
|
||||
@ -26,9 +20,9 @@ struct Modpack
|
||||
QString mods;
|
||||
QString logo;
|
||||
|
||||
//Technical data
|
||||
// Technical data
|
||||
QString dir;
|
||||
QString file; //<- Url in the xml, but doesn't make much sense
|
||||
QString file; //<- Url in the xml, but doesn't make much sense
|
||||
|
||||
bool bugged = false;
|
||||
bool broken = false;
|
||||
@ -39,7 +33,7 @@ struct Modpack
|
||||
|
||||
typedef QList<Modpack> ModpackList;
|
||||
|
||||
}
|
||||
} // namespace LegacyFTB
|
||||
|
||||
//We need it for the proxy model
|
||||
// We need it for the proxy model
|
||||
Q_DECLARE_METATYPE(LegacyFTB::Modpack)
|
||||
|
@ -43,8 +43,7 @@ namespace LegacyFTB {
|
||||
|
||||
void PrivatePackManager::load()
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
auto foo = QString::fromUtf8(FS::read(m_filename)).split('\n', Qt::SkipEmptyParts);
|
||||
currentPacks = QSet<QString>(foo.begin(), foo.end());
|
||||
@ -53,9 +52,7 @@ void PrivatePackManager::load()
|
||||
#endif
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
} catch (...) {
|
||||
currentPacks = {};
|
||||
qWarning() << "Failed to read third party FTB pack codes from" << m_filename;
|
||||
}
|
||||
@ -63,20 +60,16 @@ void PrivatePackManager::load()
|
||||
|
||||
void PrivatePackManager::save() const
|
||||
{
|
||||
if(!dirty)
|
||||
{
|
||||
if (!dirty) {
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
try {
|
||||
QStringList list = currentPacks.values();
|
||||
FS::write(m_filename, list.join('\n').toUtf8());
|
||||
dirty = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
} catch (...) {
|
||||
qWarning() << "Failed to write third party FTB pack codes to" << m_filename;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace LegacyFTB
|
||||
|
@ -1,43 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFile>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
|
||||
namespace LegacyFTB {
|
||||
|
||||
class PrivatePackManager
|
||||
{
|
||||
public:
|
||||
~PrivatePackManager()
|
||||
{
|
||||
save();
|
||||
}
|
||||
class PrivatePackManager {
|
||||
public:
|
||||
~PrivatePackManager() { save(); }
|
||||
void load();
|
||||
void save() const;
|
||||
bool empty() const
|
||||
{
|
||||
return currentPacks.empty();
|
||||
}
|
||||
const QSet<QString> &getCurrentPackCodes() const
|
||||
{
|
||||
return currentPacks;
|
||||
}
|
||||
void add(const QString &code)
|
||||
bool empty() const { return currentPacks.empty(); }
|
||||
const QSet<QString>& getCurrentPackCodes() const { return currentPacks; }
|
||||
void add(const QString& code)
|
||||
{
|
||||
currentPacks.insert(code);
|
||||
dirty = true;
|
||||
}
|
||||
void remove(const QString &code)
|
||||
void remove(const QString& code)
|
||||
{
|
||||
currentPacks.remove(code);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
QSet<QString> currentPacks;
|
||||
QString m_filename = "private_packs.txt";
|
||||
mutable bool dirty = false;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace LegacyFTB
|
||||
|
@ -8,7 +8,10 @@ class ModrinthCheckUpdate : public CheckUpdateTask {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ModrinthCheckUpdate(QList<Mod*>& mods, std::list<Version>& mcVersions, std::optional<ResourceAPI::ModLoaderTypes> loaders, std::shared_ptr<ModFolderModel> mods_folder)
|
||||
ModrinthCheckUpdate(QList<Mod*>& mods,
|
||||
std::list<Version>& mcVersions,
|
||||
std::optional<ResourceAPI::ModLoaderTypes> loaders,
|
||||
std::shared_ptr<ModFolderModel> mods_folder)
|
||||
: CheckUpdateTask(mods, mcVersions, loaders, mods_folder)
|
||||
{}
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
#include "net/ChecksumValidator.h"
|
||||
|
||||
#include "net/NetJob.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/NetJob.h"
|
||||
#include "settings/INISettingsObject.h"
|
||||
|
||||
#include "ui/dialogs/CustomMessageBox.h"
|
||||
@ -134,10 +134,10 @@ bool ModrinthCreationTask::updateInstance()
|
||||
}
|
||||
} else {
|
||||
// We don't have an old index file, so we may duplicate stuff!
|
||||
auto dialog = CustomMessageBox::selectable(m_parent,
|
||||
tr("No index file."),
|
||||
tr("We couldn't find a suitable index file for the older version. This may cause some of the files to be duplicated. Do you want to continue?"),
|
||||
QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel);
|
||||
auto dialog = CustomMessageBox::selectable(m_parent, tr("No index file."),
|
||||
tr("We couldn't find a suitable index file for the older version. This may cause some "
|
||||
"of the files to be duplicated. Do you want to continue?"),
|
||||
QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel);
|
||||
|
||||
if (dialog->exec() == QDialog::DialogCode::Rejected) {
|
||||
m_abort = true;
|
||||
@ -145,7 +145,6 @@ bool ModrinthCreationTask::updateInstance()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setOverride(true, inst->id());
|
||||
qDebug() << "Will override instance!";
|
||||
|
||||
@ -234,7 +233,8 @@ bool ModrinthCreationTask::createInstance()
|
||||
auto file_path = FS::PathCombine(root_modpack_path, file.path);
|
||||
if (!root_modpack_url.isParentOf(QUrl::fromLocalFile(file_path))) {
|
||||
// This means we somehow got out of the root folder, so abort here to prevent exploits
|
||||
setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.").arg(file.path));
|
||||
setError(tr("One of the files has a path that leads to an arbitrary location (%1). This is a security risk and isn't allowed.")
|
||||
.arg(file.path));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -251,7 +251,8 @@ bool ModrinthCreationTask::createInstance()
|
||||
auto ndl = Net::ApiDownload::makeFile(file.downloads.dequeue(), file_path);
|
||||
ndl->addValidator(new Net::ChecksumValidator(file.hashAlgorithm, file.hash));
|
||||
m_files_job->addNetAction(ndl);
|
||||
if (auto shared = param.lock()) shared->succeeded();
|
||||
if (auto shared = param.lock())
|
||||
shared->succeeded();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -264,9 +265,9 @@ bool ModrinthCreationTask::createInstance()
|
||||
setError(reason);
|
||||
});
|
||||
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
|
||||
connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
|
||||
connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) {
|
||||
setDetails(tr("%1 out of %2 complete").arg(current).arg(total));
|
||||
setProgress(current, total);
|
||||
setProgress(current, total);
|
||||
});
|
||||
connect(m_files_job.get(), &NetJob::stepProgress, this, &ModrinthCreationTask::propagateStepProgress);
|
||||
|
||||
@ -294,7 +295,10 @@ bool ModrinthCreationTask::createInstance()
|
||||
return ended_well;
|
||||
}
|
||||
|
||||
bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector<Modrinth::File>& files, bool set_internal_data, bool show_optional_dialog)
|
||||
bool ModrinthCreationTask::parseManifest(const QString& index_path,
|
||||
std::vector<Modrinth::File>& files,
|
||||
bool set_internal_data,
|
||||
bool show_optional_dialog)
|
||||
{
|
||||
try {
|
||||
auto doc = Json::requireDocument(index_path);
|
||||
|
@ -20,10 +20,7 @@ class ModrinthCreationTask final : public InstanceCreationTask {
|
||||
QString id,
|
||||
QString version_id = {},
|
||||
QString original_instance_id = {})
|
||||
: InstanceCreationTask()
|
||||
, m_parent(parent)
|
||||
, m_managed_id(std::move(id))
|
||||
, m_managed_version_id(std::move(version_id))
|
||||
: InstanceCreationTask(), m_parent(parent), m_managed_id(std::move(id)), m_managed_version_id(std::move(version_id))
|
||||
{
|
||||
setStagingPath(staging_path);
|
||||
setParentSettings(global_settings);
|
||||
|
@ -260,7 +260,6 @@ QByteArray ModrinthPackExportTask::generateIndex()
|
||||
out["dependencies"] = dependencies;
|
||||
}
|
||||
|
||||
|
||||
QJsonArray filesOut;
|
||||
for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) {
|
||||
QJsonObject fileOut;
|
||||
@ -288,7 +287,6 @@ QByteArray ModrinthPackExportTask::generateIndex()
|
||||
hashes["sha512"] = value.sha512;
|
||||
fileOut["hashes"] = hashes;
|
||||
|
||||
|
||||
fileOut["fileSize"] = value.size;
|
||||
filesOut << fileOut;
|
||||
}
|
||||
|
@ -66,23 +66,23 @@ void loadIndexedInfo(Modpack& pack, QJsonObject& obj)
|
||||
pack.extra.projectUrl = QString("https://modrinth.com/modpack/%1").arg(Json::ensureString(obj, "slug"));
|
||||
|
||||
pack.extra.issuesUrl = Json::ensureString(obj, "issues_url");
|
||||
if(pack.extra.issuesUrl.endsWith('/'))
|
||||
if (pack.extra.issuesUrl.endsWith('/'))
|
||||
pack.extra.issuesUrl.chop(1);
|
||||
|
||||
pack.extra.sourceUrl = Json::ensureString(obj, "source_url");
|
||||
if(pack.extra.sourceUrl.endsWith('/'))
|
||||
if (pack.extra.sourceUrl.endsWith('/'))
|
||||
pack.extra.sourceUrl.chop(1);
|
||||
|
||||
pack.extra.wikiUrl = Json::ensureString(obj, "wiki_url");
|
||||
if(pack.extra.wikiUrl.endsWith('/'))
|
||||
if (pack.extra.wikiUrl.endsWith('/'))
|
||||
pack.extra.wikiUrl.chop(1);
|
||||
|
||||
pack.extra.discordUrl = Json::ensureString(obj, "discord_url");
|
||||
if(pack.extra.discordUrl.endsWith('/'))
|
||||
if (pack.extra.discordUrl.endsWith('/'))
|
||||
pack.extra.discordUrl.chop(1);
|
||||
|
||||
auto donate_arr = Json::ensureArray(obj, "donation_urls");
|
||||
for(auto d : donate_arr){
|
||||
for (auto d : donate_arr) {
|
||||
auto d_obj = Json::requireObject(d);
|
||||
|
||||
DonationData donate;
|
||||
@ -107,7 +107,7 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc)
|
||||
auto obj = Json::requireObject(versionIter);
|
||||
auto file = loadIndexedVersion(obj);
|
||||
|
||||
if(!file.id.isEmpty()) // Heuristic to check if the returned value is valid
|
||||
if (!file.id.isEmpty()) // Heuristic to check if the returned value is valid
|
||||
unsortedVersions.append(file);
|
||||
}
|
||||
auto orderSortPredicate = [](const ModpackVersion& a, const ModpackVersion& b) -> bool {
|
||||
@ -122,7 +122,7 @@ void loadIndexedVersions(Modpack& pack, QJsonDocument& doc)
|
||||
pack.versionsLoaded = true;
|
||||
}
|
||||
|
||||
auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
|
||||
auto loadIndexedVersion(QJsonObject& obj) -> ModpackVersion
|
||||
{
|
||||
ModpackVersion file;
|
||||
|
||||
@ -132,12 +132,11 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
|
||||
|
||||
file.id = Json::requireString(obj, "id");
|
||||
file.project_id = Json::requireString(obj, "project_id");
|
||||
|
||||
|
||||
file.date = Json::requireString(obj, "date_published");
|
||||
|
||||
auto files = Json::requireArray(obj, "files");
|
||||
|
||||
|
||||
for (auto file_iter : files) {
|
||||
File indexed_file;
|
||||
auto parent = Json::requireObject(file_iter);
|
||||
@ -146,21 +145,21 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
|
||||
auto filename = Json::ensureString(parent, "filename");
|
||||
// Checking suffix here is fine because it's the response from Modrinth,
|
||||
// so one would assume it will always be in English.
|
||||
if(!filename.endsWith("mrpack") && !filename.endsWith("zip"))
|
||||
if (!filename.endsWith("mrpack") && !filename.endsWith("zip"))
|
||||
continue;
|
||||
}
|
||||
|
||||
auto url = Json::requireString(parent, "url");
|
||||
|
||||
file.download_url = url;
|
||||
if(is_primary)
|
||||
if (is_primary)
|
||||
break;
|
||||
}
|
||||
|
||||
if(file.download_url.isEmpty())
|
||||
if (file.download_url.isEmpty())
|
||||
return {};
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Modrinth
|
||||
|
@ -74,7 +74,6 @@ struct ModpackExtra {
|
||||
QString discordUrl;
|
||||
|
||||
QList<DonationData> donate;
|
||||
|
||||
};
|
||||
|
||||
struct ModpackVersion {
|
||||
@ -97,10 +96,10 @@ struct Modpack {
|
||||
QString description;
|
||||
std::tuple<QString, QUrl> author;
|
||||
QString iconName;
|
||||
QUrl iconUrl;
|
||||
QUrl iconUrl;
|
||||
|
||||
bool versionsLoaded = false;
|
||||
bool extraInfoLoaded = false;
|
||||
bool versionsLoaded = false;
|
||||
bool extraInfoLoaded = false;
|
||||
|
||||
ModpackExtra extra;
|
||||
QVector<ModpackVersion> versions;
|
||||
@ -113,7 +112,7 @@ auto loadIndexedVersion(QJsonObject&) -> ModpackVersion;
|
||||
|
||||
auto validateDownloadUrl(QUrl) -> bool;
|
||||
|
||||
}
|
||||
} // namespace Modrinth
|
||||
|
||||
Q_DECLARE_METATYPE(Modrinth::Modpack)
|
||||
Q_DECLARE_METATYPE(Modrinth::ModpackVersion)
|
||||
|
@ -1,20 +1,20 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* PolyMC - Minecraft Launcher
|
||||
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -36,22 +36,22 @@ auto getRealIndexName(QDir& index_dir, QString normalized_index_name, bool shoul
|
||||
class V1 {
|
||||
public:
|
||||
struct Mod {
|
||||
QString slug {};
|
||||
QString name {};
|
||||
QString filename {};
|
||||
QString slug{};
|
||||
QString name{};
|
||||
QString filename{};
|
||||
// FIXME: make side an enum
|
||||
QString side {"both"};
|
||||
QString side{ "both" };
|
||||
|
||||
// [download]
|
||||
QString mode {};
|
||||
QUrl url {};
|
||||
QString hash_format {};
|
||||
QString hash {};
|
||||
QString mode{};
|
||||
QUrl url{};
|
||||
QString hash_format{};
|
||||
QString hash{};
|
||||
|
||||
// [update]
|
||||
ModPlatform::ResourceProvider provider {};
|
||||
QVariant file_id {};
|
||||
QVariant project_id {};
|
||||
ModPlatform::ResourceProvider provider{};
|
||||
QVariant file_id{};
|
||||
QVariant project_id{};
|
||||
|
||||
public:
|
||||
// This is a totally heuristic, but should work for now.
|
||||
@ -95,4 +95,4 @@ class V1 {
|
||||
static auto getIndexForMod(QDir& index_dir, QVariant& mod_id) -> Mod;
|
||||
};
|
||||
|
||||
} // namespace Packwiz
|
||||
} // namespace Packwiz
|
||||
|
@ -17,23 +17,23 @@
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "MMCZip.h"
|
||||
#include "TechnicPackProcessor.h"
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include "net/ApiDownload.h"
|
||||
|
||||
Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion)
|
||||
Technic::SingleZipPackInstallTask::SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion)
|
||||
{
|
||||
m_sourceUrl = sourceUrl;
|
||||
m_minecraftVersion = minecraftVersion;
|
||||
}
|
||||
|
||||
bool Technic::SingleZipPackInstallTask::abort() {
|
||||
if(m_abortable)
|
||||
{
|
||||
bool Technic::SingleZipPackInstallTask::abort()
|
||||
{
|
||||
if (m_abortable) {
|
||||
return m_filesNetJob->abort();
|
||||
}
|
||||
return false;
|
||||
@ -67,12 +67,12 @@ void Technic::SingleZipPackInstallTask::downloadSucceeded()
|
||||
|
||||
// open the zip and find relevant files in it
|
||||
m_packZip.reset(new QuaZip(m_archivePath));
|
||||
if (!m_packZip->open(QuaZip::mdUnzip))
|
||||
{
|
||||
if (!m_packZip->open(QuaZip::mdUnzip)) {
|
||||
emitFailed(tr("Unable to open supplied modpack zip file."));
|
||||
return;
|
||||
}
|
||||
m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath());
|
||||
m_extractFuture =
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractSubDir, m_packZip.get(), QString(""), extractDir.absolutePath());
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &Technic::SingleZipPackInstallTask::extractFinished);
|
||||
connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &Technic::SingleZipPackInstallTask::extractAborted);
|
||||
m_extractFutureWatcher.setFuture(m_extractFuture);
|
||||
@ -95,8 +95,7 @@ void Technic::SingleZipPackInstallTask::downloadProgressChanged(qint64 current,
|
||||
void Technic::SingleZipPackInstallTask::extractFinished()
|
||||
{
|
||||
m_packZip.reset();
|
||||
if (!m_extractFuture.result())
|
||||
{
|
||||
if (!m_extractFuture.result()) {
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
}
|
||||
@ -104,30 +103,22 @@ void Technic::SingleZipPackInstallTask::extractFinished()
|
||||
|
||||
qDebug() << "Fixing permissions for extracted pack files...";
|
||||
QDirIterator it(extractDir, QDirIterator::Subdirectories);
|
||||
while (it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
auto filepath = it.next();
|
||||
QFileInfo file(filepath);
|
||||
auto permissions = QFile::permissions(filepath);
|
||||
auto origPermissions = permissions;
|
||||
if (file.isDir())
|
||||
{
|
||||
if (file.isDir()) {
|
||||
// Folder +rwx for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// File +rw for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||
}
|
||||
if (origPermissions != permissions)
|
||||
{
|
||||
if (!QFile::setPermissions(filepath, permissions))
|
||||
{
|
||||
if (origPermissions != permissions) {
|
||||
if (!QFile::setPermissions(filepath, permissions)) {
|
||||
logWarning(tr("Could not fix permissions for %1").arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
qDebug() << "Fixed" << filepath;
|
||||
}
|
||||
}
|
||||
|
@ -28,28 +28,26 @@
|
||||
|
||||
namespace Technic {
|
||||
|
||||
class SingleZipPackInstallTask : public InstanceTask
|
||||
{
|
||||
class SingleZipPackInstallTask : public InstanceTask {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SingleZipPackInstallTask(const QUrl &sourceUrl, const QString &minecraftVersion);
|
||||
public:
|
||||
SingleZipPackInstallTask(const QUrl& sourceUrl, const QString& minecraftVersion);
|
||||
|
||||
bool canAbort() const override { return true; }
|
||||
bool abort() override;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
void executeTask() override;
|
||||
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
void downloadSucceeded();
|
||||
void downloadFailed(QString reason);
|
||||
void downloadProgressChanged(qint64 current, qint64 total);
|
||||
void extractFinished();
|
||||
void extractAborted();
|
||||
|
||||
private:
|
||||
private:
|
||||
bool m_abortable = false;
|
||||
|
||||
QUrl m_sourceUrl;
|
||||
@ -61,4 +59,4 @@ private:
|
||||
QFutureWatcher<std::optional<QStringList>> m_extractFutureWatcher;
|
||||
};
|
||||
|
||||
} // namespace Technic
|
||||
} // namespace Technic
|
||||
|
@ -42,8 +42,8 @@
|
||||
|
||||
#include "SolderPackManifest.h"
|
||||
#include "TechnicPackProcessor.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
#include "net/ApiDownload.h"
|
||||
#include "net/ChecksumValidator.h"
|
||||
|
||||
Technic::SolderPackInstallTask::SolderPackInstallTask(shared_qobject_ptr<QNetworkAccessManager> network,
|
||||
const QUrl& solderUrl,
|
||||
@ -97,8 +97,7 @@ void Technic::SolderPackInstallTask::fileListSucceeded()
|
||||
TechnicSolder::PackBuild build;
|
||||
try {
|
||||
TechnicSolder::loadPackBuild(build, obj);
|
||||
}
|
||||
catch (const JSONValidationError& e) {
|
||||
} catch (const JSONValidationError& e) {
|
||||
emitFailed(tr("Could not understand pack manifest:\n") + e.cause());
|
||||
m_filesNetJob.reset();
|
||||
return;
|
||||
@ -139,17 +138,14 @@ void Technic::SolderPackInstallTask::downloadSucceeded()
|
||||
|
||||
setStatus(tr("Extracting modpack"));
|
||||
m_filesNetJob.reset();
|
||||
m_extractFuture = QtConcurrent::run([this]()
|
||||
{
|
||||
m_extractFuture = QtConcurrent::run([this]() {
|
||||
int i = 0;
|
||||
QString extractDir = FS::PathCombine(m_stagingPath, ".minecraft");
|
||||
FS::ensureFolderPathExists(extractDir);
|
||||
|
||||
while (m_modCount > i)
|
||||
{
|
||||
while (m_modCount > i) {
|
||||
auto path = FS::PathCombine(m_outputDir.path(), QString("%1").arg(i));
|
||||
if (!MMCZip::extractDir(path, extractDir))
|
||||
{
|
||||
if (!MMCZip::extractDir(path, extractDir)) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
@ -182,8 +178,7 @@ void Technic::SolderPackInstallTask::downloadAborted()
|
||||
|
||||
void Technic::SolderPackInstallTask::extractFinished()
|
||||
{
|
||||
if (!m_extractFuture.result())
|
||||
{
|
||||
if (!m_extractFuture.result()) {
|
||||
emitFailed(tr("Failed to extract modpack"));
|
||||
return;
|
||||
}
|
||||
@ -191,30 +186,22 @@ void Technic::SolderPackInstallTask::extractFinished()
|
||||
|
||||
qDebug() << "Fixing permissions for extracted pack files...";
|
||||
QDirIterator it(extractDir, QDirIterator::Subdirectories);
|
||||
while (it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
auto filepath = it.next();
|
||||
QFileInfo file(filepath);
|
||||
auto permissions = QFile::permissions(filepath);
|
||||
auto origPermissions = permissions;
|
||||
if(file.isDir())
|
||||
{
|
||||
if (file.isDir()) {
|
||||
// Folder +rwx for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser | QFileDevice::Permission::ExeUser;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// File +rw for current user
|
||||
permissions |= QFileDevice::Permission::ReadUser | QFileDevice::Permission::WriteUser;
|
||||
}
|
||||
if(origPermissions != permissions)
|
||||
{
|
||||
if(!QFile::setPermissions(filepath, permissions))
|
||||
{
|
||||
if (origPermissions != permissions) {
|
||||
if (!QFile::setPermissions(filepath, permissions)) {
|
||||
logWarning(tr("Could not fix permissions for %1").arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
qDebug() << "Fixed" << filepath;
|
||||
}
|
||||
}
|
||||
@ -230,4 +217,3 @@ void Technic::SolderPackInstallTask::extractAborted()
|
||||
{
|
||||
emitFailed(tr("Instance import has been aborted."));
|
||||
}
|
||||
|
||||
|
@ -55,4 +55,4 @@ void loadPackBuild(PackBuild& v, QJsonObject& obj)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace TechnicSolder
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace TechnicSolder {
|
||||
|
||||
@ -46,4 +46,4 @@ struct PackBuild {
|
||||
|
||||
void loadPackBuild(PackBuild& v, QJsonObject& obj);
|
||||
|
||||
}
|
||||
} // namespace TechnicSolder
|
||||
|
@ -40,8 +40,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
|
||||
instance.setName(instName);
|
||||
|
||||
if (instIcon != "default")
|
||||
{
|
||||
if (instIcon != "default") {
|
||||
instance.setIconKey(instIcon);
|
||||
}
|
||||
|
||||
@ -53,23 +52,18 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
QString modpackJar = FS::PathCombine(minecraftPath, "bin", "modpack.jar");
|
||||
QString versionJson = FS::PathCombine(minecraftPath, "bin", "version.json");
|
||||
QString fmlMinecraftVersion;
|
||||
if (QFile::exists(modpackJar))
|
||||
{
|
||||
if (QFile::exists(modpackJar)) {
|
||||
QuaZip zipFile(modpackJar);
|
||||
if (!zipFile.open(QuaZip::mdUnzip))
|
||||
{
|
||||
if (!zipFile.open(QuaZip::mdUnzip)) {
|
||||
emit failed(tr("Unable to open \"bin/modpack.jar\" file!"));
|
||||
return;
|
||||
}
|
||||
QuaZipDir zipFileRoot(&zipFile, "/");
|
||||
if (zipFileRoot.exists("/version.json"))
|
||||
{
|
||||
if (zipFileRoot.exists("/fmlversion.properties"))
|
||||
{
|
||||
if (zipFileRoot.exists("/version.json")) {
|
||||
if (zipFileRoot.exists("/fmlversion.properties")) {
|
||||
zipFile.setCurrentFile("fmlversion.properties");
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"fmlversion.properties\"!"));
|
||||
return;
|
||||
}
|
||||
@ -82,30 +76,25 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
}
|
||||
zipFile.setCurrentFile("version.json", QuaZip::csSensitive);
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
data = file.readAll();
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (minecraftVersion.isEmpty())
|
||||
emit failed(tr("Could not find \"version.json\" inside \"bin/modpack.jar\", but Minecraft version is unknown"));
|
||||
components->setComponentVersion("net.minecraft", minecraftVersion, true);
|
||||
components->installJarMods({modpackJar});
|
||||
components->installJarMods({ modpackJar });
|
||||
|
||||
// Forge for 1.4.7 and for 1.5.2 require extra libraries.
|
||||
// Figure out the forge version and add it as a component
|
||||
// (the code still comes from the jar mod installed above)
|
||||
if (zipFileRoot.exists("/forgeversion.properties"))
|
||||
{
|
||||
if (zipFileRoot.exists("/forgeversion.properties")) {
|
||||
zipFile.setCurrentFile("forgeversion.properties", QuaZip::csSensitive);
|
||||
QuaZipFile file(&zipFile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
// Really shouldn't happen, but error handling shall not be forgotten
|
||||
emit failed(tr("Unable to open \"forgeversion.properties\""));
|
||||
return;
|
||||
@ -120,8 +109,7 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
revision = iniFile["forge.revision.number"].toString();
|
||||
build = iniFile["forge.build.number"].toString();
|
||||
|
||||
if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty())
|
||||
{
|
||||
if (major.isEmpty() || minor.isEmpty() || revision.isEmpty() || build.isEmpty()) {
|
||||
emit failed(tr("Invalid \"forgeversion.properties\"!"));
|
||||
return;
|
||||
}
|
||||
@ -133,83 +121,63 @@ void Technic::TechnicPackProcessor::run(SettingsObjectPtr globalSettings,
|
||||
emit succeeded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (QFile::exists(versionJson))
|
||||
{
|
||||
} else if (QFile::exists(versionJson)) {
|
||||
QFile file(versionJson);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit failed(tr("Unable to open \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
data = file.readAll();
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// This is the "Vanilla" modpack, excluded by the search code
|
||||
emit failed(tr("Unable to find a \"version.json\"!"));
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
QJsonDocument doc = Json::requireDocument(data);
|
||||
QJsonObject root = Json::requireObject(doc, "version.json");
|
||||
QString packMinecraftVersion = Json::ensureString(root, "inheritsFrom", QString(), "");
|
||||
if (packMinecraftVersion.isEmpty()) {
|
||||
if (fmlMinecraftVersion.isEmpty())
|
||||
{
|
||||
if (fmlMinecraftVersion.isEmpty()) {
|
||||
emit failed(tr("Could not understand \"version.json\":\ninheritsFrom is missing"));
|
||||
return;
|
||||
}
|
||||
packMinecraftVersion = fmlMinecraftVersion;
|
||||
}
|
||||
components->setComponentVersion("net.minecraft", packMinecraftVersion, true);
|
||||
for (auto library: Json::ensureArray(root, "libraries", {}))
|
||||
{
|
||||
if (!library.isObject())
|
||||
{
|
||||
for (auto library : Json::ensureArray(root, "libraries", {})) {
|
||||
if (!library.isObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto libraryObject = Json::ensureObject(library, {}, "");
|
||||
auto libraryName = Json::ensureString(libraryObject, "name", "", "");
|
||||
|
||||
if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) && libraryName.contains('-'))
|
||||
{
|
||||
if ((libraryName.startsWith("net.minecraftforge:forge:") || libraryName.startsWith("net.minecraftforge:fmlloader:")) &&
|
||||
libraryName.contains('-')) {
|
||||
QString libraryVersion = libraryName.section(':', 2);
|
||||
if (!libraryVersion.startsWith("1.7.10-"))
|
||||
{
|
||||
if (!libraryVersion.startsWith("1.7.10-")) {
|
||||
components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 1.7.10 versions sometimes look like 1.7.10-10.13.4.1614-1.7.10, this filters out the 10.13.4.1614 part
|
||||
components->setComponentVersion("net.minecraftforge", libraryName.section('-', 1, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// <Technic library name prefix> -> <our component name>
|
||||
static QMap<QString, QString> loaderMap {
|
||||
{"net.minecraftforge:minecraftforge:", "net.minecraftforge"},
|
||||
{"net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader"},
|
||||
{"org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader"}
|
||||
};
|
||||
for (const auto& loader : loaderMap.keys())
|
||||
{
|
||||
if (libraryName.startsWith(loader))
|
||||
{
|
||||
static QMap<QString, QString> loaderMap{ { "net.minecraftforge:minecraftforge:", "net.minecraftforge" },
|
||||
{ "net.fabricmc:fabric-loader:", "net.fabricmc.fabric-loader" },
|
||||
{ "org.quiltmc:quilt-loader:", "org.quiltmc.quilt-loader" } };
|
||||
for (const auto& loader : loaderMap.keys()) {
|
||||
if (libraryName.startsWith(loader)) {
|
||||
components->setComponentVersion(loaderMap.value(loader), libraryName.section(':', 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
} catch (const JSONValidationError& e) {
|
||||
emit failed(tr("Could not understand \"version.json\":\n") + e.cause());
|
||||
return;
|
||||
}
|
||||
|
@ -18,18 +18,21 @@
|
||||
#include <QString>
|
||||
#include "settings/SettingsObject.h"
|
||||
|
||||
namespace Technic
|
||||
{
|
||||
// not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask
|
||||
class TechnicPackProcessor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
namespace Technic {
|
||||
// not exporting it, only used in SingleZipPackInstallTask, InstanceImportTask and SolderPackInstallTask
|
||||
class TechnicPackProcessor : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void succeeded();
|
||||
void failed(QString reason);
|
||||
signals:
|
||||
void succeeded();
|
||||
void failed(QString reason);
|
||||
|
||||
public:
|
||||
void run(SettingsObjectPtr globalSettings, const QString &instName, const QString &instIcon, const QString &stagingPath, const QString &minecraftVersion=QString(), const bool isSolder = false);
|
||||
};
|
||||
}
|
||||
public:
|
||||
void run(SettingsObjectPtr globalSettings,
|
||||
const QString& instName,
|
||||
const QString& instIcon,
|
||||
const QString& stagingPath,
|
||||
const QString& minecraftVersion = QString(),
|
||||
const bool isSolder = false);
|
||||
};
|
||||
} // namespace Technic
|
||||
|
Reference in New Issue
Block a user