zip support cleanups.

This commit is contained in:
Relintai 2023-12-16 21:37:45 +01:00
parent 8f12605cd5
commit decd780d70
13 changed files with 2 additions and 1879 deletions

View File

@ -33,7 +33,6 @@
#include "core/bind/core_bind.h"
#include "core/core_string_names.h"
#include "core/io/file_access_network.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
@ -41,8 +40,6 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
#include <zlib.h>
const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "import";
ProjectSettings *ProjectSettings::singleton = nullptr;
@ -276,24 +273,6 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_files, int p_offset) {
if (PackedData::get_singleton()->is_disabled()) {
return false;
}
bool ok = PackedData::get_singleton()->add_pack(p_pack, p_replace_files, p_offset) == OK;
if (!ok) {
return false;
}
//if data.pck is found, all directory access will be from here
DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
using_datapack = true;
return true;
}
void ProjectSettings::_convert_to_last_version(int p_from_version) {
if (p_from_version <= 3) {
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
@ -356,84 +335,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
return err;
}
// Attempt with a user-defined main pack first
if (p_main_pack != "") {
bool ok = _load_resource_pack(p_main_pack);
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'.");
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
if (err == OK && !p_ignore_override) {
// Load override from location of the main pack
// Optional, we don't mind if it fails
_load_settings_text(p_main_pack.get_base_dir().plus_file("override.cfg"));
}
return err;
}
String exec_path = OS::get_singleton()->get_executable_path();
if (exec_path != "") {
// We do several tests sequentially until one succeeds to find a PCK,
// and if so we attempt loading it at the end.
// Attempt with PCK bundled into executable.
bool found = _load_resource_pack(exec_path);
// Attempt with exec_name.pck.
// (This is the usual case when distributing a Pandemonium game.)
String exec_dir = exec_path.get_base_dir();
String exec_filename = exec_path.get_file();
String exec_basename = exec_filename.get_basename();
// Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle)
// or the exec path's basename + '.pck' (Windows).
// We need to test both possibilities as extensions for Linux binaries are optional
// (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck').
#ifdef OSX_ENABLED
if (!found) {
// Attempt to load PCK from macOS .app bundle resources.
found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_filename + ".pck"));
}
#endif
if (!found) {
// Try to load data pack at the location of the executable.
// As mentioned above, we have two potential names to attempt.
found = _load_resource_pack(exec_dir.plus_file(exec_basename + ".pck")) || _load_resource_pack(exec_dir.plus_file(exec_filename + ".pck"));
}
if (!found) {
// If we couldn't find them next to the executable, we attempt
// the current working directory. Same story, two tests.
found = _load_resource_pack(exec_basename + ".pck") || _load_resource_pack(exec_filename + ".pck");
}
// If we opened our package, try and load our project.
if (found) {
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
if (err == OK && !p_ignore_override) {
// Load override from location of the executable.
// Optional, we don't mind if it fails.
_load_settings_text(exec_path.get_base_dir().plus_file("override.cfg"));
}
return err;
}
}
// Try to use the filesystem for files, according to OS.
// (Only Android -when reading from pck- and iOS use this.)
if (OS::get_singleton()->get_resource_dir() != "") {
Error err = _load_settings_text_or_binary("res://project.pandemonium", "res://project.binary");
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
_load_settings_text("res://override.cfg");
}
return err;
}
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
@ -1001,7 +902,6 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("localize_path", "path"), &ProjectSettings::localize_path);
ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
ClassDB::bind_method(D_METHOD("save"), &ProjectSettings::save);
ClassDB::bind_method(D_METHOD("load_resource_pack", "pack", "replace_files", "offset"), &ProjectSettings::_load_resource_pack, DEFVAL(true), DEFVAL(0));
ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ProjectSettings::property_can_revert);
ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);

View File

@ -134,9 +134,7 @@ protected:
Error _save_custom_bnd(const String &p_file);
void _convert_to_last_version(int p_from_version);
bool _load_resource_pack(const String &p_pack, bool p_replace_files = true, int p_offset = 0);
void _add_property_info_bind(const Dictionary &p_info);
Error _setup(const String &p_path, const String &p_main_pack, bool p_upwards = false, bool p_ignore_override = false);

View File

