Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Universal plugins [wip] #35432

Closed
wants to merge 15 commits into from
5 changes: 5 additions & 0 deletions core/bind/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,11 @@ String _Directory::get_current_dir() {
ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use.");
return d->get_current_dir();
}
String _Directory::get_current_dir_without_drive() {

ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use.");
return d->get_current_dir_without_drive();
}
Error _Directory::make_dir(String p_dir) {

ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use.");
Expand Down
1 change: 1 addition & 0 deletions core/bind/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ class _Directory : public Reference {

Error change_dir(String p_dir); // Can be relative or absolute, return false on success.
String get_current_dir(); // Return current dir location.
String get_current_dir_without_drive();

Error make_dir(String p_dir);
Error make_dir_recursive(String p_dir);
Expand Down
2 changes: 1 addition & 1 deletion core/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1876,7 +1876,7 @@ Image::AlphaMode Image::detect_alpha() const {

Error Image::load(const String &p_path) {
#ifdef DEBUG_ENABLED
if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) {
if (p_path.is_resource_path() && ResourceLoader::exists(p_path)) {
WARN_PRINTS("Loaded resource as image file, this will not work on export: '" + p_path + "'. Instead, import the image file as an Image resource and load it normally as a resource.");
}
#endif
Expand Down
21 changes: 18 additions & 3 deletions core/io/config_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,20 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
VariantParser::StreamFile stream;
stream.f = f;

Error err = _parse(p_path, &stream);
memdelete(f);
return err;
}

Error ConfigFile::parse(const String &p_data) {

VariantParser::StreamString stream;
stream.s = p_data;
return _parse("<string>", &stream);
}

Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) {

String assign;
Variant value;
VariantParser::Tag next_tag;
Expand All @@ -270,13 +284,11 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
next_tag.fields.clear();
next_tag.name = String();

Error err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true);
Error err = VariantParser::parse_tag_assign_eof(p_stream, lines, error_text, next_tag, assign, value, NULL, true);
if (err == ERR_FILE_EOF) {
memdelete(f);
return OK;
} else if (err != OK) {
ERR_PRINTS("ConfgFile::load - " + p_path + ":" + itos(lines) + " error: " + error_text + ".");
memdelete(f);
return err;
}

Expand All @@ -286,6 +298,8 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
section = next_tag.name;
}
}

return OK;
}

