refactor: move general info from Mod to Resource

This allows us to create other resources that are not Mods, but can
still share a significant portion of code.

Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
flow 2022-08-09 01:53:50 -03:00
parent 2d63c86022
commit 3225f514f6
No known key found for this signature in database
GPG Key ID: 8D0F221F0A59F469
9 changed files with 150 additions and 110 deletions

View File

@ -318,6 +318,8 @@ set(MINECRAFT_SOURCES
minecraft/mod/ModDetails.h minecraft/mod/ModDetails.h
minecraft/mod/ModFolderModel.h minecraft/mod/ModFolderModel.h
minecraft/mod/ModFolderModel.cpp minecraft/mod/ModFolderModel.cpp
minecraft/mod/Resource.h
minecraft/mod/Resource.cpp
minecraft/mod/ResourcePackFolderModel.h minecraft/mod/ResourcePackFolderModel.h
minecraft/mod/ResourcePackFolderModel.cpp minecraft/mod/ResourcePackFolderModel.cpp
minecraft/mod/TexturePackFolderModel.h minecraft/mod/TexturePackFolderModel.h

View File

@ -148,7 +148,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
// do not merge disabled mods. // do not merge disabled mods.
if (!mod->enabled()) if (!mod->enabled())
continue; continue;
if (mod->type() == Mod::MOD_ZIPFILE) if (mod->type() == ResourceType::ZIPFILE)
{ {
if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles)) if (!mergeZipFiles(&zipOut, mod->fileinfo(), addedFiles))
{ {
@ -158,7 +158,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
return false; return false;
} }
} }
else if (mod->type() == Mod::MOD_SINGLEFILE) else if (mod->type() == ResourceType::SINGLEFILE)
{ {
// FIXME: buggy - does not work with addedFiles // FIXME: buggy - does not work with addedFiles
auto filename = mod->fileinfo(); auto filename = mod->fileinfo();
@ -171,7 +171,7 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
} }
addedFiles.insert(filename.fileName()); 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 // untested, but seems to be unused / not possible to reach
// FIXME: buggy - does not work with addedFiles // FIXME: buggy - does not work with addedFiles

View File