@ -1,542 +0,0 @@
/*************************************************************************/
/* file_access_pack.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "file_access_pack.h"
#include "core/os/os.h"
#include "core/version.h"
#include <stdio.h>
Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
for (int i = 0; i < sources.size(); i++) {
if (sources[i]->try_open_pack(p_path, p_replace_files, p_offset)) {
return OK;
};
};
return ERR_FILE_UNRECOGNIZED;
};
void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {
PathMD5 pmd5(p_path.md5_buffer());
bool exists = files.has(pmd5);
PackedFile pf;
pf.pack = p_pkg_path;
pf.offset = p_ofs;
pf.size = p_size;
for (int i = 0; i < 16; i++) {
pf.md5[i] = p_md5[i];
}
pf.src = p_src;
if (!exists || p_replace_files) {
files[pmd5] = pf;
}
if (!exists) {
//search for dir
String p = p_path.replace_first("res://", "");
PackedDir *cd = root;
if (p.find("/") != -1) { //in a subdir
Vector<String> ds = p.get_base_dir().split("/");
for (int j = 0; j < ds.size(); j++) {
if (!cd->subdirs.has(ds[j])) {
PackedDir *pd = memnew(PackedDir);
pd->name = ds[j];
pd->parent = cd;
cd->subdirs[pd->name] = pd;
cd = pd;
} else {
cd = cd->subdirs[ds[j]];
}
}
}
String filename = p_path.get_file();
// Don't add as a file if the path points to a directory
if (!filename.empty()) {
cd->files.insert(filename);
}
}
}
void PackedData::add_pack_source(PackSource *p_source) {
if (p_source != nullptr) {
sources.push_back(p_source);
}
};
PackedData *PackedData::singleton = nullptr;
PackedData::PackedData() {
singleton = this;
root = memnew(PackedDir);
root->parent = nullptr;
disabled = false;
add_pack_source(memnew(PackedSourcePCK));
}
void PackedData::_free_packed_dirs(PackedDir *p_dir) {
for (RBMap<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) {
_free_packed_dirs(E->get());
}
memdelete(p_dir);
}
PackedData::~PackedData() {
for (int i = 0; i < sources.size(); i++) {
memdelete(sources[i]);
}
_free_packed_dirs(root);
}
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
return false;
}
bool pck_header_found = false;
// Search for the header at the start offset - standalone PCK file.
f->seek(p_offset);
uint32_t magic = f->get_32();
if (magic == PACK_HEADER_MAGIC) {
pck_header_found = true;
}
// Search for the header in the executable "pck" section - self contained executable.
if (!pck_header_found) {
// Loading with offset feature not supported for self contained exe files.
if (p_offset != 0) {
f->close();
memdelete(f);
ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
}
int64_t pck_off = OS::get_singleton()->get_embedded_pck_offset();
if (pck_off != 0) {
// Search for the header, in case PCK start and section have different alignment.
for (int i = 0; i < 8; i++) {
f->seek(pck_off);
magic = f->get_32();
if (magic == PACK_HEADER_MAGIC) {
#ifdef DEBUG_ENABLED
print_verbose("PCK header found in executable pck section, loading from offset 0x" + String::num_int64(pck_off - 4, 16));
#endif
pck_header_found = true;
break;
}
pck_off++;
}
}
}
// Search for the header at the end of file - self contained executable.
if (!pck_header_found) {
// Loading with offset feature not supported for self contained exe files.
if (p_offset != 0) {
f->close();
memdelete(f);
ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
}
f->seek_end();
f->seek(f->get_position() - 4);
magic = f->get_32();
if (magic == PACK_HEADER_MAGIC) {
f->seek(f->get_position() - 12);
uint64_t ds = f->get_64();
f->seek(f->get_position() - ds - 8);
magic = f->get_32();
if (magic == PACK_HEADER_MAGIC) {
#ifdef DEBUG_ENABLED
print_verbose("PCK header found at the end of executable, loading from offset 0x" + String::num_int64(f->get_position() - 4, 16));
#endif
pck_header_found = true;
}
}
}
if (!pck_header_found) {
f->close();
memdelete(f);
return false;
}
uint32_t version = f->get_32();
uint32_t ver_major = f->get_32();
uint32_t ver_minor = f->get_32();
f->get_32(); // patch number, not used for validation.
if (version != PACK_FORMAT_VERSION) {
f->close();
memdelete(f);
ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
}
if (ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR)) {
f->close();
memdelete(f);
ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
}
for (int i = 0; i < 16; i++) {
//reserved
f->get_32();
}
int file_count = f->get_32();
for (int i = 0; i < file_count; i++) {
uint32_t sl = f->get_32();
CharString cs;
cs.resize(sl + 1);
f->get_buffer((uint8_t *)cs.ptr(), sl);
cs[sl] = 0;
String path;
path.parse_utf8(cs.ptr());
uint64_t ofs = f->get_64();
uint64_t size = f->get_64();
uint8_t md5[16];
f->get_buffer(md5, 16);
PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files);
};
f->close();
memdelete(f);
return true;
};
FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessPack(p_path, *p_file));
};
//////////////////////////////////////////////////////////////////
Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_V(ERR_UNAVAILABLE);
return ERR_UNAVAILABLE;
}
void FileAccessPack::close() {
f->close();
}
bool FileAccessPack::is_open() const {
return f->is_open();
}
void FileAccessPack::seek(uint64_t p_position) {
if (p_position > pf.size) {
eof = true;
} else {
eof = false;
}
f->seek(pf.offset + p_position);
pos = p_position;
}
void FileAccessPack::seek_end(int64_t p_position) {
seek(pf.size + p_position);
}
uint64_t FileAccessPack::get_position() const {
return pos;
}
uint64_t FileAccessPack::get_len() const {
return pf.size;
}
bool FileAccessPack::eof_reached() const {
return eof;
}
uint8_t FileAccessPack::get_8() const {
if (pos >= pf.size) {
eof = true;
return 0;
}
pos++;
return f->get_8();
}
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (eof) {
return 0;
}
int64_t to_read = p_length;
if (to_read + pos > pf.size) {
eof = true;
to_read = (int64_t)pf.size - (int64_t)pos;
}
pos += p_length;
if (to_read <= 0) {
return 0;
}
f->get_buffer(p_dst, to_read);
return to_read;
}
void FileAccessPack::set_endian_swap(bool p_swap) {
FileAccess::set_endian_swap(p_swap);
f->set_endian_swap(p_swap);
}
Error FileAccessPack::get_error() const {
if (eof) {
return ERR_FILE_EOF;
}
return OK;
}
void FileAccessPack::flush() {
ERR_FAIL();
}
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
}
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
bool FileAccessPack::file_exists(const String &p_name) {
return false;
}
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'.");
f->seek(pf.offset);
pos = 0;
eof = false;
}
FileAccessPack::~FileAccessPack() {
if (f) {
memdelete(f);
}
}
//////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////
Error DirAccessPack::list_dir_begin() {
list_dirs.clear();
list_files.clear();
for (RBMap<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) {
list_dirs.push_back(E->key());
}
for (RBSet<String>::Element *E = current->files.front(); E; E = E->next()) {
list_files.push_back(E->get());
}
return OK;
}
String DirAccessPack::get_next() {
if (list_dirs.size()) {
cdir = true;
String d = list_dirs.front()->get();
list_dirs.pop_front();
return d;
} else if (list_files.size()) {
cdir = false;
String f = list_files.front()->get();
list_files.pop_front();
return f;
} else {
return String();
}
}
bool DirAccessPack::current_is_dir() const {
return cdir;
}
bool DirAccessPack::current_is_hidden() const {
return false;
}
void DirAccessPack::list_dir_end() {
list_dirs.clear();
list_files.clear();
}
int DirAccessPack::get_drive_count() {
return 0;
}
String DirAccessPack::get_drive(int p_drive) {
return "";
}
PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
String nd = p_dir.replace("\\", "/");
// Special handling since simplify_path() will forbid it
if (p_dir == "..") {
return current->parent;
}
bool absolute = false;
if (nd.begins_with("res://")) {
nd = nd.replace_first("res://", "");
absolute = true;
}
nd = nd.simplify_path();
if (nd == "") {
nd = ".";
}
if (nd.begins_with("/")) {
nd = nd.replace_first("/", "");
absolute = true;
}
Vector<String> paths = nd.split("/");
PackedData::PackedDir *pd;
if (absolute) {
pd = PackedData::get_singleton()->root;
} else {
pd = current;
}
for (int i = 0; i < paths.size(); i++) {
String p = paths[i];
if (p == ".") {
continue;
} else if (p == "..") {
if (pd->parent) {
pd = pd->parent;
}
} else if (pd->subdirs.has(p)) {
pd = pd->subdirs[p];
} else {
return nullptr;
}
}
return pd;
}
Error DirAccessPack::change_dir(String p_dir) {
PackedData::PackedDir *pd = _find_dir(p_dir);
if (pd) {
current = pd;
return OK;
} else {
return ERR_INVALID_PARAMETER;
}
}
String DirAccessPack::get_current_dir() {
PackedData::PackedDir *pd = current;
String p = current->name;
while (pd->parent) {
pd = pd->parent;
p = pd->name.plus_file(p);
}
return "res://" + p;
}
bool DirAccessPack::file_exists(String p_file) {
p_file = fix_path(p_file);
PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir());
if (!pd) {
return false;
}
return pd->files.has(p_file.get_file());
}
bool DirAccessPack::dir_exists(String p_dir) {
p_dir = fix_path(p_dir);
return _find_dir(p_dir) != nullptr;
}
Error DirAccessPack::make_dir(String p_dir) {
return ERR_UNAVAILABLE;
}
Error DirAccessPack::rename(String p_from, String p_to) {
return ERR_UNAVAILABLE;
}
Error DirAccessPack::remove(String p_name) {
return ERR_UNAVAILABLE;
}
uint64_t DirAccessPack::get_space_left() {
return 0;
}
String DirAccessPack::get_filesystem_type() const {
return "PCK";
}
DirAccessPack::DirAccessPack() {
current = PackedData::get_singleton()->root;
cdir = false;
}
DirAccessPack::~DirAccessPack() {
}

View File

@ -1,264 +0,0 @@
#ifndef FILE_ACCESS_PACK_H
#define FILE_ACCESS_PACK_H
/*************************************************************************/
/* file_access_pack.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/containers/list.h"
#include "core/containers/rb_map.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/string/print_string.h"
#include "core/containers/rb_set.h"
#include "core/containers/hashfuncs.h"
// Pandemonium's packed file magic header ("GDPC" in ASCII).
#define PACK_HEADER_MAGIC 0x43504447
// The current packed file format version number.
#define PACK_FORMAT_VERSION 1
class PackSource;
class PackedData {
friend class FileAccessPack;
friend class DirAccessPack;
friend class PackSource;
public:
struct PackedFile {
String pack;
uint64_t offset; //if offset is ZERO, the file was ERASED
uint64_t size;
uint8_t md5[16];
PackSource *src;
};
private:
struct PackedDir {
PackedDir *parent;
String name;
RBMap<String, PackedDir *> subdirs;
RBSet<String> files;
};
struct PathMD5 {
uint64_t a;
uint64_t b;
bool operator<(const PathMD5 &p_md5) const {
if (p_md5.a == a) {
return b < p_md5.b;
} else {
return a < p_md5.a;
}
}
bool operator==(const PathMD5 &p_md5) const {
return a == p_md5.a && b == p_md5.b;
};
static uint32_t hash(const PathMD5 &p_val) {
uint32_t h = hash_murmur3_one_32(p_val.a);
return hash_fmix32(hash_murmur3_one_32(p_val.b, h));
}
PathMD5() {
a = b = 0;
};
PathMD5(const Vector<uint8_t> p_buf) {
a = *((uint64_t *)&p_buf[0]);
b = *((uint64_t *)&p_buf[8]);
};
};
RBMap<PathMD5, PackedFile> files;
Vector<PackSource *> sources;
PackedDir *root;
static PackedData *singleton;
bool disabled;
void _free_packed_dirs(PackedDir *p_dir);
public:
void add_pack_source(PackSource *p_source);
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files); // for PackSource
void set_disabled(bool p_disabled) { disabled = p_disabled; }
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
_FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
_FORCE_INLINE_ bool has_directory(const String &p_path);
PackedData();
~PackedData();
};
class PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual ~PackSource() {}
};
class PackedSourcePCK : public PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
};
class FileAccessPack : public FileAccess {
PackedData::PackedFile pf;
mutable uint64_t pos;
mutable bool eof;
FileAccess *f;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
public:
virtual void close();
virtual bool is_open() const;
virtual void seek(uint64_t p_position);
virtual void seek_end(int64_t p_position = 0);
virtual uint64_t get_position() const;
virtual uint64_t get_len() const;
virtual bool eof_reached() const;
virtual uint8_t get_8() const;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual void set_endian_swap(bool p_swap);
virtual Error get_error() const;
virtual void flush();
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length);
virtual bool file_exists(const String &p_name);
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessPack();
};
FileAccess *PackedData::try_open_path(const String &p_path) {
PathMD5 pmd5(p_path.md5_buffer());
RBMap<PathMD5, PackedFile>::Element *E = files.find(pmd5);
if (!E) {
return nullptr; //not found
}
if (E->get().offset == 0) {
return nullptr; //was erased
}
return E->get().src->get_file(p_path, &E->get());
}
bool PackedData::has_path(const String &p_path) {
return files.has(PathMD5(p_path.md5_buffer()));
}
bool PackedData::has_directory(const String &p_path) {
DirAccess *da = try_open_directory(p_path);
if (da) {
memdelete(da);
return true;
} else {
return false;
}
}
class DirAccessPack : public DirAccess {
PackedData::PackedDir *current;
List<String> list_dirs;
List<String> list_files;
bool cdir;
PackedData::PackedDir *_find_dir(String p_dir);
public:
virtual Error list_dir_begin();
virtual String get_next();
virtual bool current_is_dir() const;
virtual bool current_is_hidden() const;
virtual void list_dir_end();
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir);
virtual String get_current_dir();
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
virtual Error make_dir(String p_dir);
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
virtual bool is_link(String p_file) { return false; }
virtual String read_link(String p_file) { return p_file; }
virtual Error create_link(String p_source, String p_target) { return FAILED; }
uint64_t get_space_left();
virtual String get_filesystem_type() const;
DirAccessPack();
~DirAccessPack();
};
DirAccess *PackedData::try_open_directory(const String &p_path) {
DirAccess *da = memnew(DirAccessPack());
if (da->change_dir(p_path) != OK) {
memdelete(da);
da = nullptr;
}
return da;
}
#endif // FILE_ACCESS_PACK_H

View File

@ -1,349 +0,0 @@
/*************************************************************************/
/* file_access_zip.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#include "file_access_zip.h"
#include "core/os/file_access.h"
ZipArchive *ZipArchive::instance = nullptr;
extern "C" {
static void *pandemonium_open(void *data, const char *p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return nullptr;
}
FileAccess *f = FileAccess::open(p_fname, FileAccess::READ);
ERR_FAIL_COND_V(!f, nullptr);
return f;
}
static uLong pandemonium_read(void *data, void *fdata, void *buf, uLong size) {
FileAccess *f = (FileAccess *)fdata;
f->get_buffer((uint8_t *)buf, size);
return size;
}
static uLong pandemonium_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
return 0;
}
static long pandemonium_tell(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)stream;
return f->get_position();
}
static long pandemonium_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess *f = (FileAccess *)stream;
uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
break;
default:
break;
}
f->seek(pos);
return 0;
}
static int pandemonium_close(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)stream;
if (f) {
f->close();
memdelete(f);
f = nullptr;
}
return 0;
}
static int pandemonium_testerror(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)stream;
return f->get_error() != OK ? 1 : 0;
}
static voidpf pandemonium_alloc(voidpf opaque, uInt items, uInt size) {
return memalloc(items * size);
}
static void pandemonium_free(voidpf opaque, voidpf address) {
memfree(address);
}
} // extern "C"
void ZipArchive::close_handle(unzFile p_file) const {
ERR_FAIL_COND_MSG(!p_file, "Cannot close a file if none is open.");
unzCloseCurrentFile(p_file);
unzClose(p_file);
}
unzFile ZipArchive::get_file_handle(String p_file) const {
ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, "File '" + p_file + " doesn't exist.");
File file = files[p_file];
zlib_filefunc_def io;
memset(&io, 0, sizeof(io));
io.opaque = nullptr;
io.zopen_file = pandemonium_open;
io.zread_file = pandemonium_read;
io.zwrite_file = pandemonium_write;
io.ztell_file = pandemonium_tell;
io.zseek_file = pandemonium_seek;
io.zclose_file = pandemonium_close;
io.zerror_file = pandemonium_testerror;
io.alloc_mem = pandemonium_alloc;
io.free_mem = pandemonium_free;
unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io);
ERR_FAIL_COND_V_MSG(!pkg, nullptr, "Cannot open file '" + packages[file.package].filename + "'.");
int unz_err = unzGoToFilePos(pkg, &file.file_pos);
if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) {
unzClose(pkg);
ERR_FAIL_V(nullptr);
}
return pkg;
}
bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset = 0) {
//printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz"));
// load with offset feature only supported for PCK files
ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives.");
if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0) {
return false;
}
zlib_filefunc_def io;
memset(&io, 0, sizeof(io));
io.opaque = nullptr;
io.zopen_file = pandemonium_open;
io.zread_file = pandemonium_read;
io.zwrite_file = pandemonium_write;
io.ztell_file = pandemonium_tell;
io.zseek_file = pandemonium_seek;
io.zclose_file = pandemonium_close;
io.zerror_file = pandemonium_testerror;
unzFile zfile = unzOpen2(p_path.utf8().get_data(), &io);
ERR_FAIL_COND_V(!zfile, false);
unz_global_info64 gi;
int err = unzGetGlobalInfo64(zfile, &gi);
ERR_FAIL_COND_V(err != UNZ_OK, false);
Package pkg;
pkg.filename = p_path;
pkg.zfile = zfile;
packages.push_back(pkg);
int pkg_num = packages.size() - 1;
for (uint64_t i = 0; i < gi.number_entry; i++) {
char filename_inzip[256];
unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(zfile, &file_info, filename_inzip, sizeof(filename_inzip), nullptr, 0, nullptr, 0);
ERR_CONTINUE(err != UNZ_OK);
File f;
f.package = pkg_num;
unzGetFilePos(zfile, &f.file_pos);
String fname = String("res://") + String::utf8(filename_inzip);
files[fname] = f;
uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files);
//printf("packed data add path %s, %s\n", p_name.utf8().get_data(), fname.utf8().get_data());
if ((i + 1) < gi.number_entry) {
unzGoToNextFile(zfile);
}
}
return true;
}
bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name);
}
FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessZip(p_path, *p_file));
}
ZipArchive *ZipArchive::get_singleton() {
if (instance == nullptr) {
instance = memnew(ZipArchive);
}
return instance;
}
ZipArchive::ZipArchive() {
instance = this;
//fa_create_func = FileAccess::get_create_func();
}
ZipArchive::~ZipArchive() {
for (int i = 0; i < packages.size(); i++) {
unzClose(packages[i].zfile);
}
packages.clear();
}
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
ZipArchive *arch = ZipArchive::get_singleton();
ERR_FAIL_COND_V(!arch, FAILED);
zfile = arch->get_file_handle(p_path);
ERR_FAIL_COND_V(!zfile, FAILED);
int err = unzGetCurrentFileInfo64(zfile, &file_info, nullptr, 0, nullptr, 0, nullptr, 0);
ERR_FAIL_COND_V(err != UNZ_OK, FAILED);
return OK;
}
void FileAccessZip::close() {
if (!zfile) {
return;
}
ZipArchive *arch = ZipArchive::get_singleton();
ERR_FAIL_COND(!arch);
arch->close_handle(zfile);
zfile = nullptr;
}
bool FileAccessZip::is_open() const {
return zfile != nullptr;
}
void FileAccessZip::seek(uint64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, p_position);
}
void FileAccessZip::seek_end(int64_t p_position) {
ERR_FAIL_COND(!zfile);
unzSeekCurrentFile(zfile, get_len() + p_position);
}
uint64_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
}
uint64_t FileAccessZip::get_len() const {
ERR_FAIL_COND_V(!zfile, 0);
return file_info.uncompressed_size;
}
bool FileAccessZip::eof_reached() const {
ERR_FAIL_COND_V(!zfile, true);
return at_eof;
}
uint8_t FileAccessZip::get_8() const {
uint8_t ret = 0;
get_buffer(&ret, 1);
return ret;
}
uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V(!zfile, -1);
at_eof = unzeof(zfile);
if (at_eof) {
return 0;
}
int64_t read = unzReadCurrentFile(zfile, p_dst, p_length);
ERR_FAIL_COND_V(read < 0, read);
if ((uint64_t)read < p_length) {
at_eof = true;
}
return read;
}
Error FileAccessZip::get_error() const {
if (!zfile) {
return ERR_UNCONFIGURED;
}
if (eof_reached()) {
return ERR_FILE_EOF;
}
return OK;
}
void FileAccessZip::flush() {
ERR_FAIL();
}
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
}
bool FileAccessZip::file_exists(const String &p_name) {
return false;
}
FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) :
zfile(nullptr) {
_open(p_path, FileAccess::READ);
}
FileAccessZip::~FileAccessZip() {
close();
}
#endif

View File

@ -1,120 +0,0 @@
#ifndef FILE_ACCESS_ZIP_H
#define FILE_ACCESS_ZIP_H
/*************************************************************************/
/* file_access_zip.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef MINIZIP_ENABLED
#include "core/io/file_access_pack.h"
#include "core/containers/rb_map.h"
#include "core/thirdparty/minizip/unzip.h"
#include <stdlib.h>
class ZipArchive : public PackSource {
public:
struct File {
int package;
unz_file_pos file_pos;
File() {
package = -1;
};
};
private:
struct Package {
String filename;
unzFile zfile;
};
Vector<Package> packages;
RBMap<String, File> files;
static ZipArchive *instance;
FileAccess::CreateFunc fa_create_func;
public:
void close_handle(unzFile p_file) const;
unzFile get_file_handle(String p_file) const;
Error add_package(String p_name);
bool file_exists(String p_name) const;
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file);
static ZipArchive *get_singleton();
ZipArchive();
~ZipArchive();
};
class FileAccessZip : public FileAccess {
unzFile zfile = nullptr;
unz_file_info64 file_info;
mutable bool at_eof;
public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
virtual uint64_t get_position() const; ///< get position in the file
virtual uint64_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
virtual uint8_t get_8() const; ///< get a byte
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
virtual Error get_error() const; ///< get last error
virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip();
};
#endif // MINIZIP_ENABLED
#endif // FILE_ACCESS_ZIP_H

View File

@ -1,187 +0,0 @@
/*************************************************************************/
/* pck_packer.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "pck_packer.h"
#include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION
#include "core/os/file_access.h"
#include "core/version.h"
static uint64_t _align(uint64_t p_n, int p_alignment) {
if (p_alignment == 0) {
return p_n;
}
uint64_t rest = p_n % p_alignment;
if (rest == 0) {
return p_n;
} else {
return p_n + (p_alignment - rest);
}
};
static void _pad(FileAccess *p_file, int p_bytes) {
for (int i = 0; i < p_bytes; i++) {
p_file->store_8(0);
};
};
void PCKPacker::_bind_methods() {
ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start, DEFVAL(0));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file);
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
};
Error PCKPacker::pck_start(const String &p_file, int p_alignment) {
if (file != nullptr) {
memdelete(file);
}
file = FileAccess::open(p_file, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(!file, ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
alignment = p_alignment;
file->store_32(PACK_HEADER_MAGIC);
file->store_32(PACK_FORMAT_VERSION);
file->store_32(VERSION_MAJOR);
file->store_32(VERSION_MINOR);
file->store_32(VERSION_PATCH);
for (int i = 0; i < 16; i++) {
file->store_32(0); // reserved
};
files.clear();
return OK;
};
Error PCKPacker::add_file(const String &p_file, const String &p_src) {
ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
if (!f) {
return ERR_FILE_CANT_OPEN;
};
File pf;
pf.path = p_file;
pf.src_path = p_src;
pf.size = f->get_len();
pf.offset_offset = 0;
files.push_back(pf);
f->close();
memdelete(f);
return OK;
};
Error PCKPacker::flush(bool p_verbose) {
ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
// write the index
file->store_32(files.size());
for (int i = 0; i < files.size(); i++) {
file->store_pascal_string(files[i].path);
files.write[i].offset_offset = file->get_position();
file->store_64(0); // offset
file->store_64(files[i].size); // size
// # empty md5
file->store_32(0);
file->store_32(0);
file->store_32(0);
file->store_32(0);
};
uint64_t ofs = file->get_position();
ofs = _align(ofs, alignment);
_pad(file, ofs - file->get_position());
const uint32_t buf_max = 65536;
uint8_t *buf = memnew_arr(uint8_t, buf_max);
int count = 0;
for (int i = 0; i < files.size(); i++) {
FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ);
uint64_t to_write = files[i].size;
while (to_write > 0) {
uint64_t read = src->get_buffer(buf, MIN(to_write, buf_max));
file->store_buffer(buf, read);
to_write -= read;
};
uint64_t pos = file->get_position();
file->seek(files[i].offset_offset); // go back to store the file's offset
file->store_64(ofs);
file->seek(pos);
ofs = _align(ofs + files[i].size, alignment);
_pad(file, ofs - pos);
src->close();
memdelete(src);
count += 1;
const int file_num = files.size();
if (p_verbose && (file_num > 0)) {
print_line(vformat("[%d/%d - %d%%] PCKPacker flush: %s -> %s", count, file_num, float(count) / file_num * 100, files[i].src_path, files[i].path));
}
}
if (p_verbose) {
printf("\n");
}
file->close();
memdelete(file);
file = nullptr;
memdelete_arr(buf);
return OK;
};
PCKPacker::PCKPacker() {
file = nullptr;
};
PCKPacker::~PCKPacker() {
if (file != nullptr) {
memdelete(file);
};
file = nullptr;
};

View File

@ -1,62 +0,0 @@
#ifndef PCK_PACKER_H
#define PCK_PACKER_H
/*************************************************************************/
/* pck_packer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/object/reference.h"
class FileAccess;
class PCKPacker : public Reference {
GDCLASS(PCKPacker, Reference);
FileAccess *file;
int alignment;
static void _bind_methods();
struct File {
String path;
String src_path;
uint64_t size;
uint64_t offset_offset;
};
Vector<File> files;
public:
Error pck_start(const String &p_file, int p_alignment = 0);
Error add_file(const String &p_file, const String &p_src);
Error flush(bool p_verbose = false);
PCKPacker();
~PCKPacker();
};
#endif // PCK_PACKER_H

View File

@ -1,125 +0,0 @@
/*************************************************************************/
/* zip_io.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "zip_io.h"
void *zipio_open(void *data, const char *p_fname, int mode) {
FileAccess *&f = *(FileAccess **)data;
String fname;
fname.parse_utf8(p_fname);
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
f = FileAccess::open(fname, FileAccess::WRITE);
} else {
f = FileAccess::open(fname, FileAccess::READ);
}
if (!f) {
return nullptr;
}
return data;
}
uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
FileAccess *f = *(FileAccess **)data;
return f->get_buffer((uint8_t *)buf, size);
}
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
FileAccess *f = *(FileAccess **)opaque;
f->store_buffer((uint8_t *)buf, size);
return size;
}
long zipio_tell(voidpf opaque, voidpf stream) {
FileAccess *f = *(FileAccess **)opaque;
return f->get_position();
}
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
FileAccess *f = *(FileAccess **)opaque;
uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
break;
default:
break;
};
f->seek(pos);
return 0;
}
int zipio_close(voidpf opaque, voidpf stream) {
FileAccess *&f = *(FileAccess **)opaque;
if (f) {
f->close();
memdelete(f);
f = nullptr;
}
return 0;
}
int zipio_testerror(voidpf opaque, voidpf stream) {
FileAccess *f = *(FileAccess **)opaque;
return (f && f->get_error() != OK) ? 1 : 0;
}
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
voidpf ptr = memalloc(items * size);
memset(ptr, 0, items * size);
return ptr;
}
void zipio_free(voidpf opaque, voidpf address) {
memfree(address);
}
zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
zlib_filefunc_def io;
io.opaque = p_file;
io.zopen_file = zipio_open;
io.zread_file = zipio_read;
io.zwrite_file = zipio_write;
io.ztell_file = zipio_tell;
io.zseek_file = zipio_seek;
io.zclose_file = zipio_close;
io.zerror_file = zipio_testerror;
io.alloc_mem = zipio_alloc;
io.free_mem = zipio_free;
return io;
}

View File

@ -1,57 +0,0 @@
#ifndef ZIP_IO_H
#define ZIP_IO_H
/*************************************************************************/
/* zip_io.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/os/file_access.h"
// Not directly used in this header, but assumed available in downstream users
// like platform/*/export/export.cpp. Could be fixed, but probably better to have
// thirdparty includes in as little headers as possible.
#include "core/thirdparty/minizip/unzip.h"
#include "core/thirdparty/minizip/zip.h"
void *zipio_open(void *data, const char *p_fname, int mode);
uLong zipio_read(void *data, void *fdata, void *buf, uLong size);
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
long zipio_tell(voidpf opaque, voidpf stream);
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin);
int zipio_close(voidpf opaque, voidpf stream);
int zipio_testerror(voidpf opaque, voidpf stream);
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
void zipio_free(voidpf opaque, voidpf address);
zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file);
#endif // ZIP_IO_H

