feat: add initial support for parseing datapacks
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
parent
dd3848d7b1
commit
64c51a70a3
@ -331,6 +331,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/mod/Resource.cpp
|
minecraft/mod/Resource.cpp
|
||||||
minecraft/mod/ResourceFolderModel.h
|
minecraft/mod/ResourceFolderModel.h
|
||||||
minecraft/mod/ResourceFolderModel.cpp
|
minecraft/mod/ResourceFolderModel.cpp
|
||||||
|
minecraft/mod/DataPack.h
|
||||||
|
minecraft/mod/DataPack.cpp
|
||||||
minecraft/mod/ResourcePack.h
|
minecraft/mod/ResourcePack.h
|
||||||
minecraft/mod/ResourcePack.cpp
|
minecraft/mod/ResourcePack.cpp
|
||||||
minecraft/mod/ResourcePackFolderModel.h
|
minecraft/mod/ResourcePackFolderModel.h
|
||||||
@ -347,6 +349,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/mod/tasks/LocalModParseTask.cpp
|
minecraft/mod/tasks/LocalModParseTask.cpp
|
||||||
minecraft/mod/tasks/LocalModUpdateTask.h
|
minecraft/mod/tasks/LocalModUpdateTask.h
|
||||||
minecraft/mod/tasks/LocalModUpdateTask.cpp
|
minecraft/mod/tasks/LocalModUpdateTask.cpp
|
||||||
|
minecraft/mod/tasks/LocalDataPackParseTask.h
|
||||||
|
minecraft/mod/tasks/LocalDataPackParseTask.cpp
|
||||||
minecraft/mod/tasks/LocalResourcePackParseTask.h
|
minecraft/mod/tasks/LocalResourcePackParseTask.h
|
||||||
minecraft/mod/tasks/LocalResourcePackParseTask.cpp
|
minecraft/mod/tasks/LocalResourcePackParseTask.cpp
|
||||||
minecraft/mod/tasks/LocalTexturePackParseTask.h
|
minecraft/mod/tasks/LocalTexturePackParseTask.h
|
||||||
|
110
launcher/minecraft/mod/DataPack.cpp
Normal file
110
launcher/minecraft/mod/DataPack.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DataPack.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
#include "minecraft/mod/tasks/LocalDataPackParseTask.h"
|
||||||
|
|
||||||
|
// Values taken from:
|
||||||
|
// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_data_pack#%22pack_format%22
|
||||||
|
static const QMap<int, std::pair<Version, Version>> s_pack_format_versions = {
|
||||||
|
{ 4, { Version("1.13"), Version("1.14.4") } }, { 5, { Version("1.15"), Version("1.16.1") } },
|
||||||
|
{ 6, { Version("1.16.2"), Version("1.16.5") } }, { 7, { Version("1.17"), Version("1.17.1") } },
|
||||||
|
{ 8, { Version("1.18"), Version("1.18.1") } }, { 9, { Version("1.18.2"), Version("1.18.2") } },
|
||||||
|
{ 10, { Version("1.19"), Version("1.19.3") } },
|
||||||
|
};
|
||||||
|
|
||||||
|
void DataPack::setPackFormat(int new_format_id)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_data_lock);
|
||||||
|
|
||||||
|
if (!s_pack_format_versions.contains(new_format_id)) {
|
||||||
|
qWarning() << "Pack format '%1' is not a recognized resource pack id!";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pack_format = new_format_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataPack::setDescription(QString new_description)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_data_lock);
|
||||||
|
|
||||||
|
m_description = new_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Version, Version> DataPack::compatibleVersions() const
|
||||||
|
{
|
||||||
|
if (!s_pack_format_versions.contains(m_pack_format)) {
|
||||||
|
return { {}, {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_pack_format_versions.constFind(m_pack_format).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<int, bool> DataPack::compare(const Resource& other, SortType type) const
|
||||||
|
{
|
||||||
|
auto const& cast_other = static_cast<DataPack const&>(other);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
default: {
|
||||||
|
auto res = Resource::compare(other, type);
|
||||||
|
if (res.first != 0)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
case SortType::PACK_FORMAT: {
|
||||||
|
auto this_ver = packFormat();
|
||||||
|
auto other_ver = cast_other.packFormat();
|
||||||
|
|
||||||
|
if (this_ver > other_ver)
|
||||||
|
return { 1, type == SortType::PACK_FORMAT };
|
||||||
|
if (this_ver < other_ver)
|
||||||
|
return { -1, type == SortType::PACK_FORMAT };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { 0, false };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataPack::applyFilter(QRegularExpression filter) const
|
||||||
|
{
|
||||||
|
if (filter.match(description()).hasMatch())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (filter.match(QString::number(packFormat())).hasMatch())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (filter.match(compatibleVersions().first.toString()).hasMatch())
|
||||||
|
return true;
|
||||||
|
if (filter.match(compatibleVersions().second.toString()).hasMatch())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return Resource::applyFilter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataPack::valid() const
|
||||||
|
{
|
||||||
|
return m_pack_format != 0;
|
||||||
|
}
|
73
launcher/minecraft/mod/DataPack.h
Normal file
73
launcher/minecraft/mod/DataPack.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource.h"
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
class Version;
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
*
|
||||||
|
* Store localized descriptions
|
||||||
|
* */
|
||||||
|
|
||||||
|
class DataPack : public Resource {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
using Ptr = shared_qobject_ptr<Resource>;
|
||||||
|
|
||||||
|
DataPack(QObject* parent = nullptr) : Resource(parent) {}
|
||||||
|
DataPack(QFileInfo file_info) : Resource(file_info) {}
|
||||||
|
|
||||||
|
/** Gets the numerical ID of the pack format. */
|
||||||
|
[[nodiscard]] int packFormat() const { return m_pack_format; }
|
||||||
|
/** Gets, respectively, the lower and upper versions supported by the set pack format. */
|
||||||
|
[[nodiscard]] std::pair<Version, Version> compatibleVersions() const;
|
||||||
|
|
||||||
|
/** Gets the description of the resource pack. */
|
||||||
|
[[nodiscard]] QString description() const { return m_description; }
|
||||||
|
|
||||||
|
/** Thread-safe. */
|
||||||
|
void setPackFormat(int new_format_id);
|
||||||
|
|
||||||
|
/** Thread-safe. */
|
||||||
|
void setDescription(QString new_description);
|
||||||
|
|
||||||
|
bool valid() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto compare(Resource const& other, SortType type) const -> std::pair<int, bool> override;
|
||||||
|
[[nodiscard]] bool applyFilter(QRegularExpression filter) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mutable QMutex m_data_lock;
|
||||||
|
|
||||||
|
/* The 'version' of a resource pack, as defined in the pack.mcmeta file.
|
||||||
|
* See https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
|
||||||
|
*/
|
||||||
|
int m_pack_format = 0;
|
||||||
|
|
||||||
|
/** The resource pack's description, as defined in the pack.mcmeta file.
|
||||||
|
*/
|
||||||
|
QString m_description;
|
||||||
|
};
|
@ -17,7 +17,9 @@ static const QMap<int, std::pair<Version, Version>> s_pack_format_versions = {
|
|||||||
{ 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } },
|
{ 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } },
|
||||||
{ 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } },
|
{ 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } },
|
||||||
{ 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.2") } },
|
{ 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.2") } },
|
||||||
{ 9, { Version("1.19"), Version("1.19.2") } }, { 11, { Version("1.19.3"), Version("1.19.3") } },
|
{ 9, { Version("1.19"), Version("1.19.2") } },
|
||||||
|
// { 11, { Version("22w42a"), Version("22w44a") } }
|
||||||
|
{ 12, { Version("1.19.3"), Version("1.19.3") } },
|
||||||
};
|
};
|
||||||
|
|
||||||
void ResourcePack::setPackFormat(int new_format_id)
|
void ResourcePack::setPackFormat(int new_format_id)
|
||||||
|
169
launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
Normal file
169
launcher/minecraft/mod/tasks/LocalDataPackParseTask.cpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LocalDataPackParseTask.h"
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "Json.h"
|
||||||
|
|
||||||
|
#include <quazip/quazip.h>
|
||||||
|
#include <quazip/quazipfile.h>
|
||||||
|
#include <quazip/quazipdir.h>
|
||||||
|
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
64
launcher/minecraft/mod/tasks/LocalDataPackParseTask.h
Normal file
64
launcher/minecraft/mod/tasks/LocalDataPackParseTask.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "minecraft/mod/DataPack.h"
|
||||||
|
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
namespace DataPackUtils {
|
||||||
|
|
||||||
|
enum class ProcessingLevel { Full, BasicInfoOnly };
|
||||||
|
|
||||||
|
bool process(DataPack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
|
bool processZIP(DataPack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
bool processFolder(DataPack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
|
bool processMCMeta(DataPack& pack, QByteArray&& raw_data);
|
||||||
|
|
||||||
|
/** Checks whether a file is valid as a resource pack or not. */
|
||||||
|
bool validate(QFileInfo file);
|
||||||
|
} // namespace ResourcePackUtils
|
||||||
|
|
||||||
|
class LocalDataPackParseTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LocalDataPackParseTask(int token, DataPack& rp);
|
||||||
|
|
||||||
|
[[nodiscard]] bool canAbort() const override { return true; }
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
|
void executeTask() override;
|
||||||
|
|
||||||
|
[[nodiscard]] int token() const { return m_token; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_token;
|
||||||
|
|
||||||
|
DataPack& m_resource_pack;
|
||||||
|
|
||||||
|
bool m_aborted = false;
|
||||||
|
};
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <quazip/quazip.h>
|
#include <quazip/quazip.h>
|
||||||
#include <quazip/quazipfile.h>
|
#include <quazip/quazipfile.h>
|
||||||
|
#include <quazip/quazipdir.h>
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
@ -32,58 +33,74 @@ bool process(ResourcePack& pack, ProcessingLevel level)
|
|||||||
{
|
{
|
||||||
switch (pack.type()) {
|
switch (pack.type()) {
|
||||||
case ResourceType::FOLDER:
|
case ResourceType::FOLDER:
|
||||||
ResourcePackUtils::processFolder(pack, level);
|
return ResourcePackUtils::processFolder(pack, level);
|
||||||
return true;
|
|
||||||
case ResourceType::ZIPFILE:
|
case ResourceType::ZIPFILE:
|
||||||
ResourcePackUtils::processZIP(pack, level);
|
return ResourcePackUtils::processZIP(pack, level);
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
qWarning() << "Invalid type for resource pack parse task!";
|
qWarning() << "Invalid type for resource pack parse task!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void processFolder(ResourcePack& pack, ProcessingLevel level)
|
bool processFolder(ResourcePack& pack, ProcessingLevel level)
|
||||||
{
|
{
|
||||||
Q_ASSERT(pack.type() == ResourceType::FOLDER);
|
Q_ASSERT(pack.type() == ResourceType::FOLDER);
|
||||||
|
|
||||||
QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.mcmeta"));
|
QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.mcmeta"));
|
||||||
if (mcmeta_file_info.isFile()) {
|
if (mcmeta_file_info.exists() && 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))
|
||||||
return;
|
return false; // can't open mcmeta file
|
||||||
|
|
||||||
auto data = mcmeta_file.readAll();
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
ResourcePackUtils::processMCMeta(pack, std::move(data));
|
bool mcmeta_result = ResourcePackUtils::processMCMeta(pack, std::move(data));
|
||||||
|
|
||||||
mcmeta_file.close();
|
mcmeta_file.close();
|
||||||
|
if (!mcmeta_result) {
|
||||||
|
return false; // mcmeta invalid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false; // mcmeta file isn't a valid file
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == ProcessingLevel::BasicInfoOnly)
|
QFileInfo assets_dir_info(FS::PathCombine(pack.fileinfo().filePath(), "assets"));
|
||||||
return;
|
if (!assets_dir_info.exists() || !assets_dir_info.isDir()) {
|
||||||
|
return false; // assets dir does not exists or isn't valid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level == ProcessingLevel::BasicInfoOnly) {
|
||||||
|
return true; // only need basic info already checked
|
||||||
|
}
|
||||||
|
|
||||||
QFileInfo image_file_info(FS::PathCombine(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.exists() && 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))
|
||||||
return;
|
return false; // can't open pack.png file
|
||||||
|
|
||||||
auto data = mcmeta_file.readAll();
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
ResourcePackUtils::processPackPNG(pack, std::move(data));
|
bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
mcmeta_file.close();
|
mcmeta_file.close();
|
||||||
|
if (!pack_png_result) {
|
||||||
|
return false; // pack.png invalid
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false; // pack.png does not exists or is not a valid file.
|
||||||
}
|
}
|
||||||
|
|
||||||
void processZIP(ResourcePack& pack, ProcessingLevel level)
|
return true; // all tests passed
|
||||||
|
}
|
||||||
|
|
||||||
|
bool processZIP(ResourcePack& pack, ProcessingLevel level)
|
||||||
{
|
{
|
||||||
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||||
|
|
||||||
QuaZip zip(pack.fileinfo().filePath());
|
QuaZip zip(pack.fileinfo().filePath());
|
||||||
if (!zip.open(QuaZip::mdUnzip))
|
if (!zip.open(QuaZip::mdUnzip))
|
||||||
return;
|
return false; // can't open zip file
|
||||||
|
|
||||||
QuaZipFile file(&zip);
|
QuaZipFile file(&zip);
|
||||||
|
|
||||||
@ -91,40 +108,57 @@ void processZIP(ResourcePack& pack, ProcessingLevel level)
|
|||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qCritical() << "Failed to open file in zip.";
|
qCritical() << "Failed to open file in zip.";
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = file.readAll();
|
auto data = file.readAll();
|
||||||
|
|
||||||
ResourcePackUtils::processMCMeta(pack, std::move(data));
|
bool mcmeta_result = ResourcePackUtils::processMCMeta(pack, std::move(data));
|
||||||
|
|
||||||
file.close();
|
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("/assets")) {
|
||||||
|
return false; // assets dir does not exists at zip root
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == ProcessingLevel::BasicInfoOnly) {
|
if (level == ProcessingLevel::BasicInfoOnly) {
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return true; // only need basic info already checked
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zip.setCurrentFile("pack.png")) {
|
if (zip.setCurrentFile("pack.png")) {
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qCritical() << "Failed to open file in zip.";
|
qCritical() << "Failed to open file in zip.";
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = file.readAll();
|
auto data = file.readAll();
|
||||||
|
|
||||||
ResourcePackUtils::processPackPNG(pack, std::move(data));
|
bool pack_png_result = ResourcePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
if (!pack_png_result) {
|
||||||
|
return false; // pack.png invalid
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false; // could not set pack.mcmeta as current file.
|
||||||
}
|
}
|
||||||
|
|
||||||
zip.close();
|
zip.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
|
// https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta
|
||||||
void processMCMeta(ResourcePack& pack, QByteArray&& raw_data)
|
bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
auto json_doc = QJsonDocument::fromJson(raw_data);
|
auto json_doc = QJsonDocument::fromJson(raw_data);
|
||||||
@ -134,17 +168,21 @@ void processMCMeta(ResourcePack& pack, QByteArray&& raw_data)
|
|||||||
pack.setDescription(Json::ensureString(pack_obj, "description", ""));
|
pack.setDescription(Json::ensureString(pack_obj, "description", ""));
|
||||||
} catch (Json::JsonException& e) {
|
} catch (Json::JsonException& e) {
|
||||||
qWarning() << "JsonException: " << e.what() << e.cause();
|
qWarning() << "JsonException: " << e.what() << e.cause();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
|
bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
|
||||||
{
|
{
|
||||||
auto img = QImage::fromData(raw_data);
|
auto img = QImage::fromData(raw_data);
|
||||||
if (!img.isNull()) {
|
if (!img.isNull()) {
|
||||||
pack.setImage(img);
|
pack.setImage(img);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to parse pack.png.";
|
qWarning() << "Failed to parse pack.png.";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate(QFileInfo file)
|
bool validate(QFileInfo file)
|
||||||
|
@ -31,11 +31,11 @@ enum class ProcessingLevel { Full, BasicInfoOnly };
|
|||||||
|
|
||||||
bool process(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool process(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
void processZIP(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool processZIP(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
void processFolder(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool processFolder(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
void processMCMeta(ResourcePack& pack, QByteArray&& raw_data);
|
bool processMCMeta(ResourcePack& pack, QByteArray&& raw_data);
|
||||||
void processPackPNG(ResourcePack& pack, QByteArray&& raw_data);
|
bool processPackPNG(ResourcePack& pack, QByteArray&& raw_data);
|
||||||
|
|
||||||
/** Checks whether a file is valid as a resource pack or not. */
|
/** Checks whether a file is valid as a resource pack or not. */
|
||||||
bool validate(QFileInfo file);
|
bool validate(QFileInfo file);
|
||||||
|
@ -32,18 +32,16 @@ bool process(TexturePack& pack, ProcessingLevel level)
|
|||||||
{
|
{
|
||||||
switch (pack.type()) {
|
switch (pack.type()) {
|
||||||
case ResourceType::FOLDER:
|
case ResourceType::FOLDER:
|
||||||
TexturePackUtils::processFolder(pack, level);
|
return TexturePackUtils::processFolder(pack, level);
|
||||||
return true;
|
|
||||||
case ResourceType::ZIPFILE:
|
case ResourceType::ZIPFILE:
|
||||||
TexturePackUtils::processZIP(pack, level);
|
return TexturePackUtils::processZIP(pack, level);
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
qWarning() << "Invalid type for resource pack parse task!";
|
qWarning() << "Invalid type for resource pack parse task!";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void processFolder(TexturePack& pack, ProcessingLevel level)
|
bool processFolder(TexturePack& pack, ProcessingLevel level)
|
||||||
{
|
{
|
||||||
Q_ASSERT(pack.type() == ResourceType::FOLDER);
|
Q_ASSERT(pack.type() == ResourceType::FOLDER);
|
||||||
|
|
||||||
@ -51,39 +49,51 @@ void processFolder(TexturePack& pack, ProcessingLevel level)
|
|||||||
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))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
auto data = mcmeta_file.readAll();
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
TexturePackUtils::processPackTXT(pack, std::move(data));
|
bool packTXT_result = TexturePackUtils::processPackTXT(pack, std::move(data));
|
||||||
|
|
||||||
mcmeta_file.close();
|
mcmeta_file.close();
|
||||||
|
if (!packTXT_result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == ProcessingLevel::BasicInfoOnly)
|
if (level == ProcessingLevel::BasicInfoOnly)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
QFileInfo image_file_info(FS::PathCombine(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))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
auto data = mcmeta_file.readAll();
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
TexturePackUtils::processPackPNG(pack, std::move(data));
|
bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
mcmeta_file.close();
|
mcmeta_file.close();
|
||||||
|
if (!packPNG_result) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processZIP(TexturePack& pack, ProcessingLevel level)
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool processZIP(TexturePack& pack, ProcessingLevel level)
|
||||||
{
|
{
|
||||||
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||||
|
|
||||||
QuaZip zip(pack.fileinfo().filePath());
|
QuaZip zip(pack.fileinfo().filePath());
|
||||||
if (!zip.open(QuaZip::mdUnzip))
|
if (!zip.open(QuaZip::mdUnzip))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
QuaZipFile file(&zip);
|
QuaZipFile file(&zip);
|
||||||
|
|
||||||
@ -91,51 +101,62 @@ void processZIP(TexturePack& pack, ProcessingLevel level)
|
|||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qCritical() << "Failed to open file in zip.";
|
qCritical() << "Failed to open file in zip.";
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = file.readAll();
|
auto data = file.readAll();
|
||||||
|
|
||||||
TexturePackUtils::processPackTXT(pack, std::move(data));
|
bool packTXT_result = TexturePackUtils::processPackTXT(pack, std::move(data));
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
if (!packTXT_result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level == ProcessingLevel::BasicInfoOnly) {
|
if (level == ProcessingLevel::BasicInfoOnly) {
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zip.setCurrentFile("pack.png")) {
|
if (zip.setCurrentFile("pack.png")) {
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
qCritical() << "Failed to open file in zip.";
|
qCritical() << "Failed to open file in zip.";
|
||||||
zip.close();
|
zip.close();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = file.readAll();
|
auto data = file.readAll();
|
||||||
|
|
||||||
TexturePackUtils::processPackPNG(pack, std::move(data));
|
bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
if (!packPNG_result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zip.close();
|
zip.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processPackTXT(TexturePack& pack, QByteArray&& raw_data)
|
bool processPackTXT(TexturePack& pack, QByteArray&& raw_data)
|
||||||
{
|
{
|
||||||
pack.setDescription(QString(raw_data));
|
pack.setDescription(QString(raw_data));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processPackPNG(TexturePack& pack, QByteArray&& raw_data)
|
bool processPackPNG(TexturePack& pack, QByteArray&& raw_data)
|
||||||
{
|
{
|
||||||
auto img = QImage::fromData(raw_data);
|
auto img = QImage::fromData(raw_data);
|
||||||
if (!img.isNull()) {
|
if (!img.isNull()) {
|
||||||
pack.setImage(img);
|
pack.setImage(img);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Failed to parse pack.png.";
|
qWarning() << "Failed to parse pack.png.";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validate(QFileInfo file)
|
bool validate(QFileInfo file)
|
||||||
|
@ -32,11 +32,11 @@ enum class ProcessingLevel { Full, BasicInfoOnly };
|
|||||||
|
|
||||||
bool process(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool process(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
void processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
void processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
bool processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
|
||||||
|
|
||||||
void processPackTXT(TexturePack& pack, QByteArray&& raw_data);
|
bool processPackTXT(TexturePack& pack, QByteArray&& raw_data);
|
||||||
void processPackPNG(TexturePack& pack, QByteArray&& raw_data);
|
bool processPackPNG(TexturePack& pack, QByteArray&& raw_data);
|
||||||
|
|
||||||
/** Checks whether a file is valid as a texture pack or not. */
|
/** Checks whether a file is valid as a texture pack or not. */
|
||||||
bool validate(QFileInfo file);
|
bool validate(QFileInfo file);
|
||||||
|
@ -27,6 +27,9 @@ ecm_add_test(ResourcePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VER
|
|||||||
ecm_add_test(TexturePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
ecm_add_test(TexturePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
TEST_NAME TexturePackParse)
|
TEST_NAME TexturePackParse)
|
||||||
|
|
||||||
|
ecm_add_test(DataPackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
|
TEST_NAME DataPackParse)
|
||||||
|
|
||||||
ecm_add_test(ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
ecm_add_test(ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
TEST_NAME ParseUtils)
|
TEST_NAME ParseUtils)
|
||||||
|
|
||||||
|
76
tests/DataPackParse_test.cpp
Normal file
76
tests/DataPackParse_test.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 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 <QTest>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <FileSystem.h>
|
||||||
|
|
||||||
|
#include <minecraft/mod/DataPack.h>
|
||||||
|
#include <minecraft/mod/tasks/LocalDataPackParseTask.h>
|
||||||
|
|
||||||
|
class DataPackParseTest : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void test_parseZIP()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/DataPackParse");
|
||||||
|
|
||||||
|
QString zip_dp = FS::PathCombine(source, "test_data_pack_boogaloo.zip");
|
||||||
|
DataPack pack { QFileInfo(zip_dp) };
|
||||||
|
|
||||||
|
bool valid = DataPackUtils::processZIP(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.packFormat() == 4);
|
||||||
|
QVERIFY(pack.description() == "Some data pack 2 boobgaloo");
|
||||||
|
QVERIFY(valid == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_parseFolder()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/DataPackParse");
|
||||||
|
|
||||||
|
QString folder_dp = FS::PathCombine(source, "test_folder");
|
||||||
|
DataPack pack { QFileInfo(folder_dp) };
|
||||||
|
|
||||||
|
bool valid = DataPackUtils::processFolder(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.packFormat() == 10);
|
||||||
|
QVERIFY(pack.description() == "Some data pack, maybe");
|
||||||
|
QVERIFY(valid == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_parseFolder2()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/DataPackParse");
|
||||||
|
|
||||||
|
QString folder_dp = FS::PathCombine(source, "another_test_folder");
|
||||||
|
DataPack pack { QFileInfo(folder_dp) };
|
||||||
|
|
||||||
|
bool valid = DataPackUtils::process(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.packFormat() == 6);
|
||||||
|
QVERIFY(pack.description() == "Some data pack three, leaves on the tree");
|
||||||
|
QVERIFY(valid == true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(DataPackParseTest)
|
||||||
|
|
||||||
|
#include "DataPackParse_test.moc"
|
6
tests/testdata/DataPackParse/another_test_folder/pack.mcmeta
vendored
Normal file
6
tests/testdata/DataPackParse/another_test_folder/pack.mcmeta
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"pack_format": 6,
|
||||||
|
"description": "Some data pack three, leaves on the tree"
|
||||||
|
}
|
||||||
|
}
|
BIN
tests/testdata/DataPackParse/test_data_pack_boogaloo.zip
vendored
Normal file
BIN
tests/testdata/DataPackParse/test_data_pack_boogaloo.zip
vendored
Normal file
Binary file not shown.
6
tests/testdata/DataPackParse/test_folder/pack.mcmeta
vendored
Normal file
6
tests/testdata/DataPackParse/test_folder/pack.mcmeta
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"pack_format": 10,
|
||||||
|
"description": "Some data pack, maybe"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user