Merge pull request #2633 from Trial97/refactor_minecraft_update

refactor MinecraftUpdate Task
This commit is contained in:
TheKodeToad 2024-08-18 11:44:44 +01:00 committed by GitHub
commit e9791d6bc1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 13 additions and 144 deletions

View File

@ -16,32 +16,22 @@
#include "MinecraftUpdate.h" #include "MinecraftUpdate.h"
#include "MinecraftInstance.h" #include "MinecraftInstance.h"
#include <QDataStream>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include <FileSystem.h>
#include "BaseInstance.h"
#include "minecraft/Library.h"
#include "minecraft/PackProfile.h" #include "minecraft/PackProfile.h"
#include "tasks/SequentialTask.h"
#include "update/AssetUpdateTask.h" #include "update/AssetUpdateTask.h"
#include "update/FMLLibrariesTask.h" #include "update/FMLLibrariesTask.h"
#include "update/FoldersTask.h" #include "update/FoldersTask.h"
#include "update/LibrariesTask.h" #include "update/LibrariesTask.h"
#include <meta/Index.h> MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : SequentialTask(parent), m_inst(inst) {}
#include <meta/Version.h>
MinecraftUpdate::MinecraftUpdate(MinecraftInstance* inst, QObject* parent) : Task(parent), m_inst(inst) {}
void MinecraftUpdate::executeTask() void MinecraftUpdate::executeTask()
{ {
m_tasks.clear(); m_queue.clear();
// create folders // create folders
{ {
m_tasks.append(makeShared<FoldersTask>(m_inst)); addTask(makeShared<FoldersTask>(m_inst));
} }
// add metadata update task if necessary // add metadata update task if necessary
@ -50,121 +40,24 @@ void MinecraftUpdate::executeTask()
components->reload(Net::Mode::Online); components->reload(Net::Mode::Online);
auto task = components->getCurrentTask(); auto task = components->getCurrentTask();
if (task) { if (task) {
m_tasks.append(task); addTask(task);
} }
} }
// libraries download // libraries download
{ {
m_tasks.append(makeShared<LibrariesTask>(m_inst)); addTask(makeShared<LibrariesTask>(m_inst));
} }
// FML libraries download and copy into the instance // FML libraries download and copy into the instance
{ {
m_tasks.append(makeShared<FMLLibrariesTask>(m_inst)); addTask(makeShared<FMLLibrariesTask>(m_inst));
} }
// assets update // assets update
{ {
m_tasks.append(makeShared<AssetUpdateTask>(m_inst)); addTask(makeShared<AssetUpdateTask>(m_inst));
} }
if (!m_preFailure.isEmpty()) { SequentialTask::executeTask();
emitFailed(m_preFailure);
return;
}
next();
}
void MinecraftUpdate::next()
{
if (m_abort) {
emitFailed(tr("Aborted by user."));
return;
}
if (m_failed_out_of_order) {
emitFailed(m_fail_reason);
return;
}
m_currentTask++;
if (m_currentTask > 0) {
auto task = m_tasks[m_currentTask - 1];
disconnect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded);
disconnect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed);
disconnect(task.get(), &Task::aborted, this, &Task::abort);
disconnect(task.get(), &Task::progress, this, &MinecraftUpdate::progress);
disconnect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress);
disconnect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus);
disconnect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails);
}
if (m_currentTask == m_tasks.size()) {
emitSucceeded();
return;
}
auto task = m_tasks[m_currentTask];
// if the task is already finished by the time we look at it, skip it
if (task->isFinished()) {
qCritical() << "MinecraftUpdate: Skipping finished subtask" << m_currentTask << ":" << task.get();
next();
}
connect(task.get(), &Task::succeeded, this, &MinecraftUpdate::subtaskSucceeded);
connect(task.get(), &Task::failed, this, &MinecraftUpdate::subtaskFailed);
connect(task.get(), &Task::aborted, this, &Task::abort);
connect(task.get(), &Task::progress, this, &MinecraftUpdate::progress);
connect(task.get(), &Task::stepProgress, this, &MinecraftUpdate::propagateStepProgress);
connect(task.get(), &Task::status, this, &MinecraftUpdate::setStatus);
connect(task.get(), &Task::details, this, &MinecraftUpdate::setDetails);
// if the task is already running, do not start it again
if (!task->isRunning()) {
task->start();
}
}
void MinecraftUpdate::subtaskSucceeded()
{
if (isFinished()) {
qCritical() << "MinecraftUpdate: Subtask" << sender() << "succeeded, but work was already done!";
return;
}
auto senderTask = QObject::sender();
auto currentTask = m_tasks[m_currentTask].get();
if (senderTask != currentTask) {
qDebug() << "MinecraftUpdate: Subtask" << sender() << "succeeded out of order.";
return;
}
next();
}
void MinecraftUpdate::subtaskFailed(QString error)
{
if (isFinished()) {
qCritical() << "MinecraftUpdate: Subtask" << sender() << "failed, but work was already done!";
return;
}
auto senderTask = QObject::sender();
auto currentTask = m_tasks[m_currentTask].get();
if (senderTask != currentTask) {
qDebug() << "MinecraftUpdate: Subtask" << sender() << "failed out of order.";
m_failed_out_of_order = true;
m_fail_reason = error;
return;
}
emitFailed(error);
}
bool MinecraftUpdate::abort()
{
if (!m_abort) {
m_abort = true;
auto task = m_tasks[m_currentTask];
if (task->canAbort()) {
return task->abort();
}
}
return true;
}
bool MinecraftUpdate::canAbort() const
{
return true;
} }

View File

@ -15,43 +15,19 @@
#pragma once #pragma once
#include <QList> #include "tasks/SequentialTask.h"
#include <QObject>
#include <QUrl>
#include <quazip/quazip.h>
#include "minecraft/VersionFilterData.h"
#include "net/NetJob.h"
#include "tasks/Task.h"
class MinecraftVersion;
class MinecraftInstance; class MinecraftInstance;
// FIXME: This looks very similar to a SequentialTask. Maybe we can reduce code duplications? :^) // this needs to be a task because components->reload does stuff that may block
class MinecraftUpdate : public SequentialTask {
class MinecraftUpdate : public Task {
Q_OBJECT Q_OBJECT
public: public:
explicit MinecraftUpdate(MinecraftInstance* inst, QObject* parent = 0); explicit MinecraftUpdate(MinecraftInstance* inst, QObject* parent = 0);
virtual ~MinecraftUpdate() {}; virtual ~MinecraftUpdate() = default;
void executeTask() override; void executeTask() override;
bool canAbort() const override;
private slots:
bool abort() override;
void subtaskSucceeded();
void subtaskFailed(QString error);
private:
void next();
private: private:
MinecraftInstance* m_inst = nullptr; MinecraftInstance* m_inst = nullptr;
QList<Task::Ptr> m_tasks;
QString m_preFailure;
int m_currentTask = -1;
bool m_abort = false;
bool m_failed_out_of_order = false;
QString m_fail_reason;
}; };