aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml27
-rw-r--r--.github/workflows/codeql.yml35
-rw-r--r--.github/workflows/trigger_builds.yml1
-rw-r--r--.github/workflows/trigger_release.yml1
-rw-r--r--launcher/BaseInstance.h2
-rw-r--r--launcher/BaseVersionList.cpp4
-rw-r--r--launcher/FileSystem.cpp3
-rw-r--r--launcher/FileSystem.h1
-rw-r--r--launcher/VersionProxyModel.cpp4
-rw-r--r--launcher/icons/IconList.cpp4
-rw-r--r--launcher/meta/Index.cpp4
-rw-r--r--launcher/meta/JsonFormat.h5
-rw-r--r--launcher/minecraft/PackProfile.cpp6
-rw-r--r--launcher/minecraft/Rule.h2
-rw-r--r--launcher/minecraft/WorldList.cpp6
-rw-r--r--launcher/minecraft/WorldList.h2
-rw-r--r--launcher/minecraft/auth/AccountList.cpp10
-rw-r--r--launcher/minecraft/mod/ModFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/ResourceFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/ResourceFolderModel.h6
-rw-r--r--launcher/minecraft/mod/ResourcePackFolderModel.cpp2
-rw-r--r--launcher/minecraft/mod/tasks/LocalModParseTask.cpp2
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.cpp54
-rw-r--r--launcher/modplatform/flame/FlameInstanceCreationTask.h3
-rw-r--r--launcher/modplatform/helpers/HashUtils.cpp58
-rw-r--r--launcher/modplatform/helpers/HashUtils.h15
-rw-r--r--launcher/modplatform/modpacksch/FTBPackInstallTask.cpp60
-rw-r--r--launcher/modplatform/modpacksch/FTBPackInstallTask.h3
-rw-r--r--launcher/net/HttpMetaCache.cpp72
-rw-r--r--launcher/net/HttpMetaCache.h58
-rw-r--r--launcher/ui/MainWindow.cpp42
-rw-r--r--launcher/ui/MainWindow.h4
-rw-r--r--launcher/ui/dialogs/BlockedModsDialog.cpp178
-rw-r--r--launcher/ui/dialogs/BlockedModsDialog.h35
-rw-r--r--launcher/ui/dialogs/BlockedModsDialog.ui37
-rw-r--r--launcher/ui/pages/instance/ExternalResourcesPage.ui6
-rw-r--r--launcher/ui/pages/instance/ServersPage.cpp4
-rw-r--r--launcher/ui/pages/instance/VersionPage.ui6
-rw-r--r--launcher/ui/pages/modplatform/ModModel.h8
-rw-r--r--launcher/ui/pages/modplatform/ModPage.cpp4
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlListModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/atlauncher/AtlOptionalModDialog.cpp4
-rw-r--r--launcher/ui/pages/modplatform/flame/FlameModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/ftb/FtbListModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/legacy_ftb/ListModel.cpp4
-rw-r--r--launcher/ui/pages/modplatform/modrinth/ModrinthModel.h6
-rw-r--r--launcher/ui/pages/modplatform/technic/TechnicModel.cpp8
-rw-r--r--program_info/win_install.nsi.in167
48 files changed, 783 insertions, 196 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3225cf1e..61fd9b4c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,6 +7,10 @@ on:
description: Type of build (Debug, Release, RelWithDebInfo, MinSizeRel)
type: string
default: Debug
+ is_qt_cached:
+ description: Enable Qt caching or not
+ type: string
+ default: true
secrets:
SPARKLE_ED25519_KEY:
description: Private key for signing Sparkle updates
@@ -102,14 +106,6 @@ jobs:
with:
submodules: 'true'
- - name: Initialize CodeQL
- if: runner.os == 'Linux' && matrix.qt_ver == 6
- uses: github/codeql-action/init@v2
- with:
- config-file: ./.github/codeql/codeql-config.yml
- queries: security-and-quality
- languages: cpp, java
-
- name: 'Setup MSYS2'
if: runner.os == 'Windows' && matrix.msystem != ''
uses: msys2/setup-msys2@v2
@@ -200,8 +196,7 @@ jobs:
arch: ${{ matrix.qt_arch }}
modules: ${{ matrix.qt_modules }}
tools: ${{ matrix.qt_tools }}
- cache: true
- cache-key-prefix: ${{ matrix.qt_host }}-${{ matrix.qt_version }}-"${{ matrix.qt_modules }}"-qt_cache
+ cache: ${{ inputs.is_qt_cached }}
- name: Prepare AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5
@@ -293,14 +288,6 @@ jobs:
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
##
- # CODE SCAN
- ##
-
- - name: Perform CodeQL Analysis
- if: runner.os == 'Linux' && matrix.qt_ver == 6
- uses: github/codeql-action/analyze@v2
-
- ##
# PACKAGE BUILDS
##
@@ -510,10 +497,10 @@ jobs:
echo "VERSION=$ver_short" >> $GITHUB_ENV
- name: Package Snap (Linux)
id: snapcraft
- if: runner.os == 'Linux' && matrix.qt_ver != 5
+ if: runner.os == 'Linux' && inputs.build_type == 'Debug'
uses: snapcore/action-build@v1
- name: Upload Snap (Linux)
- if: runner.os == 'Linux' && matrix.qt_ver != 5
+ if: runner.os == 'Linux' && inputs.build_type == 'Debug'
uses: actions/upload-artifact@v3
with:
name: prismlauncher_${{ env.VERSION }}_amd64.snap
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..0cd1f6e4
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,35 @@
+name: "CodeQL Code Scanning"
+
+on: [ push, pull_request, workflow_dispatch ]
+
+jobs:
+ CodeQL:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ submodules: 'true'
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ config-file: ./.github/codeql/codeql-config.yml
+ queries: security-and-quality
+ languages: cpp, java
+
+ - name: Install Dependencies
+ run:
+ sudo apt-get -y update
+
+ sudo apt-get -y install ninja-build extra-cmake-modules scdoc qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
+
+ - name: Configure and Build
+ run: |
+ cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DLauncher_QT_VERSION_MAJOR=5 -G Ninja
+
+ cmake --build build
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/trigger_builds.yml b/.github/workflows/trigger_builds.yml
index 8adaa5e5..44751fbc 100644
--- a/.github/workflows/trigger_builds.yml
+++ b/.github/workflows/trigger_builds.yml
@@ -30,5 +30,6 @@ jobs:
uses: ./.github/workflows/build.yml
with:
build_type: Debug
+ is_qt_cached: true
secrets:
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml
index d415b2b1..8baa9693 100644
--- a/.github/workflows/trigger_release.yml
+++ b/.github/workflows/trigger_release.yml
@@ -12,6 +12,7 @@ jobs:
uses: ./.github/workflows/build.yml
with:
build_type: Release
+ is_qt_cached: false
secrets:
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h
index 307240e0..a2a4f824 100644
--- a/launcher/BaseInstance.h
+++ b/launcher/BaseInstance.h
@@ -151,7 +151,7 @@ public:
void copyManagedPack(BaseInstance& other);
/// guess log level from a line of game log
- virtual MessageLevel::Enum guessLevel(const QString &line, MessageLevel::Enum level)
+ virtual MessageLevel::Enum guessLevel([[maybe_unused]] const QString &line, MessageLevel::Enum level)
{
return level;
};
diff --git a/launcher/BaseVersionList.cpp b/launcher/BaseVersionList.cpp
index 4ed82612..dc95e7ea 100644
--- a/launcher/BaseVersionList.cpp
+++ b/launcher/BaseVersionList.cpp
@@ -95,12 +95,12 @@ BaseVersionList::RoleList BaseVersionList::providesRoles() const
int BaseVersionList::rowCount(const QModelIndex &parent) const
{
// Return count
- return count();
+ return parent.isValid() ? 0 : count();
}
int BaseVersionList::columnCount(const QModelIndex &parent) const
{
- return 1;
+ return parent.isValid() ? 0 : 1;
}
QHash<int, QByteArray> BaseVersionList::roleNames() const
diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp
index 1cbb538c..4a8f4bd3 100644
--- a/launcher/FileSystem.cpp
+++ b/launcher/FileSystem.cpp
@@ -149,6 +149,9 @@ bool ensureFolderPathExists(QString foldernamepath)
return success;
}
+/// @brief Copies a directory and it's contents from src to dest
+/// @param offset subdirectory form src to copy to dest
+/// @return if there was an error during the filecopy
bool copy::operator()(const QString& offset)
{
using copy_opts = fs::copy_options;
diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h
index b46f3281..b7e175fd 100644
--- a/launcher/FileSystem.h
+++ b/launcher/FileSystem.h
@@ -75,6 +75,7 @@ bool ensureFilePathExists(QString filenamepath);
*/
bool ensureFolderPathExists(QString filenamepath);
+/// @brief Copies a directory and it's contents from src to dest
class copy {
public:
copy(const QString& src, const QString& dst)
diff --git a/launcher/VersionProxyModel.cpp b/launcher/VersionProxyModel.cpp
index 032f21f9..6aba268d 100644
--- a/launcher/VersionProxyModel.cpp
+++ b/launcher/VersionProxyModel.cpp
@@ -311,14 +311,14 @@ QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &par
int VersionProxyModel::columnCount(const QModelIndex &parent) const
{
- return m_columns.size();
+ return parent.isValid() ? 0 : m_columns.size();
}
int VersionProxyModel::rowCount(const QModelIndex &parent) const
{
if(sourceModel())
{
- return sourceModel()->rowCount();
+ return sourceModel()->rowCount(parent);
}
return 0;
}
diff --git a/launcher/icons/IconList.cpp b/launcher/icons/IconList.cpp
index 3a223d1b..01043ad2 100644
--- a/launcher/icons/IconList.cpp
+++ b/launcher/icons/IconList.cpp
@@ -242,7 +242,7 @@ Qt::DropActions IconList::supportedDropActions() const
return Qt::CopyAction;
}
-bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
+bool IconList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex &parent)
{
if (action == Qt::IgnoreAction)
return true;
@@ -302,7 +302,7 @@ QVariant IconList::data(const QModelIndex &index, int role) const
int IconList::rowCount(const QModelIndex &parent) const
{
- return icons.size();
+ return parent.isValid() ? 0 : icons.size();
}
void IconList::installIcons(const QStringList &iconFiles)
diff --git a/launcher/meta/Index.cpp b/launcher/meta/Index.cpp
index eec1b329..242aad9f 100644
--- a/launcher/meta/Index.cpp
+++ b/launcher/meta/Index.cpp
@@ -58,11 +58,11 @@ QVariant Index::data(const QModelIndex &index, int role) const
}
int Index::rowCount(const QModelIndex &parent) const
{
- return m_lists.size();
+ return parent.isValid() ? 0 : m_lists.size();
}
int Index::columnCount(const QModelIndex &parent) const
{
- return 1;
+ return parent.isValid() ? 0 : 1;
}
QVariant Index::headerData(int section, Qt::Orientation orientation, int role) const
{
diff --git a/launcher/meta/JsonFormat.h b/launcher/meta/JsonFormat.h
index 93217b7e..63128a4e 100644
--- a/launcher/meta/JsonFormat.h
+++ b/launcher/meta/JsonFormat.h
@@ -60,11 +60,6 @@ struct Require
QString suggests;
};
-inline Q_DECL_PURE_FUNCTION uint qHash(const Require &key, uint seed = 0) Q_DECL_NOTHROW
-{
- return qHash(key.uid, seed);
-}
-
using RequireSet = std::set<Require>;
void parseIndex(const QJsonObject &obj, Index *ptr);
diff --git a/launcher/minecraft/PackProfile.cpp b/launcher/minecraft/PackProfile.cpp
index 1618458f..6ce525eb 100644
--- a/launcher/minecraft/PackProfile.cpp
+++ b/launcher/minecraft/PackProfile.cpp
@@ -613,7 +613,7 @@ QVariant PackProfile::data(const QModelIndex &index, int role) const
bool PackProfile::setData(const QModelIndex& index, const QVariant& value, int role)
{
- if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index))
+ if (!index.isValid() || index.row() < 0 || index.row() >= rowCount(index.parent()))
{
return false;
}
@@ -675,12 +675,12 @@ Qt::ItemFlags PackProfile::flags(const QModelIndex &index) const
int PackProfile::rowCount(const QModelIndex &parent) const
{
- return d->components.size();
+ return parent.isValid() ? 0 : d->components.size();
}
int PackProfile::columnCount(const QModelIndex &parent) const
{
- return NUM_COLUMNS;
+ return parent.isValid() ? 0 : NUM_COLUMNS;
}
void PackProfile::move(const int index, const MoveDirection direction)
diff --git a/launcher/minecraft/Rule.h b/launcher/minecraft/Rule.h
index 236f9a87..846e8e42 100644
--- a/launcher/minecraft/Rule.h
+++ b/launcher/minecraft/Rule.h
@@ -104,7 +104,7 @@ public:
class ImplicitRule : public Rule
{
protected:
- virtual bool applies(const Library *, const RuntimeContext & runtimeContext)
+ virtual bool applies(const Library *, [[maybe_unused]] const RuntimeContext & runtimeContext)
{
return true;
}
diff --git a/launcher/minecraft/WorldList.cpp b/launcher/minecraft/WorldList.cpp
index aee7be35..ae29a972 100644
--- a/launcher/minecraft/WorldList.cpp
+++ b/launcher/minecraft/WorldList.cpp
@@ -173,7 +173,7 @@ bool WorldList::resetIcon(int row)
int WorldList::columnCount(const QModelIndex &parent) const
{
- return 4;
+ return parent.isValid()? 0 : 4;
}
QVariant WorldList::data(const QModelIndex &index, int role) const
@@ -398,8 +398,8 @@ void WorldList::installWorld(QFileInfo filename)
w.install(m_dir.absolutePath());
}
-bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
- const QModelIndex &parent)
+bool WorldList::dropMimeData(const QMimeData *data, Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column,
+ [[maybe_unused]] const QModelIndex &parent)
{
if (action == Qt::IgnoreAction)
return true;
diff --git a/launcher/minecraft/WorldList.h b/launcher/minecraft/WorldList.h
index 5138e583..08294755 100644
--- a/launcher/minecraft/WorldList.h
+++ b/launcher/minecraft/WorldList.h
@@ -54,7 +54,7 @@ public:
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const
{
- return size();
+ return parent.isValid() ? 0 : static_cast<int>(size());
};
virtual QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
diff --git a/launcher/minecraft/auth/AccountList.cpp b/launcher/minecraft/auth/AccountList.cpp
index b3b57c74..9e2fd111 100644
--- a/launcher/minecraft/auth/AccountList.cpp
+++ b/launcher/minecraft/auth/AccountList.cpp
@@ -408,20 +408,20 @@ QVariant AccountList::headerData(int section, Qt::Orientation orientation, int r
}
}
-int AccountList::rowCount(const QModelIndex &) const
+int AccountList::rowCount(const QModelIndex &parent) const
{
// Return count
- return count();
+ return parent.isValid() ? 0 : count();
}
-int AccountList::columnCount(const QModelIndex &) const
+int AccountList::columnCount(const QModelIndex &parent) const
{
- return NUM_COLUMNS;
+ return parent.isValid() ? 0 : NUM_COLUMNS;
}
Qt::ItemFlags AccountList::flags(const QModelIndex &index) const
{
- if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid())
+ if (index.row() < 0 || index.row() >= rowCount(index.parent()) || !index.isValid())
{
return Qt::NoItemFlags;
}
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp
index 66e80f4a..4ccc5d4d 100644
--- a/launcher/minecraft/mod/ModFolderModel.cpp
+++ b/launcher/minecraft/mod/ModFolderModel.cpp
@@ -144,7 +144,7 @@ QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, in
int ModFolderModel::columnCount(const QModelIndex &parent) const
{
- return NUM_COLUMNS;
+ return parent.isValid() ? 0 : NUM_COLUMNS;
}
Task* ModFolderModel::createUpdateTask()
diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp
index b2356309..0310c8f6 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourceFolderModel.cpp
@@ -426,7 +426,7 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const
bool ResourceFolderModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
int row = index.row();
- if (row < 0 || row >= rowCount(index) || !index.isValid())
+ if (row < 0 || row >= rowCount(index.parent()) || !index.isValid())
return false;
if (role == Qt::CheckStateRole)
diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h
index 25095a45..fe283b04 100644
--- a/launcher/minecraft/mod/ResourceFolderModel.h
+++ b/launcher/minecraft/mod/ResourceFolderModel.h
@@ -90,8 +90,8 @@ class ResourceFolderModel : public QAbstractListModel {
/* Basic columns */
enum Columns { ACTIVE_COLUMN = 0, NAME_COLUMN, DATE_COLUMN, NUM_COLUMNS };
- [[nodiscard]] int rowCount(const QModelIndex& = {}) const override { return size(); }
- [[nodiscard]] int columnCount(const QModelIndex& = {}) const override { return NUM_COLUMNS; };
+ [[nodiscard]] int rowCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : static_cast<int>(size()); }
+ [[nodiscard]] int columnCount(const QModelIndex& parent = {}) const override { return parent.isValid() ? 0 : NUM_COLUMNS; };
[[nodiscard]] Qt::DropActions supportedDropActions() const override;
@@ -176,7 +176,7 @@ class ResourceFolderModel : public QAbstractListModel {
* if the resource is complex and has more stuff to parse.
*/
virtual void onParseSucceeded(int ticket, QString resource_id);
- virtual void onParseFailed(int ticket, QString resource_id) {}
+ virtual void onParseFailed(int ticket, QString resource_id) { Q_UNUSED(ticket); Q_UNUSED(resource_id); }
protected:
// Represents the relationship between a column's index (represented by the list index), and it's sorting key.
diff --git a/launcher/minecraft/mod/ResourcePackFolderModel.cpp b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
index f8a6c1cf..ebac707d 100644
--- a/launcher/minecraft/mod/ResourcePackFolderModel.cpp
+++ b/launcher/minecraft/mod/ResourcePackFolderModel.cpp
@@ -137,7 +137,7 @@ QVariant ResourcePackFolderModel::headerData(int section, Qt::Orientation orient
int ResourcePackFolderModel::columnCount(const QModelIndex& parent) const
{
- return NUM_COLUMNS;
+ return parent.isValid() ? 0 : NUM_COLUMNS;
}
Task* ResourcePackFolderModel::createUpdateTask()
diff --git a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
index a694e7b2..774f6114 100644
--- a/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalModParseTask.cpp
@@ -121,7 +121,7 @@ ModDetails ReadMCModTOML(QByteArray contents)
return {};
}
auto modsTable = tomlModsTable0->as_table();
- if (!tomlModsTable0) {
+ if (!modsTable) {
qWarning() << "Corrupted mods.toml? [[mods]] was not a table!";
return {};
}
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
index 48ac02e0..f0fbdc96 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.cpp
@@ -372,13 +372,20 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
auto results = m_mod_id_resolver->getResults();
// first check for blocked mods
- QString text;
- QList<QUrl> urls;
+ QList<BlockedMod> blocked_mods;
auto anyBlocked = false;
for (const auto& result : results.files.values()) {
if (!result.resolved || result.url.isEmpty()) {
- text += QString("%1: <a href='%2'>%2</a><br/>").arg(result.fileName, result.websiteUrl);
- urls.append(QUrl(result.websiteUrl));
+
+ BlockedMod blocked_mod;
+ blocked_mod.name = result.fileName;
+ blocked_mod.websiteUrl = result.websiteUrl;
+ blocked_mod.hash = result.hash;
+ blocked_mod.matched = false;
+ blocked_mod.localPath = "";
+
+ blocked_mods.append(blocked_mod);
+
anyBlocked = true;
}
}
@@ -388,11 +395,12 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked mods found"),
tr("The following mods were blocked on third party launchers.<br/>"
"You will need to manually download them and add them to the modpack"),
- text,
- urls);
+ blocked_mods);
message_dialog->setModal(true);
if (message_dialog->exec()) {
+ qDebug() << "Post dialog blocked mods list: " << blocked_mods;
+ copyBlockedMods(blocked_mods);
setupDownloadJob(loop);
} else {
m_mod_id_resolver.reset();
@@ -404,6 +412,38 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
}
}
+/// @brief copy the matched blocked mods to the instance staging area
+/// @param blocked_mods list of the blocked mods and their matched paths
+void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
+{
+ setStatus(tr("Copying Blocked Mods..."));
+ setAbortable(false);
+ int i = 0;
+ int total = blocked_mods.length();
+ setProgress(i, total);
+ for (auto const& mod : blocked_mods) {
+ if (!mod.matched) {
+ qDebug() << mod.name << "was not matched to a local file, skipping copy";
+ continue;
+ }
+
+ auto dest_path = FS::PathCombine(m_stagingPath, "minecraft", "mods", mod.name);
+
+ setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
+
+ qDebug() << "Will try to copy" << mod.localPath << "to" << dest_path;
+
+ if (!FS::copy(mod.localPath, dest_path)()) {
+ qDebug() << "Copy of" << mod.localPath << "to" << dest_path << "Failed";
+ }
+
+ i++;
+ setProgress(i, total);
+ }
+
+ setAbortable(true);
+}
+
void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
{
m_files_job = new NetJob(tr("Mod download"), APPLICATION->network());
@@ -449,7 +489,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
m_files_job.reset();
setError(reason);
});
- connect(m_files_job.get(), &NetJob::progress, [&](qint64 current, qint64 total) { setProgress(current, total); });
+ connect(m_files_job.get(), &NetJob::progress, this, &FlameCreationTask::setProgress);
connect(m_files_job.get(), &NetJob::finished, &loop, &QEventLoop::quit);
setStatus(tr("Downloading mods..."));
diff --git a/launcher/modplatform/flame/FlameInstanceCreationTask.h b/launcher/modplatform/flame/FlameInstanceCreationTask.h
index ded0e2ce..fbc7d5bf 100644
--- a/launcher/modplatform/flame/FlameInstanceCreationTask.h
+++ b/launcher/modplatform/flame/FlameInstanceCreationTask.h
@@ -10,6 +10,8 @@
#include "net/NetJob.h"
+#include "ui/dialogs/BlockedModsDialog.h"
+
class FlameCreationTask final : public InstanceCreationTask {
Q_OBJECT
@@ -29,6 +31,7 @@ class FlameCreationTask final : public InstanceCreationTask {
private slots:
void idResolverSucceeded(QEventLoop&);
void setupDownloadJob(QEventLoop&);
+ void copyBlockedMods(QList<BlockedMod> const& blocked_mods);
private:
QWidget* m_parent = nullptr;
diff --git a/launcher/modplatform/helpers/HashUtils.cpp b/launcher/modplatform/helpers/HashUtils.cpp
index b18c87af..f1e4759e 100644
--- a/