View File

@ -31,7 +31,6 @@
#include "file_access.h"
#include "core/crypto/crypto_core.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/config/project_settings.h"
@ -51,10 +50,6 @@ FileAccess *FileAccess::create(AccessType p_access) {
}
bool FileAccess::exists(const String &p_name) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
return true;
}
FileAccess *f = open(p_name, READ);
if (!f) {
return false;
@ -86,20 +81,7 @@ Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
};
FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
//try packed data first
FileAccess *ret = nullptr;
if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
ret = PackedData::get_singleton()->try_open_path(p_path);
if (ret) {
if (r_error) {
*r_error = OK;
}
return ret;
}
}
ret = create_for_path(p_path);
FileAccess *ret = create_for_path(p_path);
Error err = ret->_open(p_path, p_mode_flags);
if (r_error) {
@ -460,10 +442,6 @@ void FileAccess::store_double(double p_dest) {
};
uint64_t FileAccess::get_modified_time(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
FileAccess *fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
@ -473,10 +451,6 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
}
uint32_t FileAccess::get_unix_permissions(const String &p_file) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
FileAccess *fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
@ -486,10 +460,6 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
}
Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return ERR_UNAVAILABLE;
}
FileAccess *fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");

View File

@ -51,7 +51,6 @@
#include "core/io/packet_peer.h"
#include "core/io/packet_peer_dtls.h"
#include "core/io/packet_peer_udp.h"
#include "core/io/pck_packer.h"
#include "core/io/resource_format_binary.h"
#include "core/io/resource_importer.h"
#include "core/io/stream_peer_ssl.h"
@ -214,8 +213,6 @@ void register_core_types() {
ClassDB::register_class<ConfigFile>();
ClassDB::register_class<PCKPacker>();
ClassDB::register_class<PackedDataContainer>();
ClassDB::register_virtual_class<PackedDataContainerRef>();
ClassDB::register_class<AStar>();

View File

@ -34,8 +34,6 @@
#include "core/crypto/crypto.h"
#include "core/input/input_map.h"
#include "core/io/file_access_network.h"
#include "core/io/file_access_pack.h"
#include "core/io/file_access_zip.h"
#include "core/io/image_loader.h"
#include "core/io/ip.h"
#include "core/io/resource_loader.h"
@ -90,11 +88,7 @@ static ProjectSettings *globals = nullptr;
static InputMap *input_map = nullptr;
static TranslationServer *translation_server = nullptr;
static Performance *performance = nullptr;
static PackedData *packed_data = nullptr;
static Time *time_singleton = nullptr;
#ifdef MINIZIP_ENABLED
static ZipArchive *zip_packed_data = nullptr;
#endif
static FileAccessNetworkClient *file_access_network_client = nullptr;
static ScriptDebugger *script_debugger = nullptr;
static MessageQueue *message_queue = nullptr;
@ -423,23 +417,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
bool found_project = false;
#endif
packed_data = PackedData::get_singleton();
if (!packed_data) {
packed_data = memnew(PackedData);
}
#ifdef MINIZIP_ENABLED
//XXX: always get_singleton() == 0x0
zip_packed_data = ZipArchive::get_singleton();
//TODO: remove this temporary fix
if (!zip_packed_data) {
zip_packed_data = memnew(ZipArchive);
}
packed_data->add_pack_source(zip_packed_data);
#endif
// Default exit code, can be modified for certain errors.
Error exit_code = ERR_INVALID_PARAMETER;
@ -969,13 +946,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
#ifdef TOOLS_ENABLED
if (editor) {
packed_data->set_disabled(true);
}
#endif
#ifdef TOOLS_ENABLED
if (editor) {
Engine::get_singleton()->set_editor_hint(true);
@ -1283,9 +1253,6 @@ error:
if (script_debugger) {
memdelete(script_debugger);
}
if (packed_data) {
memdelete(packed_data);
}
if (file_access_network_client) {
memdelete(file_access_network_client);
}
@ -2380,9 +2347,6 @@ void Main::cleanup(bool p_force) {
OS::get_singleton()->finalize();
finalize_physics();
if (packed_data) {
memdelete(packed_data);
}
if (file_access_network_client) {
memdelete(file_access_network_client);
}