// SPDX-License-Identifier: GPL-3.0-only /* * PolyMC - Minecraft Launcher * Copyright (c) 2022 flowln * Copyright (C) 2022 Sefa Eyeoglu * * 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 . */ #include "GetModDependenciesTask.h" #include #include "QObjectPtr.h" #include "minecraft/mod/MetadataHandler.h" #include "minecraft/mod/tasks/LocalModGetAllTask.h" #include "modplatform/ModIndex.h" #include "tasks/ConcurrentTask.h" #include "tasks/SequentialTask.h" #ifdef Q_OS_WIN32 #include #endif GetModDependenciesTask::GetModDependenciesTask(QDir index_dir, QList selected, NewDependecyVersionAPITask api) : m_selected(selected), m_getDependenciesVersionAPI(api) { m_getAllMods = makeShared(index_dir); m_getNetworkDep = makeShared(this, "GetDepInfo"); connect(m_getNetworkDep.get(), &Task::finished, &loop, &QEventLoop::quit); QObject::connect(m_getAllMods.get(), &LocalModGetAllTask::getAllMod, [this](QList mods) { m_mods = mods; prepareDependecies(); }); #ifdef Q_OS_WIN32 SetFileAttributesW(index_dir.path().toStdWString().c_str(), FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); #endif } void GetModDependenciesTask::executeTask() { setStatus(tr("Geting all mods")); m_getAllMods->start(); loop.exec(); emitSucceeded(); } auto GetModDependenciesTask::abort() -> bool { emitAborted(); return true; } void GetModDependenciesTask::prepareDependecies() { auto c_dependencies = getDependenciesForVersions(m_selected); if (c_dependencies.length() == 0) { m_getNetworkDep->start(); return; } for (auto dep : c_dependencies) { auto task = m_getDependenciesVersionAPI(dep, [this](ModPlatform::IndexedVersion new_version) { addDependecies(new_version, 20); }); m_getNetworkDep->addTask(task); } m_getNetworkDep->start(); } void GetModDependenciesTask::addDependecies(const ModPlatform::IndexedVersion& new_version, int level) { // some mutex? m_dependencies.append(new_version); auto c_dependencies = getDependenciesForVersion(new_version); if (c_dependencies.length() == 0) { return; } if (level == 0) { qWarning() << "Dependency cycle exeeded"; return; } for (auto dep : c_dependencies) { auto task = m_getDependenciesVersionAPI( dep, [this, level](ModPlatform::IndexedVersion new_versions) { addDependecies(new_versions, level - 1); }); m_getNetworkDep->addTask(task); } }; QList GetModDependenciesTask::getDependenciesForVersions(const QList& selected) { auto c_dependencies = QList(); for (auto version : selected) { for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list if (auto dep = std::find_if(selected.begin(), selected.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == selected.end()) { // check the selected versions if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } } } } } } return c_dependencies; }; QList GetModDependenciesTask::getDependenciesForVersion(const ModPlatform::IndexedVersion& version) { auto c_dependencies = QList(); for (auto ver_dep : version.dependencies) { if (ver_dep.type == ModPlatform::DependencyType::REQUIRED) { if (auto dep = std::find_if(c_dependencies.begin(), c_dependencies.end(), [&ver_dep](auto i) { return i.addonId == ver_dep.addonId; }); dep == c_dependencies.end()) { // check the current dependency list if (auto dep = std::find_if(m_mods.begin(), m_mods.end(), [&ver_dep](auto i) { return i.mod_id() == ver_dep.addonId; }); dep == m_mods.end()) { // check the existing mods c_dependencies.append(ver_dep); } } } } return c_dependencies; };