diff --git a/launcher/FileSystem.cpp b/launcher/FileSystem.cpp index cafc4f25a..36410f03e 100644 --- a/launcher/FileSystem.cpp +++ b/launcher/FileSystem.cpp @@ -1701,4 +1701,30 @@ QString getPathNameInLocal8bit(const QString& file) } #endif +QString getUniqueResourceName(const QString& filePath) +{ + auto newFileName = filePath; + if (!newFileName.endsWith(".disabled")) { + return newFileName; // prioritize enabled mods + } + newFileName.chop(9); + if (!QFile::exists(newFileName)) { + return filePath; + } + QFileInfo fileInfo(filePath); + auto baseName = fileInfo.completeBaseName(); + auto path = fileInfo.absolutePath(); + + int counter = 1; + do { + if (counter == 1) { + newFileName = FS::PathCombine(path, baseName + ".duplicate"); + } else { + newFileName = FS::PathCombine(path, baseName + ".duplicate" + QString::number(counter)); + } + counter++; + } while (QFile::exists(newFileName)); + + return newFileName; +} } // namespace FS diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 23bf5f16e..66adf7a36 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -560,4 +560,6 @@ uintmax_t hardLinkCount(const QString& path); QString getPathNameInLocal8bit(const QString& file); #endif +QString getUniqueResourceName(const QString& filePath); + } // namespace FS diff --git a/launcher/minecraft/mod/Resource.cpp b/launcher/minecraft/mod/Resource.cpp index 62bf6b9a2..6066f02db 100644 --- a/launcher/minecraft/mod/Resource.cpp +++ b/launcher/minecraft/mod/Resource.cpp @@ -161,10 +161,13 @@ bool Resource::enable(EnableAction action) path.chop(9); } else { path += ".disabled"; + auto newFilePath = FS::getUniqueResourceName(path); + if (newFilePath != path) { + FS::move(path, newFilePath); + } } if (QFileInfo::exists(path)) { // the path exists so just remove the file at path - if (!QFile::remove(path)) - return false; + return false; } if (!file.rename(path)) return false; diff --git a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h index 6e8b8ed43..2bce2c137 100644 --- a/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h +++ b/launcher/minecraft/mod/tasks/BasicFolderLoadTask.h @@ -7,6 +7,7 @@ #include +#include "FileSystem.h" #include "minecraft/mod/Resource.h" #include "tasks/Task.h" @@ -49,16 +50,16 @@ class BasicFolderLoadTask : public Task { connect(this, &Task::finished, this->thread(), &QThread::quit); m_dir.refresh(); - QStringList names; for (auto entry : m_dir.entryInfoList()) { - auto resource = m_create_func(entry); - if (names.contains(resource->name())) { - resource->destroy(); - } else { - names << resource->name(); - resource->moveToThread(m_thread_to_spawn_into); - m_result->resources.insert(resource->internal_id(), resource); + auto filePath = entry.absoluteFilePath(); + auto newFilePath = FS::getUniqueResourceName(filePath); + if (newFilePath != filePath) { + FS::move(filePath, newFilePath); + entry = QFileInfo(newFilePath); } + auto resource = m_create_func(entry); + resource->moveToThread(m_thread_to_spawn_into); + m_result->resources.insert(resource->internal_id(), resource); } if (m_aborted) diff --git a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp index c11759dd2..501d5be13 100644 --- a/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp +++ b/launcher/minecraft/mod/tasks/ModFolderLoadTask.cpp @@ -36,6 +36,7 @@ #include "ModFolderLoadTask.h" +#include "FileSystem.h" #include "minecraft/mod/MetadataHandler.h" #include @@ -62,15 +63,15 @@ void ModFolderLoadTask::executeTask() // Read JAR files that don't have metadata m_mods_dir.refresh(); - QStringList names; for (auto entry : m_mods_dir.entryInfoList()) { + auto filePath = entry.absoluteFilePath(); + auto newFilePath = FS::getUniqueResourceName(filePath); + if (newFilePath != filePath) { + FS::move(filePath, newFilePath); + entry = QFileInfo(newFilePath); + } Mod* mod(new Mod(entry)); - if (names.contains(mod->name())) { - mod->destroy(m_index_dir, true); - continue; - } - names << mod->name(); if (mod->enabled()) { if (m_result->mods.contains(mod->internal_id())) { m_result->mods[mod->internal_id()]->setStatus(ModStatus::Installed);