Merge pull request #853 from kumquat-ir/nil
NilLoader mod metadata support
This commit is contained in:
@ -1038,6 +1038,7 @@ target_link_libraries(Launcher_logic
|
||||
nbt++
|
||||
${ZLIB_LIBRARIES}
|
||||
tomlplusplus::tomlplusplus
|
||||
qdcss
|
||||
BuildConfig
|
||||
Katabasis
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
|
@ -36,9 +36,10 @@ public:
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
values.append(ManagedPackPage::createPage(onesix.get()));
|
||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod *.nilmod)");
|
||||
values.append(modsPage);
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList()));
|
||||
values.append(new NilModFolderPage(onesix.get(), onesix->nilModList()));
|
||||
values.append(new ResourcePackPage(onesix.get(), onesix->resourcePackList()));
|
||||
values.append(new TexturePackPage(onesix.get(), onesix->texturePackList()));
|
||||
values.append(new ShaderPackPage(onesix.get(), onesix->shaderPackList()));
|
||||
|
@ -290,6 +290,11 @@ QString MinecraftInstance::coreModsDir() const
|
||||
return FS::PathCombine(gameRoot(), "coremods");
|
||||
}
|
||||
|
||||
QString MinecraftInstance::nilModsDir() const
|
||||
{
|
||||
return FS::PathCombine(gameRoot(), "nilmods");
|
||||
}
|
||||
|
||||
QString MinecraftInstance::resourcePacksDir() const
|
||||
{
|
||||
return FS::PathCombine(gameRoot(), "resourcepacks");
|
||||
@ -1125,6 +1130,18 @@ std::shared_ptr<ModFolderModel> MinecraftInstance::coreModList() const
|
||||
return m_core_mod_list;
|
||||
}
|
||||
|
||||
std::shared_ptr<ModFolderModel> MinecraftInstance::nilModList() const
|
||||
{
|
||||
if (!m_nil_mod_list)
|
||||
{
|
||||
bool is_indexed = !APPLICATION->settings()->get("ModMetadataDisabled").toBool();
|
||||
m_nil_mod_list.reset(new ModFolderModel(nilModsDir(), is_indexed, false));
|
||||
m_nil_mod_list->disableInteraction(isRunning());
|
||||
connect(this, &BaseInstance::runningStatusChanged, m_nil_mod_list.get(), &ModFolderModel::disableInteraction);
|
||||
}
|
||||
return m_nil_mod_list;
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() const
|
||||
{
|
||||
if (!m_resource_pack_list)
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
QString shaderPacksDir() const;
|
||||
QString modsRoot() const override;
|
||||
QString coreModsDir() const;
|
||||
QString nilModsDir() const;
|
||||
QString modsCacheLocation() const;
|
||||
QString libDir() const;
|
||||
QString worldDir() const;
|
||||
@ -116,6 +117,7 @@ public:
|
||||
////// Mod Lists //////
|
||||
std::shared_ptr<ModFolderModel> loaderModList() const;
|
||||
std::shared_ptr<ModFolderModel> coreModList() const;
|
||||
std::shared_ptr<ModFolderModel> nilModList() const;
|
||||
std::shared_ptr<ResourcePackFolderModel> resourcePackList() const;
|
||||
std::shared_ptr<TexturePackFolderModel> texturePackList() const;
|
||||
std::shared_ptr<ShaderPackFolderModel> shaderPackList() const;
|
||||
@ -170,6 +172,7 @@ 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_nil_mod_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;
|
||||
|
@ -55,6 +55,12 @@ void ScanModFolders::executeTask()
|
||||
if(!cores->update()) {
|
||||
m_coreModsDone = true;
|
||||
}
|
||||
|
||||
auto nils = m_inst->nilModList();
|
||||
connect(nils.get(), &ModFolderModel::updateFinished, this, &ScanModFolders::nilModsDone);
|
||||
if(!nils->update()) {
|
||||
m_nilModsDone = true;
|
||||
}
|
||||
checkDone();
|
||||
}
|
||||
|
||||
@ -70,9 +76,15 @@ void ScanModFolders::coreModsDone()
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void ScanModFolders::nilModsDone()
|
||||
{
|
||||
m_nilModsDone = true;
|
||||
checkDone();
|
||||
}
|
||||
|
||||
void ScanModFolders::checkDone()
|
||||
{
|
||||
if(m_modsDone && m_coreModsDone) {
|
||||
if(m_modsDone && m_coreModsDone && m_nilModsDone) {
|
||||
emitSucceeded();
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,12 @@ public:
|
||||
private slots:
|
||||
void coreModsDone();
|
||||
void modsDone();
|
||||
void nilModsDone();
|
||||
private:
|
||||
void checkDone();
|
||||
|
||||
private: // DATA
|
||||
bool m_modsDone = false;
|
||||
bool m_nilModsDone = false;
|
||||
bool m_coreModsDone = false;
|
||||
};
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
|
||||
#include "modplatform/ModIndex.h"
|
||||
|
||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed, bool create_dir) : ResourceFolderModel(QDir(dir), nullptr, create_dir), m_is_indexed(is_indexed)
|
||||
{
|
||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE, SortType::PROVIDER };
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
Enable,
|
||||
Toggle
|
||||
};
|
||||
ModFolderModel(const QString &dir, bool is_indexed = false);
|
||||
ModFolderModel(const QString &dir, bool is_indexed = false, bool create_dir = true);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
|
@ -37,6 +37,9 @@ void Resource::parseFile()
|
||||
if (file_name.endsWith(".zip") || file_name.endsWith(".jar")) {
|
||||
m_type = ResourceType::ZIPFILE;
|
||||
file_name.chop(4);
|
||||
} else if (file_name.endsWith(".nilmod")) {
|
||||
m_type = ResourceType::ZIPFILE;
|
||||
file_name.chop(7);
|
||||
} else if (file_name.endsWith(".litemod")) {
|
||||
m_type = ResourceType::LITEMOD;
|
||||
file_name.chop(8);
|
||||
|
@ -12,9 +12,11 @@
|
||||
|
||||
#include "tasks/Task.h"
|
||||
|
||||
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
||||
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent, bool create_dir) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
||||
{
|
||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||
if (create_dir) {
|
||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||
}
|
||||
|
||||
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||
m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
|
||||
|
@ -24,7 +24,7 @@ class QSortFilterProxyModel;
|
||||
class ResourceFolderModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ResourceFolderModel(QDir, QObject* parent = nullptr);
|
||||
ResourceFolderModel(QDir, QObject* parent = nullptr, bool create_dir = true);
|
||||
~ResourceFolderModel() override;
|
||||
|
||||
/** Starts watching the paths for changes.
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <quazip/quazip.h>
|
||||
#include <quazip/quazipfile.h>
|
||||
#include <toml++/toml.h>
|
||||
#include <qdcss.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
@ -285,6 +286,32 @@ ModDetails ReadLiteModInfo(QByteArray contents)
|
||||
return details;
|
||||
}
|
||||
|
||||
// https://git.sleeping.town/unascribed/NilLoader/src/commit/d7fc87b255fc31019ff90f80d45894927fac6efc/src/main/java/nilloader/api/NilMetadata.java#L64
|
||||
ModDetails ReadNilModInfo(QByteArray contents, QString fname)
|
||||
{
|
||||
ModDetails details;
|
||||
|
||||
QDCSS cssData = QDCSS(contents);
|
||||
auto name = cssData.get("@nilmod.name");
|
||||
auto desc = cssData.get("@nilmod.description");
|
||||
auto authors = cssData.get("@nilmod.authors");
|
||||
|
||||
if (name->has_value()) {
|
||||
details.name = name->value();
|
||||
}
|
||||
if (desc->has_value()) {
|
||||
details.description = desc->value();
|
||||
}
|
||||
if (authors->has_value()) {
|
||||
details.authors.append(authors->value());
|
||||
}
|
||||
details.version = cssData.get("@nilmod.version")->value_or("?");
|
||||
|
||||
details.mod_id = fname.remove(".nilmod.css");
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
bool process(Mod& mod, ProcessingLevel level)
|
||||
{
|
||||
switch (mod.type()) {
|
||||
@ -401,6 +428,32 @@ bool processZIP(Mod& mod, ProcessingLevel level)
|
||||
|
||||
mod.setDetails(details);
|
||||
return true;
|
||||
} else if (zip.setCurrentFile("META-INF/nil/mappings.json")) {
|
||||
// nilloader uses the filename of the metadata file for the modid, so we can't know the exact filename
|
||||
// thankfully, there is a good file to use as a canary so we don't look for nil meta all the time
|
||||
|
||||
QString foundNilMeta;
|
||||
for (auto& fname : zip.getFileNameList()) {
|
||||
// nilmods can shade nilloader to be able to run as a standalone agent - which includes nilloader's own meta file
|
||||
if (fname.endsWith(".nilmod.css") && fname != "nilloader.nilmod.css") {
|
||||
foundNilMeta = fname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (zip.setCurrentFile(foundNilMeta)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
zip.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
details = ReadNilModInfo(file.readAll(), foundNilMeta);
|
||||
file.close();
|
||||
zip.close();
|
||||
|
||||
mod.setDetails(details);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
zip.close();
|
||||
|
@ -273,3 +273,12 @@ bool CoreModFolderPage::shouldDisplay() const
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NilModFolderPage::NilModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel> mods, QWidget* parent)
|
||||
: ModFolderPage(inst, mods, parent)
|
||||
{}
|
||||
|
||||
bool NilModFolderPage::shouldDisplay() const
|
||||
{
|
||||
return m_model->dir().exists();
|
||||
}
|
||||
|
@ -81,3 +81,16 @@ class CoreModFolderPage : public ModFolderPage {
|
||||
|
||||
virtual bool shouldDisplay() const override;
|
||||
};
|
||||
|
||||
class NilModFolderPage : public ModFolderPage {
|
||||
public:
|
||||
explicit NilModFolderPage(BaseInstance* inst, std::shared_ptr<ModFolderModel> mods, QWidget* parent = 0);
|
||||
virtual ~NilModFolderPage() = default;
|
||||
|
||||
virtual QString displayName() const override { return tr("Nilmods"); }
|
||||
virtual QIcon icon() const override { return APPLICATION->getThemedIcon("coremods"); }
|
||||
virtual QString id() const override { return "nilmods"; }
|
||||
virtual QString helpPage() const override { return "Nilmods"; }
|
||||
|
||||
virtual bool shouldDisplay() const override;
|
||||
};
|
||||
|
Reference in New Issue
Block a user