From 64c51a70a3aa110131fb6ad0cabc07ccfdcbb1c0 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 9 Dec 2022 20:26:05 -0700
Subject: feat: add initial support for parseing datapacks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
.../minecraft/mod/tasks/LocalDataPackParseTask.cpp | 169 +++++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
(limited to 'launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp')
diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
new file mode 100644
index 00000000..8bc8278b
--- /dev/null
+++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
@@ -0,0 +1,169 @@
+// SPDX-FileCopyrightText: 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/*
+ * Prism Launcher - Minecraft Launcher
+ * Copyright (C) 2022 Rachel Powers <508861+Ryex@users.noreply.github.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "LocalDataPackParseTask.h"
+
+#include "FileSystem.h"
+#include "Json.h"
+
+#include
+#include
+#include
+
+#include
+
+namespace DataPackUtils {
+
+bool process(DataPack& pack, ProcessingLevel level)
+{
+ switch (pack.type()) {
+ case ResourceType::FOLDER:
+ return DataPackUtils::processFolder(pack, level);
+ case ResourceType::ZIPFILE:
+ return DataPackUtils::processZIP(pack, level);
+ default:
+ qWarning() << "Invalid type for resource pack parse task!";
+ return false;
+ }
+}
+
+bool processFolder(DataPack& pack, ProcessingLevel level)
+{
+ Q_ASSERT(pack.type() == ResourceType::FOLDER);
+
+ QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.mcmeta"));
+ if (mcmeta_file_info.exists() && mcmeta_file_info.isFile()) {
+ QFile mcmeta_file(mcmeta_file_info.filePath());
+ if (!mcmeta_file.open(QIODevice::ReadOnly))
+ return false; // can't open mcmeta file
+
+ auto data = mcmeta_file.readAll();
+
+ bool mcmeta_result = DataPackUtils::processMCMeta(pack, std::move(data));
+
+ mcmeta_file.close();
+ if (!mcmeta_result) {
+ return false; // mcmeta invalid
+ }
+ } else {
+ return false; // mcmeta file isn't a valid file
+ }
+
+ QFileInfo data_dir_info(FS::PathCombine(pack.fileinfo().filePath(), "data"));
+ if (!data_dir_info.exists() || !data_dir_info.isDir()) {
+ return false; // data dir does not exists or isn't valid
+ }
+
+ if (level == ProcessingLevel::BasicInfoOnly) {
+ return true; // only need basic info already checked
+ }
+
+ return true; // all tests passed
+}
+
+bool processZIP(DataPack& pack, ProcessingLevel level)
+{
+ Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
+
+ QuaZip zip(pack.fileinfo().filePath());
+ if (!zip.open(QuaZip::mdUnzip))
+ return false; // can't open zip file
+
+ QuaZipFile file(&zip);
+
+ if (zip.setCurrentFile("pack.mcmeta")) {
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCritical() << "Failed to open file in zip.";
+ zip.close();
+ return false;
+ }
+
+ auto data = file.readAll();
+
+ bool mcmeta_result = DataPackUtils::processMCMeta(pack, std::move(data));
+
+ file.close();
+ if (!mcmeta_result) {
+ return false; // mcmeta invalid
+ }
+ } else {
+ return false; // could not set pack.mcmeta as current file.
+ }
+
+ QuaZipDir zipDir(&zip);
+ if (!zipDir.exists("/data")) {
+ return false; // data dir does not exists at zip root
+ }
+
+ if (level == ProcessingLevel::BasicInfoOnly) {
+ zip.close();
+ return true; // only need basic info already checked
+ }
+
+ zip.close();
+
+ return true;
+}
+
+// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
+bool processMCMeta(DataPack& pack, QByteArray&& raw_data)
+{
+ try {
+ auto json_doc = QJsonDocument::fromJson(raw_data);
+ auto pack_obj = Json::requireObject(json_doc.object(), "pack", {});
+
+ pack.setPackFormat(Json::ensureInteger(pack_obj, "pack_format", 0));
+ pack.setDescription(Json::ensureString(pack_obj, "description", ""));
+ } catch (Json::JsonException& e) {
+ qWarning() << "JsonException: " << e.what() << e.cause();
+ return false;
+ }
+ return true;
+}
+
+bool validate(QFileInfo file)
+{
+ DataPack dp{ file };
+ return DataPackUtils::process(dp, ProcessingLevel::BasicInfoOnly) && dp.valid();
+}
+
+} // namespace DataPackUtils
+
+LocalDataPackParseTask::LocalDataPackParseTask(int token, DataPack& dp)
+ : Task(nullptr, false), m_token(token), m_resource_pack(dp)
+{}
+
+bool LocalDataPackParseTask::abort()
+{
+ m_aborted = true;
+ return true;
+}
+
+void LocalDataPackParseTask::executeTask()
+{
+ if (!DataPackUtils::process(m_resource_pack))
+ return;
+
+ if (m_aborted)
+ emitAborted();
+ else
+ emitSucceeded();
+}
--
cgit
From 3691f3a2963c77dbd7b469b4b90ca79b61014d43 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Mon, 26 Dec 2022 14:29:13 -0700
Subject: fix: cleanup and suggested changes
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
.../minecraft/mod/tasks/LocalDataPackParseTask.cpp | 46 +++++++++++++---------
1 file changed, 27 insertions(+), 19 deletions(-)
(limited to 'launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp')
diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
index 8bc8278b..3fcb2110 100644
--- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
@@ -25,8 +25,8 @@
#include "Json.h"
#include
-#include
#include
+#include
#include
@@ -40,7 +40,7 @@ bool process(DataPack& pack, ProcessingLevel level)
case ResourceType::ZIPFILE:
return DataPackUtils::processZIP(pack, level);
default:
- qWarning() << "Invalid type for resource pack parse task!";
+ qWarning() << "Invalid type for data pack parse task!";
return false;
}
}
@@ -49,11 +49,16 @@ bool processFolder(DataPack& pack, ProcessingLevel level)
{
Q_ASSERT(pack.type() == ResourceType::FOLDER);
+ auto mcmeta_invalid = [&pack]() {
+ qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
+ return false; // the mcmeta is not optional
+ };
+
QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.mcmeta"));
if (mcmeta_file_info.exists() && mcmeta_file_info.isFile()) {
QFile mcmeta_file(mcmeta_file_info.filePath());
if (!mcmeta_file.open(QIODevice::ReadOnly))
- return false; // can't open mcmeta file
+ return mcmeta_invalid(); // can't open mcmeta file
auto data = mcmeta_file.readAll();
@@ -61,22 +66,22 @@ bool processFolder(DataPack& pack, ProcessingLevel level)
mcmeta_file.close();
if (!mcmeta_result) {
- return false; // mcmeta invalid
+ return mcmeta_invalid(); // mcmeta invalid
}
} else {
- return false; // mcmeta file isn't a valid file
+ return mcmeta_invalid(); // mcmeta file isn't a valid file
}
QFileInfo data_dir_info(FS::PathCombine(pack.fileinfo().filePath(), "data"));
if (!data_dir_info.exists() || !data_dir_info.isDir()) {
- return false; // data dir does not exists or isn't valid
+ return false; // data dir does not exists or isn't valid
}
if (level == ProcessingLevel::BasicInfoOnly) {
- return true; // only need basic info already checked
+ return true; // only need basic info already checked
}
- return true; // all tests passed
+ return true; // all tests passed
}
bool processZIP(DataPack& pack, ProcessingLevel level)
@@ -85,15 +90,20 @@ bool processZIP(DataPack& pack, ProcessingLevel level)
QuaZip zip(pack.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
- return false; // can't open zip file
+ return false; // can't open zip file
QuaZipFile file(&zip);
+ auto mcmeta_invalid = [&pack]() {
+ qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
+ return false; // the mcmeta is not optional
+ };
+
if (zip.setCurrentFile("pack.mcmeta")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
- return false;
+ return mcmeta_invalid();
}
auto data = file.readAll();
@@ -102,20 +112,20 @@ bool processZIP(DataPack& pack, ProcessingLevel level)
file.close();
if (!mcmeta_result) {
- return false; // mcmeta invalid
+ return mcmeta_invalid(); // mcmeta invalid
}
} else {
- return false; // could not set pack.mcmeta as current file.
+ return mcmeta_invalid(); // could not set pack.mcmeta as current file.
}
QuaZipDir zipDir(&zip);
if (!zipDir.exists("/data")) {
- return false; // data dir does not exists at zip root
+ return false; // data dir does not exists at zip root
}
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
- return true; // only need basic info already checked
+ return true; // only need basic info already checked
}
zip.close();
@@ -123,7 +133,7 @@ bool processZIP(DataPack& pack, ProcessingLevel level)
return true;
}
-// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
+// https://minecraft.fandom.com/wiki/Data_pack#pack.mcmeta
bool processMCMeta(DataPack& pack, QByteArray&& raw_data)
{
try {
@@ -147,9 +157,7 @@ bool validate(QFileInfo file)
} // namespace DataPackUtils
-LocalDataPackParseTask::LocalDataPackParseTask(int token, DataPack& dp)
- : Task(nullptr, false), m_token(token), m_resource_pack(dp)
-{}
+LocalDataPackParseTask::LocalDataPackParseTask(int token, DataPack& dp) : Task(nullptr, false), m_token(token), m_data_pack(dp) {}
bool LocalDataPackParseTask::abort()
{
@@ -159,7 +167,7 @@ bool LocalDataPackParseTask::abort()
void LocalDataPackParseTask::executeTask()
{
- if (!DataPackUtils::process(m_resource_pack))
+ if (!DataPackUtils::process(m_data_pack))
return;
if (m_aborted)
--
cgit
From 03b75bf2a98edd4114be4799f974bb10fe9b82c4 Mon Sep 17 00:00:00 2001
From: Rachel Powers <508861+Ryex@users.noreply.github.com>
Date: Fri, 30 Dec 2022 18:06:17 -0700
Subject: feat: Import all the things!
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
---
launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp')
diff --git a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
index 3fcb2110..5bb44877 100644
--- a/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
@@ -50,7 +50,7 @@ bool processFolder(DataPack& pack, ProcessingLevel level)
Q_ASSERT(pack.type() == ResourceType::FOLDER);
auto mcmeta_invalid = [&pack]() {
- qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
+ qWarning() << "Data pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
return false; // the mcmeta is not optional
};
@@ -95,7 +95,7 @@ bool processZIP(DataPack& pack, ProcessingLevel level)
QuaZipFile file(&zip);
auto mcmeta_invalid = [&pack]() {
- qWarning() << "Resource pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
+ qWarning() << "Data pack at" << pack.fileinfo().filePath() << "does not have a valid pack.mcmeta";
return false; // the mcmeta is not optional
};
--
cgit