diff options
| author | Sefa Eyeoglu <contact@scrumplex.net> | 2022-08-28 16:52:53 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-28 16:52:53 +0200 |
| commit | f371ec210c091b9ebc91930be74752383cb941c6 (patch) | |
| tree | f3b13e1015285e76145552d21503ff641bf4ce11 /launcher | |
| parent | afcd669d2f6934c2b6076939d7665f791d495994 (diff) | |
| parent | 0b81b283bfdd16b409127f22eac7b51ce0142929 (diff) | |
| download | PrismLauncher-f371ec210c091b9ebc91930be74752383cb941c6.tar.gz PrismLauncher-f371ec210c091b9ebc91930be74752383cb941c6.tar.bz2 PrismLauncher-f371ec210c091b9ebc91930be74752383cb941c6.zip | |
Merge pull request #1052 from flowln/resource_model
Diffstat (limited to 'launcher')
46 files changed, 2068 insertions, 1225 deletions
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 1a5579c8..490202cf 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -318,10 +318,16 @@ set(MINECRAFT_SOURCES minecraft/mod/ModDetails.h minecraft/mod/ModFolderModel.h minecraft/mod/ModFolderModel.cpp + minecraft/mod/Resource.h + minecraft/mod/Resource.cpp + minecraft/mod/ResourceFolderModel.h + minecraft/mod/ResourceFolderModel.cpp minecraft/mod/ResourcePackFolderModel.h minecraft/mod/ResourcePackFolderModel.cpp minecraft/mod/TexturePackFolderModel.h minecraft/mod/TexturePackFolderModel.cpp + minecraft/mod/ShaderPackFolderModel.h + minecraft/mod/tasks/BasicFolderLoadTask.h minecraft/mod/tasks/ModFolderLoadTask.h minecraft/mod/tasks/ModFolderLoadTask.cpp minecraft/mod/tasks/LocalModParseTask.h @@ -375,8 +381,8 @@ ecm_add_test(minecraft/Library_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VER # FIXME: shares data with FileSystem test # TODO: needs testdata -ecm_add_test(minecraft/mod/ModFolderModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test - TEST_NAME ModFolderModel) +ecm_add_test(minecraft/mod/ResourceFolderModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test + TEST_NAME ResourceFolderModel) ecm_add_test(minecraft/ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test TEST_NAME ParseUtils) @@ -881,8 +887,8 @@ SET(LAUNCHER_SOURCES ui/widgets/LineSeparator.h ui/widgets/LogView.cpp ui/widgets/LogView.h - ui/widgets/MCModInfoFrame.cpp - ui/widgets/MCModInfoFrame.h + ui/widgets/InfoFrame.cpp + ui/widgets/InfoFrame.h ui/widgets/ModFilterWidget.cpp ui/widgets/ModFilterWidget.h ui/widgets/ModListView.cpp @@ -944,7 +950,7 @@ qt_wrap_ui(LAUNCHER_UI ui/pages/modplatform/technic/TechnicPage.ui ui/widgets/InstanceCardWidget.ui ui/widgets/CustomCommands.ui - ui/widgets/MCModInfoFrame.ui + ui/widgets/InfoFrame.ui ui/widgets/ModFilterWidget.ui ui/dialogs/CopyInstanceDialog.ui ui/dialogs/ProfileSetupDialog.ui diff --git a/launcher/InstancePageProvider.h b/launcher/InstancePageProvider.h index 78fb7016..bf29377d 100644 --- a/launcher/InstancePageProvider.h +++ b/launcher/InstancePageProvider.h @@ -37,9 +37,9 @@ public: modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); values.append(modsPage); values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList())); - values.append(new ResourcePackPage(onesix.get())); - values.append(new TexturePackPage(onesix.get())); - values.append(new ShaderPackPage(onesix.get())); + values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList())); + values.append(new TexturePackPage(onesix.get(), onesix->texturePackList())); + values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList())); values.append(new NotesPage(onesix.get())); values.append(new WorldListPage(onesix.get(), onesix->worldList())); values.append(new ServersPage(onesix)); diff --git a/launcher/MMCZip.cpp b/launcher/MMCZip.cpp index 04ca5094..9f4e968f 100644 --- a/launcher/MMCZip.cpp +++ b/launcher/MMCZip.cpp @@ -148,7 +148,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const // do not merge disabled mods. if (!mod->enabled()) continue; - if (mod->type() == Mod::MOD_ZIPFILE) + if (mod->type() == ResourceType::ZIPFILE) { if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) { @@ -158,7 +158,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const return false; } } - else if (mod->type() == Mod::MOD_SINGLEFILE) + else if (mod->type() == ResourceType::SINGLEFILE) { // FIXME: buggy - does not work with addedFiles auto filename = mod->fileinfo(); @@ -171,7 +171,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const } addedFiles.insert(filename.fileName()); } - else if (mod->type() == Mod::MOD_FOLDER) + else if (mod->type() == ResourceType::FOLDER) { // untested, but seems to be unused / not possible to reach // FIXME: buggy - does not work with addedFiles diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index c677b677..94b4776e 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -76,6 +76,7 @@ #include "mod/ModFolderModel.h" #include "mod/ResourcePackFolderModel.h" +#include "mod/ShaderPackFolderModel.h" #include "mod/TexturePackFolderModel.h" #include "WorldList.h" @@ -714,7 +715,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr }); for(auto mod: modList) { - if(mod->type() == Mod::MOD_FOLDER) + if(mod->type() == ResourceType::FOLDER) { out << u8" [🖿] " + mod->fileinfo().completeBaseName() + " (folder)"; continue; @@ -1092,18 +1093,18 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const return m_core_mod_list; } -std::shared_ptr<ModFolderModel> MinecraftInstance::resourcePackList() const +std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() const { if (!m_resource_pack_list) { m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir())); - m_resource_pack_list->disableInteraction(isRunning()); - connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ModFolderModel::disableInteraction); + m_resource_pack_list->enableInteraction(!isRunning()); + connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ResourcePackFolderModel::disableInteraction); } return m_resource_pack_list; } -std::shared_ptr<ModFolderModel> MinecraftInstance::texturePackList() const +std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList() const { if (!m_texture_pack_list) { @@ -1114,11 +1115,11 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::texturePackList() const return m_texture_pack_list; } -std::shared_ptr<ModFolderModel> MinecraftInstance::shaderPackList() const +std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList() const { if (!m_shader_pack_list) { - m_shader_pack_list.reset(new ResourcePackFolderModel(shaderPacksDir())); + m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir())); m_shader_pack_list->disableInteraction(isRunning()); connect(this, &BaseInstance::runningStatusChanged, m_shader_pack_list.get(), &ModFolderModel::disableInteraction); } diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index 7a75f452..d62ac655 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -7,6 +7,10 @@ #include "minecraft/launch/MinecraftServerTarget.h" class ModFolderModel; +class ResourceFolderModel; +class ResourcePackFolderModel; +class ShaderPackFolderModel; +class TexturePackFolderModel; class WorldList; class GameOptions; class LaunchStep; @@ -72,9 +76,9 @@ public: ////// Mod Lists ////// std::shared_ptr<ModFolderModel> loaderModList() const; std::shared_ptr<ModFolderModel> coreModList() const; - std::shared_ptr<ModFolderModel> resourcePackList() const; - std::shared_ptr<ModFolderModel> texturePackList() const; - std::shared_ptr<ModFolderModel> shaderPackList() const; + std::shared_ptr<ResourcePackFolderModel> resourcePackList() const; + std::shared_ptr<TexturePackFolderModel> texturePackList() const; + std::shared_ptr<ShaderPackFolderModel> shaderPackList() const; std::shared_ptr<WorldList> worldList() const; std::shared_ptr<GameOptions> gameOptionsModel() const; @@ -125,9 +129,9 @@ protected: // data std::shared_ptr<PackProfile> m_components; mutable std::shared_ptr<ModFolderModel> m_loader_mod_list; mutable std::shared_ptr<ModFolderModel> m_core_mod_list; - mutable std::shared_ptr<ModFolderModel> m_resource_pack_list; - mutable std::shared_ptr<ModFolderModel> m_shader_pack_list; - mutable std::shared_ptr<ModFolderModel> m_texture_pack_list; + mutable std::shared_ptr<ResourcePackFolderModel> m_resource_pack_list; + mutable std::shared_ptr<ShaderPackFolderModel> m_shader_pack_list; + mutable std::shared_ptr<TexturePackFolderModel> m_texture_pack_list; mutable std::shared_ptr<WorldList> m_world_list; mutable std::shared_ptr<GameOptions> m_game_options; }; diff --git a/launcher/minecraft/mod/Mod.cpp b/launcher/minecraft/mod/Mod.cpp index 588d76e3..39023f69 100644 --- a/launcher/minecraft/mod/Mod.cpp +++ b/launcher/minecraft/mod/Mod.cpp @@ -36,130 +36,77 @@ #include "Mod.h" +#include <QDebug> #include <QDir> #include <QString> +#include <QRegularExpression> -#include <FileSystem.h> -#include <QDebug> - -#include "Application.h" #include "MetadataHandler.h" +#include "Version.h" -namespace { - -ModDetails invalidDetails; - -} - -Mod::Mod(const QFileInfo& file) +Mod::Mod(const QFileInfo& file) : Resource(file), m_local_details() { - repath(file); - m_changedDateTime = file.lastModified(); + m_enabled = (file.suffix() != "disabled"); } Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) - : m_file(mods_dir.absoluteFilePath(metadata.filename)) - , m_internal_id(metadata.filename) - , m_name(metadata.name) -{ - if (m_file.isDir()) { - m_type = MOD_FOLDER; - } else { - if (metadata.filename.endsWith(".zip") || metadata.filename.endsWith(".jar")) - m_type = MOD_ZIPFILE; - else if (metadata.filename.endsWith(".litemod")) - m_type = MOD_LITEMOD; - else - m_type = MOD_SINGLEFILE; - } - - m_enabled = true; - m_changedDateTime = m_file.lastModified(); - - m_temp_metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata)); + : Mod(mods_dir.absoluteFilePath(metadata.filename)) +{ + m_name = metadata.name; + m_local_details.metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata)); } -void Mod::repath(const QFileInfo& file) +void Mod::setStatus(ModStatus status) { - m_file = file; - QString name_base = file.fileName(); - - m_type = Mod::MOD_UNKNOWN; - - m_internal_id = name_base; - - if (m_file.isDir()) { - m_type = MOD_FOLDER; - m_name = name_base; - } else if (m_file.isFile()) { - if (name_base.endsWith(".disabled")) { - m_enabled = false; - name_base.chop(9); - } else { - m_enabled = true; - } - if (name_base.endsWith(".zip") || name_base.endsWith(".jar")) { - m_type = MOD_ZIPFILE; - name_base.chop(4); - } else if (name_base.endsWith(".litemod")) { - m_type = MOD_LITEMOD; - name_base.chop(8); - } else { - m_type = MOD_SINGLEFILE; - } - m_name = name_base; - } + m_local_details.status = status; } - -auto Mod::enable(bool value) -> bool +void Mod::setMetadata(std::shared_ptr<Metadata::ModStruct>&& metadata) { - if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER) - return false; - - if (m_enabled == value) - return false; - - QString path = m_file.absoluteFilePath(); - QFile file(path); - if (value) { - if (!path.endsWith(".disabled")) - return false; - path.chop(9); - - if (!file.rename(path)) - return false; - } else { - path += ".disabled"; - - if (!file.rename(path)) - return false; - } - if (status() == ModStatus::NoMetadata) - repath(QFileInfo(path)); + setStatus(ModStatus::Installed); - m_enabled = value; - return true; + m_local_details.metadata = metadata; } -void Mod::setStatus(ModStatus status) +std::pair<int, bool> Mod::compare(const Resource& other, SortType type) const { - if (m_localDetails) { - m_localDetails->status = status; - } else { - m_temp_status = status; + auto cast_other = dynamic_cast<Mod const*>(&other); + if (!cast_other) + return Resource::compare(other, type); + + switch (type) { + default: + case SortType::ENABLED: + case SortType::NAME: + case SortType::DATE: { + auto res = Resource::compare(other, type); + if (res.first != 0) + return res; + } + case SortType::VERSION: { + auto this_ver = Version(version()); + auto other_ver = Version(cast_other->version()); + if (this_ver > other_ver) + return { 1, type == SortType::VERSION }; + if (this_ver < other_ver) + return { -1, type == SortType::VERSION }; + } } + return { 0, false }; } -void Mod::setMetadata(const Metadata::ModStruct& metadata) + +bool Mod::applyFilter(QRegularExpression filter) const { - if (status() == ModStatus::NoMetadata) - setStatus(ModStatus::Installed); + if (filter.match(description()).hasMatch()) + return true; - if (m_localDetails) { - m_localDetails->metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata)); - } else { - m_temp_metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata)); + for (auto& author : authors()) { + if (filter.match(author).hasMatch()) { + return true; + } } + + return Resource::applyFilter(filter); } auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool @@ -175,13 +122,12 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool } } - m_type = MOD_UNKNOWN; - return FS::deletePath(m_file.filePath()); + return Resource::destroy(); } auto Mod::details() const -> const ModDetails& { - return m_localDetails ? *m_localDetails : invalidDetails; + return m_local_details; } auto Mod::name() const -> QString @@ -218,35 +164,29 @@ auto Mod::authors() const -> QStringList auto Mod::status() const -> ModStatus { - if (!m_localDetails) - return m_temp_status; return details().status; } auto Mod::metadata() -> std::shared_ptr<Metadata::ModStruct> { - if (m_localDetails) - return m_localDetails->metadata; - return m_temp_metadata; + return m_local_details.metadata; } auto Mod::metadata() const -> const std::shared_ptr<Metadata::ModStruct> { - if (m_localDetails) - return m_localDetails->metadata; - return m_temp_metadata; + return m_local_details.metadata; } -void Mod::finishResolvingWithDetails(std::shared_ptr<ModDetails> details) +void Mod::finishResolvingWithDetails(ModDetails&& details) { - m_resolving = false; - m_resolved = true; - m_localDetails = details; + m_is_resolving = false; + m_is_resolved = true; - setStatus(m_temp_status); + std::shared_ptr<Metadata::ModStruct> metadata = details.metadata; + if (details.status == ModStatus::Unknown) + details.status = m_local_details.status; - if (m_localDetails && m_temp_metadata && m_temp_metadata->isValid()) { - setMetadata(*m_temp_metadata); - m_temp_metadata.reset(); - } + m_local_details = std::move(details); + if (metadata) + setMetadata(std::move(metadata)); } diff --git a/launcher/minecraft/mod/Mod.h b/launcher/minecraft/mod/Mod.h index 7a13e44b..f336bec4 100644 --- a/launcher/minecraft/mod/Mod.h +++ b/launcher/minecraft/mod/Mod.h @@ -39,38 +39,23 @@ #include <QFileInfo> #include <QList> -#include "QObjectPtr.h" +#include "Resource.h" #include "ModDetails.h" -class Mod : public QObject +class Mod : public Resource { Q_OBJECT public: - enum ModType - { - MOD_UNKNOWN, //!< Indicates an unspecified mod type. - MOD_ZIPFILE, //!< The mod is a zip file containing the mod's class files. - MOD_SINGLEFILE, //!< The mod is a single file (not a zip file). - MOD_FOLDER, //!< The mod is in a folder on the filesystem. - MOD_LITEMOD, //!< The mod is a litemod - }; - using Ptr = shared_qobject_ptr<Mod>; + using WeakPtr = QPointer<Mod>; Mod() = default; Mod(const QFileInfo &file); - explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); - - auto fileinfo() const -> QFileInfo { return m_file; } - auto dateTimeChanged() const -> QDateTime { return m_changedDateTime; } - auto internal_id() const -> QString { return m_internal_id; } - auto type() const -> ModType { return m_type; } - auto enabled() const -> bool { return m_enabled; } - - auto valid() const -> bool { return m_type != MOD_UNKNOWN; } + Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); + Mod(QString file_path) : Mod(QFileInfo(file_path)) {} auto details() const -> const ModDetails&; - auto name() const -> QString; + auto name() const -> QString override; auto version() const -> QString; auto homeurl() const -> QString; auto description() const -> QString; @@ -81,46 +66,17 @@ public: auto metadata() const -> const std::shared_ptr<Metadata::ModStruct>; void setStatus(ModStatus status); - void setMetadata(const Metadata::ModStruct& metadata); + void setMetadata(std::shared_ptr<Metadata::ModStruct>&& metadata); + void setMetadata(const Metadata::ModStruct& metadata) { setMetadata(std::make_shared<Metadata::ModStruct>(metadata)); } - auto enable(bool value) -> bool; + [[nodiscard]] auto compare(Resource const& other, SortType type) const -> std::pair<int, bool> override; + [[nodiscard]] bool applyFilter(QRegularExpression filter) const override; - // delete all the files of this mod + // Delete all the files of this mod auto destroy(QDir& index_dir, bool preserve_metadata = false) -> bool; - // change the mod's filesystem path (used by mod lists for *MAGIC* purposes) - void repath(const QFileInfo &file); - - auto shouldResolve() const -> bool { return !m_resolving && !m_resolved; } - auto isResolving() const -> bool { return m_resolving; } - auto resolutionTicket() const -> int { return m_resolutionTicket; } - - void setResolving(bool resolving, int resolutionTicket) { - m_resolving = resolving; - m_resolutionTicket = resolutionTicket; - } - void finishResolvingWithDetails(std::shared_ptr<ModDetails> details); + void finishResolvingWithDetails(ModDetails&& details); protected: - QFileInfo m_file; - QDateTime m_changedDateTime; - - QString m_internal_id; - /* Name as reported via the file name */ - QString m_name; - ModType m_type = MOD_UNKNOWN; - - /* If the mod has metadata, this will be filled in the constructor, and passed to - * the ModDetails when calling finishResolvingWithDetails */ - std::shared_ptr<Metadata::ModStruct> m_temp_metadata; - - /* Set the mod status while it doesn't have local details just yet */ - ModStatus m_temp_status = ModStatus::NoMetadata; - - std::shared_ptr<ModDetails> m_localDetails; - - bool m_enabled = true; - bool m_resolving = false; - bool m_resolved = false; - int m_resolutionTicket = 0; + ModDetails m_local_details; }; diff --git a/launcher/minecraft/mod/ModDetails.h b/launcher/minecraft/mod/ModDetails.h index 3e0a7ab0..dd84b0a3 100644 --- a/launcher/minecraft/mod/ModDetails.h +++ b/launcher/minecraft/mod/ModDetails.h @@ -46,34 +46,77 @@ enum class ModStatus { Installed, // Both JAR and Metadata are present NotInstalled, // Only the Metadata is present NoMetadata, // Only the JAR is present + Unknown, // Default status }; struct ModDetails { /* Mod ID as defined in the ModLoader-specific metadata */ - QString mod_id; + QString mod_id = {}; /* Human-readable name */ - QString name; + QString name = {}; /* Human-readable mod version */ - QString version; + QString version = {}; /* Human-readable minecraft version */ - QString mcversion; + QString mcversion = {}; /* URL for mod's home page */ - QString homeurl; + QString homeurl = {}; /* Human-readable description */ - QString description; + QString description = {}; /* List of the author's names */ - QStringList authors; + QStringList authors = {}; /* Installation status of the mod */ - ModStatus status; + ModStatus status = ModStatus::Unknown; /* Metadata information, if any */ - std::shared_ptr<Metadata::ModStruct> metadata; + std::shared_ptr<Metadata::ModStruct> metadata = nullptr; + + ModDetails() = default; + + /** Metadata should be handled manually to properly set the mod status. */ + ModDetails(ModDetails& other) + : mod_id(other.mod_id) + , name(other.name) + , version(other.version) + , mcversion(other.mcversion) + , homeurl(other.homeurl) + , description(other.description) + , authors(other.authors) + , status(other.status) + {} + + ModDetails& operator=(ModDetails |
