mirror of
https://github.com/PrismLauncher/PrismLauncher.git
synced 2025-05-01 23:24:31 +02:00
Use non-mod metadata in ModrinthPackExportTask
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
parent
5eff9b0934
commit
13e13ea8fc
@ -522,7 +522,8 @@ QStringList MinecraftInstance::javaArguments()
|
||||
|
||||
if (javaVersion.isModular() && shouldApplyOnlineFixes())
|
||||
// allow reflective access to java.net - required by the skin fix
|
||||
args << "--add-opens" << "java.base/java.net=ALL-UNNAMED";
|
||||
args << "--add-opens"
|
||||
<< "java.base/java.net=ALL-UNNAMED";
|
||||
|
||||
return args;
|
||||
}
|
||||
@ -796,8 +797,10 @@ QString MinecraftInstance::createLaunchScript(AuthSessionPtr session, MinecraftT
|
||||
QStringList MinecraftInstance::verboseDescription(AuthSessionPtr session, MinecraftTarget::Ptr targetToJoin)
|
||||
{
|
||||
QStringList out;
|
||||
out << "Main Class:" << " " + getMainClass() << "";
|
||||
out << "Native path:" << " " + getNativePath() << "";
|
||||
out << "Main Class:"
|
||||
<< " " + getMainClass() << "";
|
||||
out << "Native path:"
|
||||
<< " " + getNativePath() << "";
|
||||
|
||||
auto profile = m_components->getProfile();
|
||||
|
||||
@ -1227,6 +1230,11 @@ std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList()
|
||||
return m_shader_pack_list;
|
||||
}
|
||||
|
||||
QList<std::shared_ptr<ResourceFolderModel>> MinecraftInstance::resourceLists()
|
||||
{
|
||||
return { loaderModList(), coreModList(), nilModList(), resourcePackList(), texturePackList(), shaderPackList() };
|
||||
}
|
||||
|
||||
std::shared_ptr<WorldList> MinecraftInstance::worldList()
|
||||
{
|
||||
if (!m_world_list) {
|
||||
|
@ -116,6 +116,7 @@ class MinecraftInstance : public BaseInstance {
|
||||
std::shared_ptr<ResourcePackFolderModel> resourcePackList();
|
||||
std::shared_ptr<TexturePackFolderModel> texturePackList();
|
||||
std::shared_ptr<ShaderPackFolderModel> shaderPackList();
|
||||
QList<std::shared_ptr<ResourceFolderModel>> resourceLists();
|
||||
std::shared_ptr<WorldList> worldList();
|
||||
std::shared_ptr<GameOptions> gameOptionsModel();
|
||||
|
||||
|
@ -115,7 +115,7 @@ QString hash(QIODevice* device, Algorithm type)
|
||||
|
||||
QCryptographicHash hash(alg);
|
||||
if (!hash.addData(device))
|
||||
qCritical() << "Failed to read JAR to create hash!";
|
||||
qCritical() << "Failed to read file to create hash!";
|
||||
|
||||
Q_ASSERT(hash.result().length() == hash.hashLength(alg));
|
||||
auto result = hash.result().toHex();
|
||||
|
@ -34,22 +34,21 @@
|
||||
const QStringList ModrinthPackExportTask::PREFIXES({ "mods/", "coremods/", "resourcepacks/", "texturepacks/", "shaderpacks/" });
|
||||
const QStringList ModrinthPackExportTask::FILE_EXTENSIONS({ "jar", "litemod", "zip" });
|
||||
|
||||
ModrinthPackExportTask::ModrinthPackExportTask(const QString& name,
|
||||
const QString& version,
|
||||
const QString& summary,
|
||||
ModrinthPackExportTask::ModrinthPackExportTask(QString name,
|
||||
QString version,
|
||||
QString summary,
|
||||
bool optionalFiles,
|
||||
InstancePtr instance,
|
||||
const QString& output,
|
||||
MinecraftInstancePtr instance,
|
||||
QString output,
|
||||
MMCZip::FilterFunction filter)
|
||||
: name(name)
|
||||
, version(version)
|
||||
, summary(summary)
|
||||
: name(std::move(name))
|
||||
, version(std::move(version))
|
||||
, summary(std::move(summary))
|
||||
, optionalFiles(optionalFiles)
|
||||
, instance(instance)
|
||||
, mcInstance(dynamic_cast<MinecraftInstance*>(instance.get()))
|
||||
, gameRoot(instance->gameRoot())
|
||||
, output(output)
|
||||
, filter(filter)
|
||||
, instance(std::move(instance))
|
||||
, gameRoot(this->instance->gameRoot())
|
||||
, output(std::move(output))
|
||||
, filter(std::move(filter))
|
||||
{}
|
||||
|
||||
void ModrinthPackExportTask::executeTask()
|
||||
@ -83,20 +82,86 @@ void ModrinthPackExportTask::collectFiles()
|
||||
pendingHashes.clear();
|
||||
resolvedFiles.clear();
|
||||
|
||||
if (mcInstance) {
|
||||
mcInstance->loaderModList()->update();
|
||||
connect(mcInstance->loaderModList().get(), &ModFolderModel::updateFinished, this, &ModrinthPackExportTask::collectHashes);
|
||||
} else
|
||||
collectHashes();
|
||||
collectHashes();
|
||||
}
|
||||
|
||||
void ModrinthPackExportTask::collectHashes()
|
||||
{
|
||||
setStatus(tr("Finding file hashes..."));
|
||||
|
||||
for (const auto& model : instance->resourceLists()) {
|
||||
QCoreApplication::processEvents(); // TODO: maybe don't do this?
|
||||
|
||||
QEventLoop loop;
|
||||
connect(model.get(), &ModFolderModel::updateFinished, &loop, &QEventLoop::quit);
|
||||
model->update();
|
||||
loop.exec();
|
||||
|
||||
for (const Resource* resource : model->allResources()) {
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
if (resource->metadata() == nullptr)
|
||||
continue;
|
||||
|
||||
const QUrl& url = resource->metadata()->url;
|
||||
|
||||
if (url.isEmpty() || !BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host()))
|
||||
continue;
|
||||
|
||||
const QFileInfo& fileInfo = resource->fileinfo();
|
||||
const QString relativePath = gameRoot.relativeFilePath(fileInfo.absoluteFilePath());
|
||||
|
||||
if (filter(relativePath))
|
||||
continue;
|
||||
|
||||
qDebug() << "Resolving" << relativePath << "from index";
|
||||
|
||||
QString sha1;
|
||||
QString sha512;
|
||||
qint64 size;
|
||||
|
||||
if (resource->metadata()->hash_format == "sha1")
|
||||
sha1 = resource->metadata()->hash;
|
||||
else if (resource->metadata()->hash_format == "sha512")
|
||||
sha512 = resource->metadata()->hash;
|
||||
|
||||
{
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qWarning() << "Could not open" << relativePath << "for hashing";
|
||||
continue;
|
||||
}
|
||||
|
||||
const QByteArray data = file.readAll();
|
||||
|
||||
if (file.error() != QFileDevice::NoError) {
|
||||
qWarning() << "Could not read" << relativePath;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sha1.isEmpty())
|
||||
sha1 = Hashing::hash(data, Hashing::Algorithm::Sha1);
|
||||
|
||||
if (sha512.isEmpty())
|
||||
sha512 = Hashing::hash(data, Hashing::Algorithm::Sha512);
|
||||
|
||||
size = file.size();
|
||||
}
|
||||
|
||||
ResolvedFile resolvedFile{ sha1, sha512, url.toEncoded(), size, resource->metadata()->side };
|
||||
resolvedFiles[relativePath] = resolvedFile;
|
||||
}
|
||||
}
|
||||
|
||||
for (const QFileInfo& file : files) {
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
const QString relative = gameRoot.relativeFilePath(file.absoluteFilePath());
|
||||
|
||||
if (resolvedFiles.contains(relative))
|
||||
continue;
|
||||
|
||||
// require sensible file types
|
||||
if (!std::any_of(PREFIXES.begin(), PREFIXES.end(), [&relative](const QString& prefix) { return relative.startsWith(prefix); }))
|
||||
continue;
|
||||
@ -105,42 +170,8 @@ void ModrinthPackExportTask::collectHashes()
|
||||
}))
|
||||
continue;
|
||||
|
||||
QFile openFile(file.absoluteFilePath());
|
||||
if (!openFile.open(QFile::ReadOnly)) {
|
||||
qWarning() << "Could not open" << file << "for hashing";
|
||||
continue;
|
||||
}
|
||||
|
||||
const QByteArray data = openFile.readAll();
|
||||
if (openFile.error() != QFileDevice::NoError) {
|
||||
qWarning() << "Could not read" << file;
|
||||
continue;
|
||||
}
|
||||
auto sha512 = Hashing::hash(data, Hashing::Algorithm::Sha512);
|
||||
|
||||
auto allMods = mcInstance->loaderModList()->allMods();
|
||||
if (auto modIter = std::find_if(allMods.begin(), allMods.end(), [&file](Mod* mod) { return mod->fileinfo() == file; });
|
||||
modIter != allMods.end()) {
|
||||
const Mod* mod = *modIter;
|
||||
if (mod->metadata() != nullptr) {
|
||||
const QUrl& url = mod->metadata()->url;
|
||||
// ensure the url is permitted on modrinth.com
|
||||
if (!url.isEmpty() && BuildConfig.MODRINTH_MRPACK_HOSTS.contains(url.host())) {
|
||||
qDebug() << "Resolving" << relative << "from index";
|
||||
|
||||
auto sha1 = Hashing::hash(data, Hashing::Algorithm::Sha1);
|
||||
|
||||
ResolvedFile resolvedFile{ sha1, sha512, url.toEncoded(), openFile.size(), mod->metadata()->side };
|
||||
resolvedFiles[relative] = resolvedFile;
|
||||
|
||||
// nice! we've managed to resolve based on local metadata!
|
||||
// no need to enqueue it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Enqueueing" << relative << "for Modrinth query";
|
||||
auto sha512 = Hashing::hash(file.absoluteFilePath(), Hashing::Algorithm::Sha512);
|
||||
pendingHashes[relative] = sha512;
|
||||
}
|
||||
|
||||
@ -241,30 +272,28 @@ QByteArray ModrinthPackExportTask::generateIndex()
|
||||
if (!summary.isEmpty())
|
||||
out["summary"] = summary;
|
||||
|
||||
if (mcInstance) {
|
||||
auto profile = mcInstance->getPackProfile();
|
||||
// collect all supported components
|
||||
const ComponentPtr minecraft = profile->getComponent("net.minecraft");
|
||||
const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader");
|
||||
const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader");
|
||||
const ComponentPtr forge = profile->getComponent("net.minecraftforge");
|
||||
const ComponentPtr neoForge = profile->getComponent("net.neoforged");
|
||||
auto profile = instance->getPackProfile();
|
||||
// collect all supported components
|
||||
const ComponentPtr minecraft = profile->getComponent("net.minecraft");
|
||||
const ComponentPtr quilt = profile->getComponent("org.quiltmc.quilt-loader");
|
||||
const ComponentPtr fabric = profile->getComponent("net.fabricmc.fabric-loader");
|
||||
const ComponentPtr forge = profile->getComponent("net.minecraftforge");
|
||||
const ComponentPtr neoForge = profile->getComponent("net.neoforged");
|
||||
|
||||
// convert all available components to mrpack dependencies
|
||||
QJsonObject dependencies;
|
||||
if (minecraft != nullptr)
|
||||
dependencies["minecraft"] = minecraft->m_version;
|
||||
if (quilt != nullptr)
|
||||
dependencies["quilt-loader"] = quilt->m_version;
|
||||
if (fabric != nullptr)
|
||||
dependencies["fabric-loader"] = fabric->m_version;
|
||||
if (forge != nullptr)
|
||||
dependencies["forge"] = forge->m_version;
|
||||
if (neoForge != nullptr)
|
||||
dependencies["neoforge"] = neoForge->m_version;
|
||||
// convert all available components to mrpack dependencies
|
||||
QJsonObject dependencies;
|
||||
if (minecraft != nullptr)
|
||||
dependencies["minecraft"] = minecraft->m_version;
|
||||
if (quilt != nullptr)
|
||||
dependencies["quilt-loader"] = quilt->m_version;
|
||||
if (fabric != nullptr)
|
||||
dependencies["fabric-loader"] = fabric->m_version;
|
||||
if (forge != nullptr)
|
||||
dependencies["forge"] = forge->m_version;
|
||||
if (neoForge != nullptr)
|
||||
dependencies["neoforge"] = neoForge->m_version;
|
||||
|
||||
out["dependencies"] = dependencies;
|
||||
}
|
||||
out["dependencies"] = dependencies;
|
||||
|
||||
QJsonArray filesOut;
|
||||
for (auto iterator = resolvedFiles.constBegin(); iterator != resolvedFiles.constEnd(); iterator++) {
|
||||
|
@ -29,12 +29,12 @@
|
||||
class ModrinthPackExportTask : public Task {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ModrinthPackExportTask(const QString& name,
|
||||
const QString& version,
|
||||
const QString& summary,
|
||||
ModrinthPackExportTask(QString name,
|
||||
QString version,
|
||||
QString summary,
|
||||
bool optionalFiles,
|
||||
InstancePtr instance,
|
||||
const QString& output,
|
||||
MinecraftInstancePtr instance,
|
||||
QString output,
|
||||
MMCZip::FilterFunction filter);
|
||||
|
||||
protected:
|
||||
@ -54,8 +54,7 @@ class ModrinthPackExportTask : public Task {
|
||||
// inputs
|
||||
const QString name, version, summary;
|
||||
const bool optionalFiles;
|
||||
const InstancePtr instance;
|
||||
MinecraftInstance* mcInstance;
|
||||
const MinecraftInstancePtr instance;
|
||||
const QDir gameRoot;
|
||||
const QString output;
|
||||
const MMCZip::FilterFunction filter;
|
||||
|
@ -1403,27 +1403,26 @@ void MainWindow::on_actionExportInstanceZip_triggered()
|
||||
|
||||
void MainWindow::on_actionExportInstanceMrPack_triggered()
|
||||
{
|
||||
if (m_selectedInstance) {
|
||||
ExportPackDialog dlg(m_selectedInstance, this);
|
||||
auto instance = std::dynamic_pointer_cast<MinecraftInstance>(m_selectedInstance);
|
||||
if (instance) {
|
||||
ExportPackDialog dlg(std::move(instance), this);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExportInstanceFlamePack_triggered()
|
||||
{
|
||||
if (m_selectedInstance) {
|
||||
auto instance = dynamic_cast<MinecraftInstance*>(m_selectedInstance.get());
|
||||
if (instance) {
|
||||
if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft");
|
||||
cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Snapshots are currently not supported by CurseForge modpacks.");
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
ExportPackDialog dlg(m_selectedInstance, this, ModPlatform::ResourceProvider::FLAME);
|
||||
dlg.exec();
|
||||
auto instance = std::dynamic_pointer_cast<MinecraftInstance>(m_selectedInstance);
|
||||
if (instance) {
|
||||
if (auto cmp = instance->getPackProfile()->getComponent("net.minecraft");
|
||||
cmp && cmp->getVersionFile() && cmp->getVersionFile()->type == "snapshot") {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Snapshots are currently not supported by CurseForge modpacks.");
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
ExportPackDialog dlg(std::move(instance), this, ModPlatform::ResourceProvider::FLAME);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "MMCZip.h"
|
||||
#include "modplatform/modrinth/ModrinthPackExportTask.h"
|
||||
|
||||
ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPlatform::ResourceProvider provider)
|
||||
ExportPackDialog::ExportPackDialog(const MinecraftInstancePtr& instance, QWidget* parent, ModPlatform::ResourceProvider provider)
|
||||
: QDialog(parent), instance(instance), ui(new Ui::ExportPackDialog), m_provider(provider)
|
||||
{
|
||||
Q_ASSERT(m_provider == ModPlatform::ResourceProvider::MODRINTH || m_provider == ModPlatform::ResourceProvider::FLAME);
|
||||
@ -86,12 +86,9 @@ ExportPackDialog::ExportPackDialog(InstancePtr instance, QWidget* parent, ModPla
|
||||
proxy->blockedPaths().insert(file);
|
||||
}
|
||||
|
||||
MinecraftInstance* mcInstance = dynamic_cast<MinecraftInstance*>(instance.get());
|
||||
if (mcInstance) {
|
||||
const QDir index = mcInstance->loaderModList()->indexDir();
|
||||
if (index.exists())
|
||||
proxy->ignoreFilesWithPath().insert(root.relativeFilePath(index.absolutePath()));
|
||||
}
|
||||
for (auto& resourceModel : instance->resourceLists())
|
||||
if (resourceModel->indexDir().exists())
|
||||
proxy->ignoreFilesWithPath().insert(root.relativeFilePath(resourceModel->indexDir().absolutePath()));
|
||||
|
||||
ui->files->setModel(proxy);
|
||||
ui->files->setRootIndex(proxy->mapFromSource(model->index(instance->gameRoot())));
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <minecraft/MinecraftInstance.h>
|
||||
#include <QDialog>
|
||||
#include "BaseInstance.h"
|
||||
#include "FastFileIconProvider.h"
|
||||
@ -32,7 +33,7 @@ class ExportPackDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportPackDialog(InstancePtr instance,
|
||||
explicit ExportPackDialog(const MinecraftInstancePtr& instance,
|
||||
QWidget* parent = nullptr,
|
||||
ModPlatform::ResourceProvider provider = ModPlatform::ResourceProvider::MODRINTH);
|
||||
~ExportPackDialog();
|
||||
@ -41,7 +42,7 @@ class ExportPackDialog : public QDialog {
|
||||
void validate();
|
||||
|
||||
private:
|
||||
const InstancePtr instance;
|
||||
const MinecraftInstancePtr instance;
|
||||
Ui::ExportPackDialog* ui;
|
||||
FileIgnoreProxy* proxy;
|
||||
FastFileIconProvider icons;
|
||||
|
Loading…
x
Reference in New Issue
Block a user