diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index fce3bb177..e5d69986c 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -346,6 +346,7 @@ set(MINECRAFT_SOURCES minecraft/mod/TexturePackFolderModel.h minecraft/mod/TexturePackFolderModel.cpp minecraft/mod/ShaderPackFolderModel.h + minecraft/mod/ShaderPackFolderModel.cpp minecraft/mod/tasks/ResourceFolderLoadTask.h minecraft/mod/tasks/ResourceFolderLoadTask.cpp minecraft/mod/tasks/LocalModParseTask.h diff --git a/launcher/minecraft/mod/ResourceFolderModel.cpp b/launcher/minecraft/mod/ResourceFolderModel.cpp index 4083a7088..b6f84adab 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.cpp +++ b/launcher/minecraft/mod/ResourceFolderModel.cpp @@ -23,6 +23,7 @@ #include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameModIndex.h" #include "settings/Setting.h" +#include "tasks/SequentialTask.h" #include "tasks/Task.h" #include "ui/dialogs/CustomMessageBox.h" @@ -334,7 +335,17 @@ bool ResourceFolderModel::update() }, Qt::ConnectionType::QueuedConnection); - QThreadPool::globalInstance()->start(m_current_update_task.get()); + auto task = new SequentialTask("ResourceFolderModel::update"); + + Task::Ptr preUpdate(createPreUpdateTask()); + if (preUpdate != nullptr) + task->addTask(preUpdate); + + task->addTask(m_current_update_task); + + connect(task, &Task::finished, [task] { task->deleteLater(); }); + + QThreadPool::globalInstance()->start(task); return true; } diff --git a/launcher/minecraft/mod/ResourceFolderModel.h b/launcher/minecraft/mod/ResourceFolderModel.h index 5c41fc520..0526b5bbf 100644 --- a/launcher/minecraft/mod/ResourceFolderModel.h +++ b/launcher/minecraft/mod/ResourceFolderModel.h @@ -84,7 +84,7 @@ class ResourceFolderModel : public QAbstractListModel { virtual bool startWatching() { return startWatching({ indexDir().absolutePath(), m_dir.absolutePath() }); } virtual bool stopWatching() { return stopWatching({ indexDir().absolutePath(), m_dir.absolutePath() }); } - QDir indexDir() { return { QString("%1/.index").arg(dir().absolutePath()) }; } + virtual QDir indexDir() const { return { QString("%1/.index").arg(dir().absolutePath()) }; } /** Given a path in the system, install that resource, moving it to its place in the * instance file hierarchy. @@ -188,6 +188,7 @@ class ResourceFolderModel : public QAbstractListModel { void parseFinished(); protected: + [[nodiscard]] virtual Task* createPreUpdateTask() { return nullptr; } /** This creates a new update task to be executed by update(). * * The task should load and parse all resources necessary, and provide a way of accessing such results. diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.cpp b/launcher/minecraft/mod/ShaderPackFolderModel.cpp new file mode 100644 index 000000000..ee236512d --- /dev/null +++ b/launcher/minecraft/mod/ShaderPackFolderModel.cpp @@ -0,0 +1,56 @@ +#include "ShaderPackFolderModel.h" + +namespace { +class ShaderPackIndexMigrateTask : public Task { + Q_OBJECT + public: + ShaderPackIndexMigrateTask(QDir resourceDir, QDir indexDir) : m_resourceDir(std::move(resourceDir)), m_indexDir(std::move(indexDir)) {} + + void executeTask() override + { + if (!m_indexDir.exists()) { + qDebug() << m_indexDir.absolutePath() << "does not exist; nothing to migrate"; + emitSucceeded(); + return; + } + + QStringList pwFiles = m_indexDir.entryList({ "*.pw.toml" }, QDir::Files); + bool movedAll = true; + + for (const auto& file : pwFiles) { + QString src = m_indexDir.filePath(file); + QString dest = m_resourceDir.filePath(file); + + if (QFile::rename(src, dest)) { + qDebug() << "Moved" << src << "to" << dest; + } else { + movedAll = false; + qDebug() << "Error moving" << src << "to" << dest; + } + } + + if (!movedAll) { + // FIXME: not shown in the UI + emitFailed(tr("Failed to migrate everything from .index")); + return; + } + + if (!m_indexDir.removeRecursively()) { + emitFailed(tr("Failed to remove old .index dir")); + return; + } + + emitSucceeded(); + } + + private: + QDir m_resourceDir, m_indexDir; +}; +} // namespace + +Task* ShaderPackFolderModel::createPreUpdateTask() +{ + return new ShaderPackIndexMigrateTask(m_dir, ResourceFolderModel::indexDir()); +} + +#include "ShaderPackFolderModel.moc" diff --git a/launcher/minecraft/mod/ShaderPackFolderModel.h b/launcher/minecraft/mod/ShaderPackFolderModel.h index cd01f6226..9b0180180 100644 --- a/launcher/minecraft/mod/ShaderPackFolderModel.h +++ b/launcher/minecraft/mod/ShaderPackFolderModel.h @@ -21,5 +21,16 @@ class ShaderPackFolderModel : public ResourceFolderModel { return new LocalShaderPackParseTask(m_next_resolution_ticket, static_cast(resource)); } + QDir indexDir() const override { return m_dir; } + + Task* createPreUpdateTask() override; + + // avoid watching twice + virtual bool startWatching() override { return ResourceFolderModel::startWatching({ m_dir.absolutePath() }); } + virtual bool stopWatching() override { return ResourceFolderModel::stopWatching({ m_dir.absolutePath() }); } + RESOURCE_HELPERS(ShaderPack); + + private: + QMutex m_migrateLock; };