diff options
Diffstat (limited to 'core/io/file_access_pack.cpp')
-rw-r--r-- | core/io/file_access_pack.cpp | 82 |
1 files changed, 62 insertions, 20 deletions
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 1340382eaa..8b6b445cea 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -48,7 +48,7 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, uint64_t } 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, bool p_encrypted) { - String simplified_path = p_path.simplify_path(); + String simplified_path = p_path.simplify_path().trim_prefix("res://"); PathMD5 pmd5(simplified_path.md5_buffer()); bool exists = files.has(pmd5); @@ -68,13 +68,11 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64 } if (!exists) { - //search for dir - String p = simplified_path.replace_first("res://", ""); + // Search for directory. PackedDir *cd = root; - if (p.contains("/")) { //in a subdir - - Vector<String> ds = p.get_base_dir().split("/"); + if (simplified_path.contains("/")) { // In a subdirectory. + Vector<String> ds = simplified_path.get_base_dir().split("/"); for (int j = 0; j < ds.size(); j++) { if (!cd->subdirs.has(ds[j])) { @@ -89,13 +87,40 @@ void PackedData::add_path(const String &p_pkg_path, const String &p_path, uint64 } } String filename = simplified_path.get_file(); - // Don't add as a file if the path points to a directory + // Don't add as a file if the path points to a directory. if (!filename.is_empty()) { cd->files.insert(filename); } } } +void PackedData::remove_path(const String &p_path) { + String simplified_path = p_path.simplify_path().trim_prefix("res://"); + PathMD5 pmd5(simplified_path.md5_buffer()); + if (!files.has(pmd5)) { + return; + } + + // Search for directory. + PackedDir *cd = root; + + if (simplified_path.contains("/")) { // In a subdirectory. + Vector<String> ds = simplified_path.get_base_dir().split("/"); + + for (int j = 0; j < ds.size(); j++) { + if (!cd->subdirs.has(ds[j])) { + return; // Subdirectory does not exist, do not bother creating. + } else { + cd = cd->subdirs[ds[j]]; + } + } + } + + cd->files.erase(simplified_path.get_file()); + + files.erase(pmd5); +} + void PackedData::add_pack_source(PackSource *p_source) { if (p_source != nullptr) { sources.push_back(p_source); @@ -103,15 +128,32 @@ void PackedData::add_pack_source(PackSource *p_source) { } uint8_t *PackedData::get_file_hash(const String &p_path) { - PathMD5 pmd5(p_path.md5_buffer()); + String simplified_path = p_path.simplify_path().trim_prefix("res://"); + PathMD5 pmd5(simplified_path.md5_buffer()); HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5); - if (!E || E->value.offset == 0) { + if (!E) { return nullptr; } return E->value.md5; } +HashSet<String> PackedData::get_file_paths() const { + HashSet<String> file_paths; + _get_file_paths(root, root->name, file_paths); + return file_paths; +} + +void PackedData::_get_file_paths(PackedDir *p_dir, const String &p_parent_dir, HashSet<String> &r_paths) const { + for (const String &E : p_dir->files) { + r_paths.insert(p_parent_dir.path_join(E)); + } + + for (const KeyValue<String, PackedDir *> &E : p_dir->subdirs) { + _get_file_paths(E.value, p_parent_dir.path_join(E.key), r_paths); + } +} + void PackedData::clear() { files.clear(); _free_packed_dirs(root); @@ -223,8 +265,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint32_t ver_minor = f->get_32(); f->get_32(); // patch number, not used for validation. - ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + "."); - ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "."); + ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, vformat("Pack version unsupported: %d.", version)); + ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, vformat("Pack created with a newer version of the engine: %d.%d.", ver_major, ver_minor)); uint32_t pack_flags = f->get_32(); uint64_t file_base = f->get_64(); @@ -269,13 +311,17 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, String path; path.parse_utf8(cs.ptr()); - uint64_t ofs = file_base + f->get_64(); + uint64_t ofs = f->get_64(); uint64_t size = f->get_64(); uint8_t md5[16]; f->get_buffer(md5, 16); uint32_t flags = f->get_32(); - PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED)); + if (flags & PACK_FILE_REMOVAL) { // The file was removed. + PackedData::get_singleton()->remove_path(path); + } else { + PackedData::get_singleton()->add_path(p_path, path, file_base + ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED)); + } } return true; @@ -386,7 +432,7 @@ void FileAccessPack::close() { 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.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(f.is_null(), vformat("Can't open pack-referenced file '%s'.", String(pf.pack))); f->seek(pf.offset); off = pf.offset; @@ -394,7 +440,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil if (pf.encrypted) { Ref<FileAccessEncrypted> fae; fae.instantiate(); - ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(fae.is_null(), vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack))); Vector<uint8_t> key; key.resize(32); @@ -403,7 +449,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil } Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false); - ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + ERR_FAIL_COND_MSG(err, vformat("Can't open encrypted pack-referenced file '%s'.", String(pf.pack))); f = fae; off = 0; } @@ -544,8 +590,6 @@ String DirAccessPack::get_current_dir(bool p_include_drive) const { } 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; @@ -554,8 +598,6 @@ bool DirAccessPack::file_exists(String p_file) { } bool DirAccessPack::dir_exists(String p_dir) { - p_dir = fix_path(p_dir); - return _find_dir(p_dir) != nullptr; } |