refactor: move resource pack file parsing utilities to separate namespace

This makes it easier to use that logic in other contexts.

Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
flow 2022-08-29 09:25:39 -03:00
parent 9b984cedac
commit 8a7e117f6b
No known key found for this signature in database
GPG Key ID: 8D0F221F0A59F469
3 changed files with 114 additions and 65 deletions

View File

@ -10,7 +10,6 @@ class Version;
/* TODO: /* TODO:
* *
* Store pack.png
* Store localized descriptions * Store localized descriptions
* */ * */

View File

@ -1,3 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.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 <https://www.gnu.org/licenses/>.
*/
#include "LocalResourcePackParseTask.h" #include "LocalResourcePackParseTask.h"
#include "FileSystem.h" #include "FileSystem.h"
@ -6,67 +24,28 @@
#include <quazip/quazip.h> #include <quazip/quazip.h>
#include <quazip/quazipfile.h> #include <quazip/quazipfile.h>
LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp) namespace ResourcePackUtils {
: Task(nullptr, false), m_token(token), m_resource_pack(rp)
{}
bool LocalResourcePackParseTask::abort() bool process(ResourcePack& pack)
{ {
m_aborted = true; switch (pack.type()) {
return true;
}
void LocalResourcePackParseTask::executeTask()
{
switch (m_resource_pack.type()) {
case ResourceType::FOLDER: case ResourceType::FOLDER:
processAsFolder(); ResourcePackUtils::processFolder(pack);
break; return true;
case ResourceType::ZIPFILE: case ResourceType::ZIPFILE:
processAsZip(); ResourcePackUtils::processZIP(pack);
break; return true;
default: default:
qWarning() << "Invalid type for resource pack parse task!"; qWarning() << "Invalid type for resource pack parse task!";
emitFailed(tr("Invalid type.")); return false;
}
} }
if (isFinished()) void processFolder(ResourcePack& pack)
return;
if (m_aborted)
emitAborted();
else
emitSucceeded();
}
// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
void LocalResourcePackParseTask::processMCMeta(QByteArray&& raw_data)
{ {
try { Q_ASSERT(pack.type() == ResourceType::FOLDER);
auto json_doc = QJsonDocument::fromJson(raw_data);
auto pack_obj = Json::requireObject(json_doc.object(), "pack", {});
m_resource_pack.setPackFormat(Json::ensureInteger(pack_obj, "pack_format", 0)); QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.mcmeta"));
m_resource_pack.setDescription(Json::ensureString(pack_obj, "description", ""));
} catch (Json::JsonException& e) {
qWarning() << "JsonException: " << e.what() << e.cause();
emitFailed(tr("Failed to process .mcmeta file."));
}
}
void LocalResourcePackParseTask::processPackPNG(QByteArray&& raw_data)
{
auto img = QImage::fromData(raw_data);
if (!img.isNull()) {
m_resource_pack.setImage(img);
} else {
qWarning() << "Failed to parse pack.png.";
}
}
void LocalResourcePackParseTask::processAsFolder()
{
QFileInfo mcmeta_file_info(FS::PathCombine(m_resource_pack.fileinfo().filePath(), "pack.mcmeta"));
if (mcmeta_file_info.isFile()) { if (mcmeta_file_info.isFile()) {
QFile mcmeta_file(mcmeta_file_info.filePath()); QFile mcmeta_file(mcmeta_file_info.filePath());
if (!mcmeta_file.open(QIODevice::ReadOnly)) if (!mcmeta_file.open(QIODevice::ReadOnly))
@ -74,12 +53,12 @@ void LocalResourcePackParseTask::processAsFolder()
auto data = mcmeta_file.readAll(); auto data = mcmeta_file.readAll();
processMCMeta(std::move(data)); ResourcePackUtils::processMCMeta(pack, std::move(data));
mcmeta_file.close(); mcmeta_file.close();
} }
QFileInfo image_file_info(FS::PathCombine(m_resource_pack.fileinfo().filePath(), "pack.png")); QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
if (image_file_info.isFile()) { if (image_file_info.isFile()) {
QFile mcmeta_file(image_file_info.filePath()); QFile mcmeta_file(image_file_info.filePath());
if (!mcmeta_file.open(QIODevice::ReadOnly)) if (!mcmeta_file.open(QIODevice::ReadOnly))
@ -87,15 +66,17 @@ void LocalResourcePackParseTask::processAsFolder()
auto data = mcmeta_file.readAll(); auto data = mcmeta_file.readAll();
processPackPNG(std::move(data)); ResourcePackUtils::processPackPNG(pack, std::move(data));
mcmeta_file.close(); mcmeta_file.close();
} }
} }
void LocalResourcePackParseTask::processAsZip() void processZIP(ResourcePack& pack)
{ {
QuaZip zip(m_resource_pack.fileinfo().filePath()); Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
QuaZip zip(pack.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip)) if (!zip.open(QuaZip::mdUnzip))
return; return;
@ -110,7 +91,7 @@ void LocalResourcePackParseTask::processAsZip()
auto data = file.readAll(); auto data = file.readAll();
processMCMeta(std::move(data)); ResourcePackUtils::processMCMeta(pack, std::move(data));
file.close(); file.close();
} }
@ -124,10 +105,58 @@ void LocalResourcePackParseTask::processAsZip()
auto data = file.readAll(); auto data = file.readAll();
processPackPNG(std::move(data)); ResourcePackUtils::processPackPNG(pack, std::move(data));
file.close(); file.close();
} }
zip.close(); zip.close();
} }
// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
void processMCMeta(ResourcePack& 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();
}
}
void processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
{
auto img = QImage::fromData(raw_data);
if (!img.isNull()) {
pack.setImage(img);
} else {
qWarning() << "Failed to parse pack.png.";
}
}
} // namespace ResourcePackUtils
LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp)
: Task(nullptr, false), m_token(token), m_resource_pack(rp)
{}
bool LocalResourcePackParseTask::abort()
{
m_aborted = true;
return true;
}
void LocalResourcePackParseTask::executeTask()
{
Q_ASSERT(m_resource_pack.valid());
if (!ResourcePackUtils::process(m_resource_pack))
return;
if (m_aborted)
emitAborted();
else
emitSucceeded();
}

View File

@ -1,3 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PolyMC - Minecraft Launcher
* Copyright (c) 2022 flowln <flowlnlnln@gmail.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 <https://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <QDebug> #include <QDebug>
@ -7,6 +25,16 @@
#include "tasks/Task.h" #include "tasks/Task.h"
namespace ResourcePackUtils {
bool process(ResourcePack& pack);
void processZIP(ResourcePack& pack);
void processFolder(ResourcePack& pack);
void processMCMeta(ResourcePack& pack, QByteArray&& raw_data);
void processPackPNG(ResourcePack& pack, QByteArray&& raw_data);
} // namespace ResourcePackUtils
class LocalResourcePackParseTask : public Task { class LocalResourcePackParseTask : public Task {
Q_OBJECT Q_OBJECT
public: public:
@ -19,13 +47,6 @@ class LocalResourcePackParseTask : public Task {
[[nodiscard]] int token() const { return m_token; } [[nodiscard]] int token() const { return m_token; }
private:
void processMCMeta(QByteArray&& raw_data);
void processPackPNG(QByteArray&& raw_data);
void processAsFolder();
void processAsZip();
private: private:
int m_token; int m_token;