diff options
Diffstat (limited to 'core/io')
-rw-r--r-- | core/io/http_client.cpp | 132 | ||||
-rw-r--r-- | core/io/http_client.h | 27 | ||||
-rw-r--r-- | core/io/packet_peer.cpp | 10 | ||||
-rw-r--r-- | core/io/packet_peer.h | 12 | ||||
-rw-r--r-- | core/io/resource_format_binary.cpp | 68 | ||||
-rw-r--r-- | core/io/resource_format_binary.h | 7 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 112 | ||||
-rw-r--r-- | core/io/resource_loader.h | 4 |
8 files changed, 242 insertions, 130 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 9d89baafb1..e457a4ac1e 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -30,27 +30,53 @@ #include "http_client.h" #include "io/stream_peer_ssl.h" +const char *HTTPClient::_methods[METHOD_MAX] = { + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "OPTIONS", + "TRACE", + "CONNECT", + "PATCH" +}; + #ifndef JAVASCRIPT_ENABLED Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) { close(); + conn_port = p_port; conn_host = p_host; - if (conn_host.begins_with("http://")) { + ssl = p_ssl; + ssl_verify_host = p_verify_host; + + String host_lower = conn_host.to_lower(); + if (host_lower.begins_with("http://")) { - conn_host = conn_host.replace_first("http://", ""); - } else if (conn_host.begins_with("https://")) { - //use https - conn_host = conn_host.replace_first("https://", ""); + conn_host = conn_host.substr(7, conn_host.length() - 7); + } else if (host_lower.begins_with("https://")) { + + ssl = true; + conn_host = conn_host.substr(8, conn_host.length() - 8); + } + + ERR_FAIL_COND_V(conn_host.length() < HOST_MIN_LEN, ERR_INVALID_PARAMETER); + + if (conn_port < 0) { + if (ssl) { + conn_port = PORT_HTTPS; + } else { + conn_port = PORT_HTTP; + } } - ssl = p_ssl; - ssl_verify_host = p_verify_host; connection = tcp_connection; if (conn_host.is_valid_ip_address()) { - //is ip + // Host contains valid IP Error err = tcp_connection->connect_to_host(IP_Address(conn_host), p_port); if (err) { status = STATUS_CANT_CONNECT; @@ -59,7 +85,7 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, status = STATUS_CONNECTING; } else { - //is hostname + // Host contains hostname and needs to be resolved to IP resolving = IP::get_singleton()->resolve_hostname_queue_item(conn_host); status = STATUS_RESOLVING; } @@ -82,24 +108,13 @@ Ref<StreamPeer> HTTPClient::get_connection() const { Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); - static const char *_methods[METHOD_MAX] = { - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - "OPTIONS", - "TRACE", - "CONNECT", - "PATCH" - }; - String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n"; - if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) { - // don't append the standard ports + if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { + // Don't append the standard ports request += "Host: " + conn_host + "\r\n"; } else { request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; @@ -113,17 +128,20 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector } if (add_clen) { request += "Content-Length: " + itos(p_body.size()) + "\r\n"; - //should it add utf8 encoding? not sure + // Should it add utf8 encoding? } request += "\r\n"; CharString cs = request.utf8(); PoolVector<uint8_t> data; - - //Maybe this goes faster somehow? - for (int i = 0; i < cs.length(); i++) { - data.append(cs[i]); + data.resize(cs.length()); + { + PoolVector<uint8_t>::Write data_write = data.write(); + for (int i = 0; i < cs.length(); i++) { + data_write[i] = cs[i]; + } } + data.append_array(p_body); PoolVector<uint8_t>::Read r = data.read(); @@ -143,24 +161,13 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); - static const char *_methods[METHOD_MAX] = { - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - "OPTIONS", - "TRACE", - "CONNECT", - "PATCH" - }; - String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n"; - if ((ssl && conn_port == 443) || (!ssl && conn_port == 80)) { - // don't append the standard ports + if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { + // Don't append the standard ports request += "Host: " + conn_host + "\r\n"; } else { request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; @@ -174,7 +181,7 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str } if (add_clen) { request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n"; - //should it add utf8 encoding? not sure + // Should it add utf8 encoding? } request += "\r\n"; request += p_body; @@ -253,7 +260,7 @@ Error HTTPClient::poll() { IP::ResolverStatus rstatus = IP::get_singleton()->get_resolve_item_status(resolving); switch (rstatus) { case IP::RESOLVER_STATUS_WAITING: - return OK; //still resolving + return OK; // Still resolving case IP::RESOLVER_STATUS_DONE: { @@ -285,7 +292,7 @@ Error HTTPClient::poll() { switch (s) { case StreamPeerTCP::STATUS_CONNECTING: { - return OK; //do none + return OK; } break; case StreamPeerTCP::STATUS_CONNECTED: { if (ssl) { @@ -296,7 +303,6 @@ Error HTTPClient::poll() { status = STATUS_SSL_HANDSHAKE_ERROR; return ERR_CANT_CONNECT; } - //print_line("SSL! TURNED ON!"); connection = ssl; } status = STATUS_CONNECTED; @@ -312,7 +318,7 @@ Error HTTPClient::poll() { } } break; case STATUS_CONNECTED: { - //request something please + // Connection established, requests can now be made return OK; } break; case STATUS_REQUESTING: { @@ -328,7 +334,7 @@ Error HTTPClient::poll() { } if (rec == 0) - return OK; //keep trying! + return OK; // Still requesting, keep trying! response_str.push_back(byte); int rs = response_str.size(); @@ -336,11 +342,10 @@ Error HTTPClient::poll() { (rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') || (rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) { - //end of response, parse. + // End of response, parse. response_str.push_back(0); String response; response.parse_utf8((const char *)response_str.ptr()); - //print_line("END OF RESPONSE? :\n"+response+"\n------"); Vector<String> responses = response.split("\n"); body_size = 0; chunked = false; @@ -363,7 +368,6 @@ Error HTTPClient::poll() { if (s.begins_with("transfer-encoding:")) { String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges(); - //print_line("TRANSFER ENCODING: "+encoding); if (encoding == "chunked") { chunked = true; } @@ -381,14 +385,14 @@ Error HTTPClient::poll() { if (body_size == 0 && !chunked) { - status = STATUS_CONNECTED; //ask for something again? + status = STATUS_CONNECTED; // Ready for new requests } else { status = STATUS_BODY; } return OK; } } - //wait for response + // Wait for response return OK; } break; case STATUS_DISCONNECTED: { @@ -424,7 +428,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { while (true) { if (chunk_left == 0) { - //reading len + // Reading length uint8_t b; int rec = 0; err = _get_http_data(&b, 1, rec); @@ -467,7 +471,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { } if (len == 0) { - //end! + // End reached! status = STATUS_CONNECTED; chunk.clear(); return PoolByteArray(); @@ -525,7 +529,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { to_read -= rec; _offset += rec; } else { - if (to_read > 0) //ended up reading less + if (to_read > 0) // Ended up reading less ret.resize(_offset); break; } @@ -540,7 +544,7 @@ PoolByteArray HTTPClient::read_response_body_chunk() { close(); if (err == ERR_FILE_EOF) { - status = STATUS_DISCONNECTED; //server disconnected + status = STATUS_DISCONNECTED; // Server disconnected } else { status = STATUS_CONNECTION_ERROR; @@ -593,7 +597,7 @@ HTTPClient::HTTPClient() { tcp_connection = StreamPeerTCP::create_ref(); resolving = IP::RESOLVER_INVALID_ID; status = STATUS_DISCONNECTED; - conn_port = 80; + conn_port = -1; body_size = 0; chunked = false; body_left = 0; @@ -653,7 +657,7 @@ PoolStringArray HTTPClient::_get_response_headers() { void HTTPClient::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(false), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_connection", "connection"), &HTTPClient::set_connection); ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection); ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::request_raw); @@ -689,13 +693,13 @@ void HTTPClient::_bind_methods() { BIND_ENUM_CONSTANT(METHOD_MAX); BIND_ENUM_CONSTANT(STATUS_DISCONNECTED); - BIND_ENUM_CONSTANT(STATUS_RESOLVING); //resolving hostname (if passed a hostname) + BIND_ENUM_CONSTANT(STATUS_RESOLVING); // Resolving hostname (if hostname was passed in) BIND_ENUM_CONSTANT(STATUS_CANT_RESOLVE); - BIND_ENUM_CONSTANT(STATUS_CONNECTING); //connecting to ip + BIND_ENUM_CONSTANT(STATUS_CONNECTING); // Connecting to IP BIND_ENUM_CONSTANT(STATUS_CANT_CONNECT); - BIND_ENUM_CONSTANT(STATUS_CONNECTED); //connected ); requests only accepted here - BIND_ENUM_CONSTANT(STATUS_REQUESTING); // request in progress - BIND_ENUM_CONSTANT(STATUS_BODY); // request resulted in body ); which must be read + BIND_ENUM_CONSTANT(STATUS_CONNECTED); // Connected, now accepting requests + BIND_ENUM_CONSTANT(STATUS_REQUESTING); // Request in progress + BIND_ENUM_CONSTANT(STATUS_BODY); // Request resulted in body which must be read BIND_ENUM_CONSTANT(STATUS_CONNECTION_ERROR); BIND_ENUM_CONSTANT(STATUS_SSL_HANDSHAKE_ERROR); diff --git a/core/io/http_client.h b/core/io/http_client.h index 2e0a345f1c..3d8953c156 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -133,19 +133,29 @@ public: enum Status { STATUS_DISCONNECTED, - STATUS_RESOLVING, //resolving hostname (if passed a hostname) + STATUS_RESOLVING, // Resolving hostname (if passed a hostname) STATUS_CANT_RESOLVE, - STATUS_CONNECTING, //connecting to ip + STATUS_CONNECTING, // Connecting to IP STATUS_CANT_CONNECT, - STATUS_CONNECTED, //connected, requests only accepted here - STATUS_REQUESTING, // request in progress - STATUS_BODY, // request resulted in body, which must be read + STATUS_CONNECTED, // Connected, requests can be made + STATUS_REQUESTING, // Request in progress + STATUS_BODY, // Request resulted in body, which must be read STATUS_CONNECTION_ERROR, STATUS_SSL_HANDSHAKE_ERROR, }; private: + static const char *_methods[METHOD_MAX]; + static const int HOST_MIN_LEN = 4; + + enum Port { + + PORT_HTTP = 80, + PORT_HTTPS = 443, + + }; + #ifndef JAVASCRIPT_ENABLED Status status; IP::ResolverID resolving; @@ -182,8 +192,7 @@ private: static void _bind_methods(); public: - //Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request - Error connect_to_host(const String &p_host, int p_port, bool p_ssl = false, bool p_verify_host = true); + Error connect_to_host(const String &p_host, int p_port = -1, bool p_ssl = false, bool p_verify_host = true); void set_connection(const Ref<StreamPeer> &p_connection); Ref<StreamPeer> get_connection() const; @@ -201,9 +210,9 @@ public: Error get_response_headers(List<String> *r_response); int get_response_body_length() const; - PoolByteArray read_response_body_chunk(); // can't get body as partial text because of most encodings UTF8, gzip, etc. + PoolByteArray read_response_body_chunk(); // Can't get body as partial text because of most encodings UTF8, gzip, etc. - void set_blocking_mode(bool p_enable); //useful mostly if running in a thread + void set_blocking_mode(bool p_enable); // Useful mostly if running in a thread bool is_blocking_mode_enabled() const; void set_read_chunk_size(int p_size); diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 16c73c26e7..c6b12f73ae 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -49,7 +49,7 @@ bool PacketPeer::is_object_decoding_allowed() const { return allow_object_decoding; } -Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) const { +Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { const uint8_t *buffer; int buffer_size; @@ -78,7 +78,7 @@ Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) { return put_packet(&r[0], len); } -Error PacketPeer::get_var(Variant &r_variant) const { +Error PacketPeer::get_var(Variant &r_variant) { const uint8_t *buffer; int buffer_size; @@ -107,7 +107,7 @@ Error PacketPeer::put_var(const Variant &p_packet) { return put_packet(buf, len); } -Variant PacketPeer::_bnd_get_var() const { +Variant PacketPeer::_bnd_get_var() { Variant var; get_var(var); @@ -117,7 +117,7 @@ Variant PacketPeer::_bnd_get_var() const { Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) { return put_packet_buffer(p_buffer); } -PoolVector<uint8_t> PacketPeer::_get_packet() const { +PoolVector<uint8_t> PacketPeer::_get_packet() { PoolVector<uint8_t> raw; last_get_error = get_packet_buffer(raw); @@ -202,7 +202,7 @@ int PacketPeerStream::get_available_packet_count() const { return count; } -Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) const { +Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED); _poll_buffer(); diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index b08d44ad8a..a6d363ec12 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -37,13 +37,13 @@ class PacketPeer : public Reference { GDCLASS(PacketPeer, Reference); - Variant _bnd_get_var() const; + Variant _bnd_get_var(); void _bnd_put_var(const Variant &p_var); static void _bind_methods(); Error _put_packet(const PoolVector<uint8_t> &p_buffer); - PoolVector<uint8_t> _get_packet() const; + PoolVector<uint8_t> _get_packet(); Error _get_packet_error() const; mutable Error last_get_error; @@ -52,17 +52,17 @@ class PacketPeer : public Reference { public: virtual int get_available_packet_count() const = 0; - virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const = 0; ///< buffer is GONE after next get_packet + virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) = 0; ///< buffer is GONE after next get_packet virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size) = 0; virtual int get_max_packet_size() const = 0; /* helpers / binders */ - virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer) const; + virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer); virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer); - virtual Error get_var(Variant &r_variant) const; + virtual Error get_var(Variant &r_variant); virtual Error put_var(const Variant &p_packet); void set_allow_object_decoding(bool p_enable); @@ -91,7 +91,7 @@ protected: public: virtual int get_available_packet_count() const; - virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size) const; + virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size); virtual int get_max_packet_size() const; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index df0d41ea9d..92fdbc1581 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -104,7 +104,7 @@ StringName ResourceInteractiveLoaderBinary::_get_string() { uint32_t id = f->get_32(); if (id & 0x80000000) { - int len = id & 0x7FFFFFFF; + uint32_t len = id & 0x7FFFFFFF; if (len > str_buf.size()) { str_buf.resize(len); } @@ -734,6 +734,7 @@ Error ResourceInteractiveLoaderBinary::poll() { for (int i = 0; i < pc; i++) { StringName name = _get_string(); + if (name == StringName()) { error = ERR_FILE_CORRUPT; ERR_FAIL_V(ERR_FILE_CORRUPT); @@ -902,7 +903,9 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) { ExtResource er; er.type = get_unicode_string(); + er.path = get_unicode_string(); + external_resources.push_back(er); } @@ -1271,7 +1274,7 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// -void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) { +void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) { int extra = 4 - (p_bytes % 4); if (extra < 4) { @@ -1280,7 +1283,12 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(int p_bytes) { } } -void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, const PropertyInfo &p_hint) { +void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) { + + write_variant(f, p_property, resource_set, external_resources, string_map, p_hint); +} + +void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) { switch (p_property.get_type()) { @@ -1327,7 +1335,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, f->store_32(VARIANT_STRING); String val = p_property; - save_unicode_string(val); + save_unicode_string(f, val); } break; case Variant::VECTOR2: { @@ -1453,10 +1461,20 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, if (np.is_absolute()) snc |= 0x8000; f->store_16(snc); - for (int i = 0; i < np.get_name_count(); i++) - f->store_32(get_string_index(np.get_name(i))); - for (int i = 0; i < np.get_subname_count(); i++) - f->store_32(get_string_index(np.get_subname(i))); + for (int i = 0; i < np.get_name_count(); i++) { + if (string_map.has(np.get_name(i))) { + f->store_32(string_map[np.get_name(i)]); + } else { + save_unicode_string(f, np.get_name(i), true); + } + } + for (int i = 0; i < np.get_subname_count(); i++) { + if (string_map.has(np.get_subname(i))) { + f->store_32(string_map[np.get_subname(i)]); + } else { + save_unicode_string(f, np.get_subname(i), true); + } + } } break; case Variant::_RID: { @@ -1508,8 +1526,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, continue; */ - write_variant(E->get()); - write_variant(d[E->get()]); + write_variant(f, E->get(), resource_set, external_resources, string_map); + write_variant(f, d[E->get()], resource_set, external_resources, string_map); } } break; @@ -1520,7 +1538,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, f->store_32(uint32_t(a.size())); for (int i = 0; i < a.size(); i++) { - write_variant(a[i]); + write_variant(f, a[i], resource_set, external_resources, string_map); } } break; @@ -1532,7 +1550,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, f->store_32(len); PoolVector<uint8_t>::Read r = arr.read(); f->store_buffer(r.ptr(), len); - _pad_buffer(len); + _pad_buffer(f, len); } break; case Variant::POOL_INT_ARRAY: { @@ -1566,7 +1584,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property, f->store_32(len); PoolVector<String>::Read r = arr.read(); for (int i = 0; i < len; i++) { - save_unicode_string(r[i]); + save_unicode_string(f, r[i]); } } break; @@ -1693,10 +1711,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant } } -void ResourceFormatSaverBinaryInstance::save_unicode_string(const String &p_string) { +void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) { CharString utf8 = p_string.utf8(); - f->store_32(utf8.length() + 1); + if (p_bit_on_len) { + f->store_32(utf8.length() + 1 | 0x80000000); + } else { + f->store_32(utf8.length() + 1); + } f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1); } @@ -1763,7 +1785,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p return ERR_CANT_CREATE; } - save_unicode_string(p_resource->get_class()); + save_unicode_string(f, p_resource->get_class()); f->store_64(0); //offset to import metadata for (int i = 0; i < 14; i++) f->store_32(0); // reserved @@ -1800,7 +1822,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p f->store_32(strings.size()); //string table size for (int i = 0; i < strings.size(); i++) { - save_unicode_string(strings[i]); + save_unicode_string(f, strings[i]); } // save external resource table @@ -1814,10 +1836,10 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p for (int i = 0; i < save_order.size(); i++) { - save_unicode_string(save_order[i]->get_save_class()); + save_unicode_string(f, save_order[i]->get_save_class()); String path = save_order[i]->get_path(); path = relative_paths ? local_path.path_to_file(path) : path; - save_unicode_string(path); + save_unicode_string(f, path); } // save internal resource table f->store_32(saved_resources.size()); //amount of internal resources @@ -1853,7 +1875,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p used_indices.insert(new_subindex); } - save_unicode_string("local://" + itos(r->get_subindex())); + save_unicode_string(f, "local://" + itos(r->get_subindex())); if (takeover_paths) { r->set_path(p_path + "::" + itos(r->get_subindex()), true); } @@ -1861,7 +1883,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p r->set_edited(false); #endif } else { - save_unicode_string(r->get_path()); //actual external + save_unicode_string(f, r->get_path()); //actual external } ofs_pos.push_back(f->get_position()); f->store_64(0); //offset in 64 bits @@ -1875,14 +1897,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p ResourceData &rd = E->get(); ofs_table.push_back(f->get_position()); - save_unicode_string(rd.type); + save_unicode_string(f, rd.type); f->store_32(rd.properties.size()); for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) { Property &p = F->get(); f->store_32(p.name_idx); - write_variant(p.value, F->get().pi); + _write_variant(p.value, F->get().pi); } } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 687da0a9b4..176b8350cf 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -140,14 +140,15 @@ class ResourceFormatSaverBinaryInstance { List<Property> properties; }; - void _pad_buffer(int p_bytes); - void write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo()); + static void _pad_buffer(FileAccess *f, int p_bytes); + void _write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo()); void _find_resources(const Variant &p_variant, bool p_main = false); - void save_unicode_string(const String &p_string); + static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false); int get_string_index(const String &p_string); public: Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); + static void write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo()); }; class ResourceFormatSaverBinary : public ResourceFormatSaver { diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index ed0d491679..dea9f38634 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -35,6 +35,7 @@ #include "print_string.h" #include "project_settings.h" #include "translation.h" +#include "variant_parser.h" ResourceFormatLoader *ResourceLoader::loader[MAX_LOADERS]; int ResourceLoader::loader_count = 0; @@ -196,19 +197,19 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p else local_path = ProjectSettings::get_singleton()->localize_path(p_path); - bool xl_remapped = false; - String path = _path_remap(local_path, &xl_remapped); - - ERR_FAIL_COND_V(path == "", RES()); - - if (!p_no_cache && ResourceCache::has(path)) { + if (!p_no_cache && ResourceCache::has(local_path)) { if (OS::get_singleton()->is_stdout_verbose()) - print_line("load resource: " + path + " (cached)"); + print_line("load resource: " + local_path + " (cached)"); - return RES(ResourceCache::get(path)); + return RES(ResourceCache::get(local_path)); } + bool xl_remapped = false; + String path = _path_remap(local_path, &xl_remapped); + + ERR_FAIL_COND_V(path == "", RES()); + if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: " + path); @@ -247,23 +248,23 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ else local_path = ProjectSettings::get_singleton()->localize_path(p_path); - bool xl_remapped = false; - String path = _path_remap(local_path, &xl_remapped); - - ERR_FAIL_COND_V(path == "", Ref<ResourceInteractiveLoader>()); - - if (!p_no_cache && ResourceCache::has(path)) { + if (!p_no_cache && ResourceCache::has(local_path)) { if (OS::get_singleton()->is_stdout_verbose()) - print_line("load resource: " + path + " (cached)"); + print_line("load resource: " + local_path + " (cached)"); - Ref<Resource> res_cached = ResourceCache::get(path); + Ref<Resource> res_cached = ResourceCache::get(local_path); Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault)); ril->resource = res_cached; return ril; } + bool xl_remapped = false; + String path = _path_remap(local_path, &xl_remapped); + + ERR_FAIL_COND_V(path == "", Ref<ResourceInteractiveLoader>()); + if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: "); @@ -426,9 +427,11 @@ String ResourceLoader::get_resource_type(const String &p_path) { String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) { - if (translation_remaps.has(p_path)) { + String new_path = p_path; - Vector<String> &v = *translation_remaps.getptr(p_path); + if (translation_remaps.has(new_path)) { + + Vector<String> &v = *translation_remaps.getptr(new_path); String locale = TranslationServer::get_singleton()->get_locale(); if (r_translation_remapped) { *r_translation_remapped = true; @@ -443,12 +446,59 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem continue; if (l.begins_with(locale)) { - return v[i].left(split); + new_path = v[i].left(split); + break; } } } - return p_path; + if (path_remaps.has(new_path)) { + new_path = path_remaps[new_path]; + } + + if (new_path == p_path) { //did not remap + //try file remap + Error err; + FileAccess *f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err); + + if (f) { + + VariantParser::StreamFile stream; + stream.f = f; + + String assign; + Variant value; + VariantParser::Tag next_tag; + + int lines = 0; + String error_text; + while (true) { + + assign = Variant(); + next_tag.fields.clear(); + next_tag.name = String(); + + err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, NULL, true); + if (err == ERR_FILE_EOF) { + break; + } else if (err != OK) { + ERR_PRINTS("Parse error: " + p_path + ".remap:" + itos(lines) + " error: " + error_text); + break; + } + + if (assign == "path") { + new_path = value; + break; + } else if (next_tag.name != "remap") { + break; + } + } + + memdelete(f); + } + } + + return new_path; } String ResourceLoader::import_remap(const String &p_path) { @@ -515,6 +565,27 @@ void ResourceLoader::clear_translation_remaps() { translation_remaps.clear(); } +void ResourceLoader::load_path_remaps() { + + if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) + return; + + PoolVector<String> remaps = ProjectSettings::get_singleton()->get("path_remap/remapped_paths"); + int rc = remaps.size(); + ERR_FAIL_COND(rc & 1); //must be even + PoolVector<String>::Read r = remaps.read(); + + for (int i = 0; i < rc; i += 2) { + + path_remaps[r[i]] = r[i + 1]; + } +} + +void ResourceLoader::clear_path_remaps() { + + path_remaps.clear(); +} + ResourceLoadErrorNotify ResourceLoader::err_notify = NULL; void *ResourceLoader::err_notify_ud = NULL; @@ -526,3 +597,4 @@ bool ResourceLoader::timestamp_on_load = false; SelfList<Resource>::List ResourceLoader::remapped_list; HashMap<String, Vector<String> > ResourceLoader::translation_remaps; +HashMap<String, String> ResourceLoader::path_remaps; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 5deffbca1a..05f01d8d31 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -91,6 +91,7 @@ class ResourceLoader { static DependencyErrorNotify dep_err_notify; static bool abort_on_missing_resource; static HashMap<String, Vector<String> > translation_remaps; + static HashMap<String, String> path_remaps; static String _path_remap(const String &p_path, bool *r_translation_remapped = NULL); friend class Resource; @@ -137,6 +138,9 @@ public: static String path_remap(const String &p_path); static String import_remap(const String &p_path); + static void load_path_remaps(); + static void clear_path_remaps(); + static void reload_translation_remaps(); static void load_translation_remaps(); static void clear_translation_remaps(); |