From 3b119ba465f13fce3ee2ce3e8968ec0ad84f582b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Mon, 21 Jul 2025 16:23:58 +0300 Subject: [PATCH] [PCKPacker] Add method to add files from buffer. --- core/io/pck_packer.cpp | 21 ++++++++++++++++----- core/io/pck_packer.h | 3 +++ doc/classes/PCKPacker.xml | 9 +++++++++ tests/core/io/test_pck_packer.h | 3 +++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index ee7bb15ba5..b6cae15397 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -49,6 +49,7 @@ static int _get_pad(int p_alignment, int p_n) { void PCKPacker::_bind_methods() { ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_file", "target_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_file_from_buffer", "target_path", "data", "encrypt"), &PCKPacker::add_file_from_buffer, DEFVAL(false)); ClassDB::bind_method(D_METHOD("add_file_removal", "target_path"), &PCKPacker::add_file_removal); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false)); } @@ -152,6 +153,17 @@ Error PCKPacker::add_file(const String &p_target_path, const String &p_source_pa if (f.is_null()) { return ERR_FILE_CANT_OPEN; } + Vector data = FileAccess::get_file_as_bytes(p_source_path); + + return _add_file(p_target_path, p_source_path, data, p_encrypt); +} + +Error PCKPacker::add_file_from_buffer(const String &p_target_path, const Vector &p_data, bool p_encrypt) { + return _add_file(p_target_path, "", p_data, p_encrypt); +} + +Error PCKPacker::_add_file(const String &p_target_path, const String &p_source_path, const Vector &p_data, bool p_encrypt) { + ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use."); File pf; // Simplify path here and on every 'files' access so that paths that have extra '/' @@ -159,12 +171,11 @@ Error PCKPacker::add_file(const String &p_target_path, const String &p_source_pa pf.path = p_target_path.simplify_path().trim_prefix("res://"); pf.src_path = p_source_path; pf.ofs = file->get_position(); - pf.size = f->get_length(); + pf.size = p_data.size(); - Vector data = FileAccess::get_file_as_bytes(p_source_path); { unsigned char hash[16]; - CryptoCore::md5(data.ptr(), data.size(), hash); + CryptoCore::md5(p_data.ptr(), p_data.size(), hash); pf.md5.resize(16); for (int i = 0; i < 16; i++) { pf.md5.write[i] = hash[i]; @@ -184,7 +195,7 @@ Error PCKPacker::add_file(const String &p_target_path, const String &p_source_pa ftmp = fae; } - ftmp->store_buffer(data); + ftmp->store_buffer(p_data); if (fae.is_valid()) { ftmp.unref(); @@ -256,7 +267,7 @@ Error PCKPacker::flush(bool p_verbose) { fhead->store_32(flags); if (p_verbose) { - print_line(vformat("[%d/%d - %d%%] PCKPacker flush: %s -> %s", i, file_num, float(i) / file_num * 100, files[i].src_path, files[i].path)); + print_line(vformat("[%d/%d - %d%%] PCKPacker flush: %s -> %s", i + 1, file_num, float(i + 1) / file_num * 100, files[i].src_path, files[i].path)); } } diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index c7a2b75995..e0c70501f2 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -60,9 +60,12 @@ class PCKPacker : public RefCounted { }; Vector files; + Error _add_file(const String &p_target_path, const String &p_source_path, const Vector &p_data, bool p_encrypt = false); + public: Error pck_start(const String &p_pck_path, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false); Error add_file(const String &p_target_path, const String &p_source_path, bool p_encrypt = false); + Error add_file_from_buffer(const String &p_target_path, const Vector &p_data, bool p_encrypt = false); Error add_file_removal(const String &p_target_path); Error flush(bool p_verbose = false); diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml index 90b9be6cd1..c6a97f02db 100644 --- a/doc/classes/PCKPacker.xml +++ b/doc/classes/PCKPacker.xml @@ -34,6 +34,15 @@ Adds the [param source_path] file to the current PCK package at the [param target_path] internal path. The [code]res://[/code] prefix for [param target_path] is optional and stripped internally. File content is immediately written to the PCK. + + + + + + + Adds the [param data] to the current PCK package at the [param target_path] internal path. The [code]res://[/code] prefix for [param target_path] is optional and stripped internally. File content is immediately written to the PCK. + + diff --git a/tests/core/io/test_pck_packer.h b/tests/core/io/test_pck_packer.h index 725564a91c..6b2eb164d5 100644 --- a/tests/core/io/test_pck_packer.h +++ b/tests/core/io/test_pck_packer.h @@ -100,6 +100,9 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") { CHECK_MESSAGE( pck_packer.add_file("some/directories with spaces/to/create/icon.png", base_dir.path_join("../logo.png")) == OK, "Overriding a non-flushed file to an existing subdirectory in the PCK should return an OK error code."); + CHECK_MESSAGE( + pck_packer.add_file_from_buffer("buffer/new.txt", String("Hello world!").to_utf8_buffer()) == OK, + "Adding a file from a buffer to the PCK in a new subdirectory should return an OK error code."); CHECK_MESSAGE( pck_packer.flush() == OK, "Flushing the PCK should return an OK error code.");