@ -714,7 +714,7 @@ QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, Minecr
}); });
for(auto mod: modList) for(auto mod: modList)
{ {
if(mod->type() == Mod::MOD_FOLDER) if(mod->type() == ResourceType::FOLDER)
{ {
out << u8" [🖿] " + mod->fileinfo().completeBaseName() + " (folder)"; out << u8" [🖿] " + mod->fileinfo().completeBaseName() + " (folder)";
continue; continue;

View File

@ -36,13 +36,10 @@
#include "Mod.h" #include "Mod.h"
#include <QDebug>
#include <QDir> #include <QDir>
#include <QString> #include <QString>
#include <FileSystem.h>
#include <QDebug>
#include "Application.h"
#include "MetadataHandler.h" #include "MetadataHandler.h"
namespace { namespace {
@ -51,75 +48,27 @@ ModDetails invalidDetails;
} }
Mod::Mod(const QFileInfo& file) Mod::Mod(const QFileInfo& file) : Resource(file)
{ {
repath(file); m_enabled = (file.suffix() != "disabled");
m_changedDateTime = file.lastModified();
} }
Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata) Mod::Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata)
: m_file(mods_dir.absoluteFilePath(metadata.filename)) : Mod(mods_dir.absoluteFilePath(metadata.filename))
, m_internal_id(metadata.filename)
, m_name(metadata.name)
{ {
if (m_file.isDir()) { m_name = metadata.name;
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)); m_temp_metadata = std::make_shared<Metadata::ModStruct>(std::move(metadata));
} }
void Mod::repath(const QFileInfo& file)
{
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;
}
}
auto Mod::enable(bool value) -> bool auto Mod::enable(bool value) -> bool
{ {
if (m_type == Mod::MOD_UNKNOWN || m_type == Mod::MOD_FOLDER) if (m_type == ResourceType::UNKNOWN || m_type == ResourceType::FOLDER)
return false; return false;
if (m_enabled == value) if (m_enabled == value)
return false; return false;
QString path = m_file.absoluteFilePath(); QString path = m_file_info.absoluteFilePath();
QFile file(path); QFile file(path);
if (value) { if (value) {
if (!path.endsWith(".disabled")) if (!path.endsWith(".disabled"))
@ -136,7 +85,7 @@ auto Mod::enable(bool value) -> bool
} }
if (status() == ModStatus::NoMetadata) if (status() == ModStatus::NoMetadata)
repath(QFileInfo(path)); setFile(QFileInfo(path));
m_enabled = value; m_enabled = value;
return true; return true;
@ -175,8 +124,7 @@ auto Mod::destroy(QDir& index_dir, bool preserve_metadata) -> bool
} }
} }
m_type = MOD_UNKNOWN; return Resource::destroy();
return FS::deletePath(m_file.filePath());
} }
auto Mod::details() const -> const ModDetails& auto Mod::details() const -> const ModDetails&
@ -239,8 +187,8 @@ auto Mod::metadata() const -> const std::shared_ptr<Metadata::ModStruct>
void Mod::finishResolvingWithDetails(std::shared_ptr<ModDetails> details) void Mod::finishResolvingWithDetails(std::shared_ptr<ModDetails> details)
{ {
m_resolving = false; m_is_resolving = false;
m_resolved = true; m_is_resolved = true;
m_localDetails = details; m_localDetails = details;
setStatus(m_temp_status); setStatus(m_temp_status);

View File

@ -39,38 +39,23 @@
#include <QFileInfo> #include <QFileInfo>
#include <QList> #include <QList>
#include "QObjectPtr.h" #include "Resource.h"
#include "ModDetails.h" #include "ModDetails.h"
class Mod : public QObject class Mod : public Resource
{ {
Q_OBJECT Q_OBJECT
public: 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 Ptr = shared_qobject_ptr<Mod>;
Mod() = default; Mod() = default;
Mod(const QFileInfo &file); Mod(const QFileInfo &file);
explicit Mod(const QDir& mods_dir, const Metadata::ModStruct& metadata); 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 enabled() const -> bool { return m_enabled; }
auto valid() const -> bool { return m_type != MOD_UNKNOWN; }
auto details() const -> const ModDetails&; auto details() const -> const ModDetails&;
auto name() const -> QString; auto name() const -> QString override;
auto version() const -> QString; auto version() const -> QString;
auto homeurl() const -> QString; auto homeurl() const -> QString;
auto description() const -> QString; auto description() const -> QString;
@ -85,31 +70,12 @@ public:
auto enable(bool value) -> bool; auto enable(bool value) -> bool;
// delete all the files of this mod // Delete all the files of this mod
auto destroy(QDir& index_dir, bool preserve_metadata = false) -> bool; 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(std::shared_ptr<ModDetails> details);
protected: 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 /* If the mod has metadata, this will be filled in the constructor, and passed to
* the ModDetails when calling finishResolvingWithDetails */ * the ModDetails when calling finishResolvingWithDetails */
std::shared_ptr<Metadata::ModStruct> m_temp_metadata; std::shared_ptr<Metadata::ModStruct> m_temp_metadata;
@ -120,7 +86,4 @@ protected:
std::shared_ptr<ModDetails> m_localDetails; std::shared_ptr<ModDetails> m_localDetails;
bool m_enabled = true; bool m_enabled = true;
bool m_resolving = false;
bool m_resolved = false;
int m_resolutionTicket = 0;
}; };

View File

@ -0,0 +1,53 @@
#include "Resource.h"
#include "FileSystem.h"
Resource::Resource(QObject* parent) : QObject(parent) {}
Resource::Resource(QFileInfo file_info) : QObject()
{
setFile(file_info);
}
void Resource::setFile(QFileInfo file_info)
{
m_file_info = file_info;
parseFile();
}
void Resource::parseFile()
{
QString file_name{ m_file_info.fileName() };
m_type = ResourceType::UNKNOWN;
m_internal_id = file_name;
if (m_file_info.isDir()) {
m_type = ResourceType::FOLDER;
m_name = file_name;
} else if (m_file_info.isFile()) {
if (file_name.endsWith(".disabled"))
file_name.chop(9);
if (file_name.endsWith(".zip") || file_name.endsWith(".jar")) {
m_type = ResourceType::ZIPFILE;
file_name.chop(4);
} else if (file_name.endsWith(".litemod")) {
m_type = ResourceType::LITEMOD;
file_name.chop(8);
} else {
m_type = ResourceType::SINGLEFILE;
}
m_name = file_name;
}
m_changed_date_time = m_file_info.lastModified();
}
bool Resource::destroy()
{
m_type = ResourceType::UNKNOWN;
return FS::deletePath(m_file_info.filePath());
}

View File

@ -0,0 +1,74 @@
#pragma once
#include <QDateTime>
#include <QFileInfo>
#include <QObject>
#include "QObjectPtr.h"
enum class ResourceType {
UNKNOWN, //!< Indicates an unspecified resource type.
ZIPFILE, //!< The resource is a zip file containing the resource's class files.
SINGLEFILE, //!< The resource is a single file (not a zip file).
FOLDER, //!< The resource is in a folder on the filesystem.
LITEMOD, //!< The resource is a litemod
};
/** General class for managed resources. It mirrors a file in disk, with some more info
* for display and house-keeping purposes.
*
* Subclass it to add additional data / behavior, such as Mods or Resource packs.
*/
class Resource : public QObject {
Q_OBJECT
Q_DISABLE_COPY(Resource)
public:
using Ptr = shared_qobject_ptr<Resource>;
Resource(QObject* parent = nullptr);
Resource(QFileInfo file_info);
~Resource() override = default;
void setFile(QFileInfo file_info);
void parseFile();
[[nodiscard]] auto fileinfo() const -> QFileInfo { return m_file_info; }
[[nodiscard]] auto dateTimeChanged() const -> QDateTime { return m_changed_date_time; }
[[nodiscard]] auto internal_id() const -> QString { return m_internal_id; }
[[nodiscard]] auto type() const -> ResourceType { return m_type; }
[[nodiscard]] virtual auto name() const -> QString { return m_name; }
[[nodiscard]] virtual bool valid() const { return m_type != ResourceType::UNKNOWN; }
[[nodiscard]] auto shouldResolve() const -> bool { return !m_is_resolving && !m_is_resolved; }
[[nodiscard]] auto isResolving() const -> bool { return m_is_resolving; }
[[nodiscard]] auto resolutionTicket() const -> int { return m_resolution_ticket; }
void setResolving(bool resolving, int resolutionTicket)
{
m_is_resolving = resolving;
m_resolution_ticket = resolutionTicket;
}
// Delete all files of this resource.
bool destroy();
protected:
/* The file corresponding to this resource. */
QFileInfo m_file_info;
/* The cached date when this file was last changed. */
QDateTime m_changed_date_time;
/* Internal ID for internal purposes. Properties such as human-readability should not be assumed. */
QString m_internal_id;
/* Name as reported via the file name. In the absence of a better name, this is shown to the user. */
QString m_name;
/* The type of file we're dealing with. */
ResourceType m_type = ResourceType::UNKNOWN;
/* Used to keep trach of pending / concluded actions on the resource. */
bool m_is_resolving = false;
bool m_is_resolved = false;
int m_resolution_ticket = 0;
};

View File

@ -110,7 +110,7 @@ void EnsureMetadataTask::executeTask()
} }
// Folders don't have metadata // Folders don't have metadata
if (mod->type() == Mod::MOD_FOLDER) { if (mod->type() == ResourceType::FOLDER) {
emitReady(mod); emitReady(mod);
} }
} }

View File

@ -23,7 +23,7 @@
void MCModInfoFrame::updateWithMod(Mod &m) void MCModInfoFrame::updateWithMod(Mod &m)
{ {
if (m.type() == m.MOD_FOLDER) if (m.type() == ResourceType::FOLDER)
{ {
clear(); clear();
return; return;