void ConfigFile::_bind_methods() {
Expand All @@ -303,6 +317,7 @@ void ConfigFile::_bind_methods() {
ClassDB::bind_method(D_METHOD("erase_section_key", "section", "key"), &ConfigFile::erase_section_key);

ClassDB::bind_method(D_METHOD("load", "path"), &ConfigFile::load);
ClassDB::bind_method(D_METHOD("parse", "data"), &ConfigFile::parse);
ClassDB::bind_method(D_METHOD("save", "path"), &ConfigFile::save);

ClassDB::bind_method(D_METHOD("load_encrypted", "path", "key"), &ConfigFile::load_encrypted);
Expand Down
4 changes: 4 additions & 0 deletions core/io/config_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "core/ordered_hash_map.h"
#include "core/os/file_access.h"
#include "core/reference.h"
#include "core/variant_parser.h"

class ConfigFile : public Reference {

Expand All @@ -46,6 +47,8 @@ class ConfigFile : public Reference {
Error _internal_load(const String &p_path, FileAccess *f);
Error _internal_save(FileAccess *file);

Error _parse(const String &p_path, VariantParser::Stream *p_stream);

protected:
static void _bind_methods();

Expand All @@ -64,6 +67,7 @@ class ConfigFile : public Reference {

Error save(const String &p_path);
Error load(const String &p_path);
Error parse(const String &p_data);

Error load_encrypted(const String &p_path, const Vector<uint8_t> &p_key);
Error load_encrypted_pass(const String &p_path, const String &p_pass);
Expand Down
137 changes: 99 additions & 38 deletions core/io/file_access_pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files) {

for (int i = 0; i < sources.size(); i++) {

if (sources[i]->try_open_pack(p_path, p_replace_files)) {
if (sources[i]->try_open_pack(p_path, p_replace_files, this)) {

return OK;
};
Expand All @@ -47,6 +47,38 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files) {
return ERR_FILE_UNRECOGNIZED;
};

#ifdef TOOLS_ENABLED
// This works only for "disjoint" packs. That means that if a pack A containing a path P is mounted
// and then a pack B containing the same path P, after unmounting B, the path P is removed altogether
// from the packed file system. There's no bookkeeping of multiple packs containing the same path.
// For the current only use case (plugins in PCK), that's enough.
void PackedData::remove_pack(const String &p_path) {

Map<PathMD5, PackedFile>::Element *E = files.front();
while (E) {
Map<PathMD5, PackedFile>::Element *next = E->next();
if (E->get().pack == p_path) {
const PackedFile &pf = E->get();
PackedDir *pd = pf.dir;
pd->files.erase(pf.name);

do {
if (pd->files.size() != 0 || pd->subdirs.size() != 0) {
break;
}
PackedDir *parent = pd->parent;
pd->parent->subdirs.erase(pd->name);
memdelete(pd);
pd = parent;
} while (pd != root);

files.erase(E);
}
E = next;
}
}
#endif

void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) {

PathMD5 pmd5(path.md5_buffer());
Expand All @@ -65,9 +97,14 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
if (!exists || p_replace_files)
files[pmd5] = pf;

String filename = path.get_file();
#ifdef TOOLS_ENABLED
pf.name = filename;
#endif

if (!exists) {
//search for dir
String p = path.replace_first("res://", "");
// Keep the file system as a subdirectory of the root
String p = path.replace_first("://", "/");
PackedDir *cd = root;

if (p.find("/") != -1) { //in a subdir
Expand All @@ -87,8 +124,10 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o
cd = cd->subdirs[ds[j]];
}
}
#ifdef TOOLS_ENABLED
pf.dir = cd;
#endif
}
String filename = path.get_file();
// Don't add as a file if the path points to a directory
if (!filename.empty()) {
cd->files.insert(filename);
Expand All @@ -107,7 +146,9 @@ PackedData *PackedData::singleton = NULL;

PackedData::PackedData() {

singleton = this;
if (!singleton) { // So only the main PackedData sets itself
singleton = this;
}
root = memnew(PackedDir);
root->parent = NULL;
disabled = false;
Expand All @@ -132,7 +173,7 @@ PackedData::~PackedData() {

//////////////////////////////////////////////////////////////////

bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) {
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, PackedData *p_packed_data) {

FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f)
Expand Down Expand Up @@ -203,7 +244,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files)
uint64_t size = f->get_64();
uint8_t md5[16];
f->get_buffer(md5, 16);
PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this, p_replace_files);
p_packed_data->add_path(p_path, path, ofs, size, md5, this, p_replace_files);
};

f->close();
Expand All @@ -218,6 +259,11 @@ FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFi

//////////////////////////////////////////////////////////////////

String FileAccessPack::_get_resource_path() const {

return "/";
}

Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {

ERR_FAIL_V(ERR_UNAVAILABLE);
Expand Down Expand Up @@ -346,6 +392,11 @@ FileAccessPack::~FileAccessPack() {
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////

String DirAccessPack::_get_resource_path() const {

return "/";
}

Error DirAccessPack::list_dir_begin() {

list_dirs.clear();
Expand Down Expand Up @@ -403,25 +454,20 @@ String DirAccessPack::get_drive(int p_drive) {
return "";
}

Error DirAccessPack::change_dir(String p_dir) {
PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {

if (p_dir == "") p_dir = ".";

String nd = p_dir.replace("\\", "/");
bool absolute = false;
if (nd.begins_with("res://")) {
nd = nd.replace_first("res://", "");
if (p_dir.begins_with("/")) {
p_dir = p_dir.replace_first("/", "res://");
absolute = true;
}

nd = nd.simplify_path();

if (nd == "") nd = ".";

if (nd.begins_with("/")) {
nd = nd.replace_first("/", "");
} else if (p_dir.find("://") != -1) {
p_dir = p_dir.replace_first("://", "/");
absolute = true;
}

Vector<String> paths = nd.split("/");
Vector<String> paths = p_dir.split("/");

PackedData::PackedDir *pd;

Expand All @@ -435,23 +481,35 @@ Error DirAccessPack::change_dir(String p_dir) {
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 NULL;
}
}

return pd;
}

Error DirAccessPack::change_dir(String p_dir) {

if (p_dir == "..") {
if (current->parent) {
current = current->parent;
return OK;
} else {
return ERR_INVALID_PARAMETER;
}
}

current = pd;

return OK;
String nd = fix_path(p_dir).simplify_path();
PackedData::PackedDir *pd = _find_dir(nd);
if (pd) {
current = pd;
return OK;
} else {
return ERR_INVALID_PARAMETER;
}
}

String DirAccessPack::get_current_dir() {
Expand All @@ -464,21 +522,24 @@ String DirAccessPack::get_current_dir() {
p = pd->name.plus_file(p);
}

return "res://" + p;
p = p.replace_first("/", "://");

return unfix_path(p);
}

bool DirAccessPack::file_exists(String p_file) {

p_file = fix_path(p_file);

return current->files.has(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 current->subdirs.has(p_dir);
PackedData::PackedDir *pd = _find_dir(p_dir);
return pd != NULL;
}

Error DirAccessPack::make_dir(String p_dir) {
Expand All @@ -504,9 +565,9 @@ String DirAccessPack::get_filesystem_type() const {
return "PCK";
}

DirAccessPack::DirAccessPack() {
DirAccessPack::DirAccessPack(PackedData *p_packed_data) {

current = PackedData::get_singleton()->root;
current = p_packed_data->root;
cdir = false;
}

Expand Down
Loading