aboutsummaryrefslogtreecommitdiff
path: root/launcher/modplatform
diff options
context:
space:
mode:
authorTheKodeToad <TheKodeToad@proton.me>2023-03-03 15:00:07 +0000
committerTheKodeToad <TheKodeToad@proton.me>2023-03-03 15:00:07 +0000
commit2343aad088e302bf9f4f75eb6c4d6d1da3c7fbe3 (patch)
tree719ffd8e61b067080f2e643ec4e545f8bcb2f91b /launcher/modplatform
parentdcaa907fede11c8f0aeddde8a78e8d9397eaee2f (diff)
downloadPrismLauncher-2343aad088e302bf9f4f75eb6c4d6d1da3c7fbe3.tar.gz
PrismLauncher-2343aad088e302bf9f4f75eb6c4d6d1da3c7fbe3.tar.bz2
PrismLauncher-2343aad088e302bf9f4f75eb6c4d6d1da3c7fbe3.zip
Make it work! (TODO make it not crash)
Signed-off-by: TheKodeToad <TheKodeToad@proton.me>
Diffstat (limited to 'launcher/modplatform')
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackExportTask.cpp119
-rw-r--r--launcher/modplatform/modrinth/ModrinthPackExportTask.h7
2 files changed, 108 insertions, 18 deletions
diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
index 1bb78cae..a319eec4 100644
--- a/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
+++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.cpp
@@ -17,12 +17,17 @@
*/
#include "ModrinthPackExportTask.h"
-#include <qtconcurrentrun.h>
+
+#include <qcryptographichash.h>
+#include <QFileInfo>
#include <QFileInfoList>
#include <QMessageBox>
+#include <QtConcurrent>
+#include "Json.h"
#include "MMCZip.h"
#include "minecraft/MinecraftInstance.h"
#include "minecraft/PackProfile.h"
+#include "modplatform/modrinth/ModrinthAPI.h"
ModrinthPackExportTask::ModrinthPackExportTask(const QString& name,
const QString& version,
@@ -35,13 +40,76 @@ ModrinthPackExportTask::ModrinthPackExportTask(const QString& name,
void ModrinthPackExportTask::executeTask()
{
- QtConcurrent::run(QThreadPool::globalInstance(), [this] {
- QFileInfoList files;
- if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) {
- emitFailed(tr("Could not collect list of files"));
- return;
+ setStatus(tr("Searching for files..."));
+
+ QFileInfoList files;
+ if (!MMCZip::collectFileListRecursively(instance->gameRoot(), nullptr, &files, filter)) {
+ emitFailed(tr("Could not collect list of files"));
+ return;
+ }
+
+ QDir mc(instance->gameRoot());
+
+ ModrinthAPI api;
+
+ static const QStringList prefixes({ "mods", "coremods", "resourcepacks", "texturepacks", "shaderpacks" });
+ // hash -> file
+ QMap<QString, QString> hashes;
+
+ for (QFileInfo file : files) {
+ QString relative = mc.relativeFilePath(file.absoluteFilePath());
+ // require sensible file types
+ if (!(relative.endsWith(".zip") || relative.endsWith(".jar") || relative.endsWith(".litemod")))
+ continue;
+
+ if (!std::any_of(prefixes.begin(), prefixes.end(),
+ [&relative](const QString& prefix) { return relative.startsWith(prefix + QDir::separator()); }))
+ continue;
+
+ QCryptographicHash hash(QCryptographicHash::Algorithm::Sha512);
+
+ QFile openFile(file.absoluteFilePath());
+ if (!openFile.open(QFile::ReadOnly)) {
+ qWarning() << "Could not open" << file << "for hashing";
+ continue;
}
+ if (!hash.addData(&openFile)) {
+ qWarning() << "Could not add hash data for" << file;
+ continue;
+ }
+
+ hashes[hash.result().toHex()] = relative;
+ }
+
+ QByteArray* response = new QByteArray;
+ Task::Ptr versionsTask = api.currentVersions(hashes.keys(), "sha512", response);
+ connect(versionsTask.get(), &NetJob::succeeded, this, [this, mc, files, hashes, response, versionsTask]() {
+ // file -> url
+ QMap<QString, ResolvedFile> resolved;
+
+ try {
+ QJsonDocument doc = Json::requireDocument(*response);
+ for (auto iter = hashes.keyBegin(); iter != hashes.keyEnd(); iter++) {
+ QJsonObject obj = doc[*iter].toObject();
+ if (obj.isEmpty())
+ continue;
+
+ QJsonArray files = obj["files"].toArray();
+ if (auto fileIter = std::find_if(files.begin(), files.end(),
+ [&iter](const QJsonValue& file) { return file["hashes"]["sha512"] == *iter; });
+ fileIter != files.end()) {
+ // map the file to the url
+ resolved[hashes[*iter]] = ResolvedFile{ fileIter->toObject()["hashes"].toObject()["sha1"].toString(), *iter,
+ fileIter->toObject()["url"].toString(), fileIter->toObject()["size"].toInt() };
+ }
+ }
+ } catch (Json::JsonException& e) {
+ qWarning() << "Failed to parse versions response" << e.what();
+ }
+
+ delete response;
+
setStatus("Adding files...");
QuaZip zip(output);
@@ -55,25 +123,19 @@ void ModrinthPackExportTask::executeTask()
QuaZipFile indexFile(&zip);
if (!indexFile.open(QIODevice::WriteOnly, QuaZipNewInfo("modrinth.index.json"))) {
QFile::remove(output);
-
emitFailed(tr("Could not create index"));
return;
}
- indexFile.write(generateIndex());
+ indexFile.write(generateIndex(resolved));
}
- // should exist
- QDir dotMinecraft(instance->gameRoot());
-
{
size_t i = 0;
for (const QFileInfo& file : files) {
setProgress(i, files.length());
- if (!JlCompress::compressFile(&zip, file.absoluteFilePath(),
- "overrides/" + dotMinecraft.relativeFilePath(file.absoluteFilePath()))) {
- emitFailed(tr("Could not compress %1").arg(file.absoluteFilePath()));
- return;
- }
+ QString relative = mc.relativeFilePath(file.absoluteFilePath());
+ if (!resolved.contains(relative) && !JlCompress::compressFile(&zip, file.absoluteFilePath(), "overrides/" + relative))
+ qWarning() << "Could not compress" << file;
i++;
}
}
@@ -88,9 +150,11 @@ void ModrinthPackExportTask::executeTask()
emitSucceeded();
});
+ connect(versionsTask.get(), &NetJob::failed, this, [this](const QString& reason) { emitFailed(reason); });
+ versionsTask->start();
}
-QByteArray ModrinthPackExportTask::generateIndex()
+QByteArray ModrinthPackExportTask::generateIndex(const QMap<QString, ResolvedFile>& urls)
{
QJsonObject obj;
obj["formatVersion"] = 1;
@@ -121,5 +185,26 @@ QByteArray ModrinthPackExportTask::generateIndex()
obj["dependencies"] = dependencies;
}
+ QJsonArray files;
+ QMapIterator<QString, ResolvedFile> iterator(urls);
+ while (iterator.hasNext()) {
+ iterator.next();
+
+ const ResolvedFile& value = iterator.value();
+
+ QJsonObject file;
+ file["path"] = iterator.key();
+ file["downloads"] = QJsonArray({ iterator.value().url });
+
+ QJsonObject hashes;
+ hashes["sha1"] = value.sha1;
+ hashes["sha512"] = value.sha512;
+ file["hashes"] = hashes;
+ file["fileSize"] = value.size;
+
+ files << file;
+ }
+ obj["files"] = files;
+
return QJsonDocument(obj).toJson(QJsonDocument::Compact);
} \ No newline at end of file
diff --git a/launcher/modplatform/modrinth/ModrinthPackExportTask.h b/launcher/modplatform/modrinth/ModrinthPackExportTask.h
index c38be204..974c9f0e 100644
--- a/launcher/modplatform/modrinth/ModrinthPackExportTask.h
+++ b/launcher/modplatform/modrinth/ModrinthPackExportTask.h
@@ -40,5 +40,10 @@ class ModrinthPackExportTask : public Task {
const QString output;
const MMCZip::FilterFunction filter;
- QByteArray generateIndex();
+ struct ResolvedFile {
+ QString sha1, sha512, url;
+ int size;
+ };
+
+ QByteArray generateIndex(const QMap<QString, ResolvedFile>& urls);
}; \ No newline at end of file