diff options
Diffstat (limited to 'core/io')
27 files changed, 1138 insertions, 240 deletions
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 5968972143..b44ac16a87 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -34,11 +34,11 @@ #include "core/os/keyboard.h" #include "core/variant_parser.h" -PoolStringArray ConfigFile::_get_sections() const { +PackedStringArray ConfigFile::_get_sections() const { List<String> s; get_sections(&s); - PoolStringArray arr; + PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { @@ -49,11 +49,11 @@ PoolStringArray ConfigFile::_get_sections() const { return arr; } -PoolStringArray ConfigFile::_get_section_keys(const String &p_section) const { +PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { List<String> s; get_section_keys(p_section, &s); - PoolStringArray arr; + PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { diff --git a/core/io/config_file.h b/core/io/config_file.h index 2d61ef6afe..150fd24693 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -42,8 +42,8 @@ class ConfigFile : public Reference { OrderedHashMap<String, OrderedHashMap<String, Variant> > values; - PoolStringArray _get_sections() const; - PoolStringArray _get_section_keys(const String &p_section) const; + PackedStringArray _get_sections() const; + PackedStringArray _get_section_keys(const String &p_section) const; Error _internal_load(const String &p_path, FileAccess *f); Error _internal_save(FileAccess *file); diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp new file mode 100644 index 0000000000..07e6abb1c9 --- /dev/null +++ b/core/io/dtls_server.cpp @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* dtls_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "dtls_server.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" + +DTLSServer *(*DTLSServer::_create)() = NULL; +bool DTLSServer::available = false; + +DTLSServer *DTLSServer::create() { + + return _create(); +} + +bool DTLSServer::is_available() { + return available; +} + +void DTLSServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("setup", "key", "certificate", "chain"), &DTLSServer::setup, DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("take_connection", "udp_peer"), &DTLSServer::take_connection); +} + +DTLSServer::DTLSServer() { +} diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h new file mode 100644 index 0000000000..7b08138f7f --- /dev/null +++ b/core/io/dtls_server.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* dtls_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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. */ +/*************************************************************************/ + +#ifndef DTLS_SERVER_H +#define DTLS_SERVER_H + +#include "core/io/net_socket.h" +#include "core/io/packet_peer_dtls.h" + +class DTLSServer : public Reference { + GDCLASS(DTLSServer, Reference); + +protected: + static DTLSServer *(*_create)(); + static void _bind_methods(); + + static bool available; + +public: + static bool is_available(); + static DTLSServer *create(); + + virtual Error setup(Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; + virtual void stop() = 0; + virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) = 0; + + DTLSServer(); +}; + +#endif // DTLS_SERVER_H diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp index 6ac065a19b..ab0fb3943c 100644 --- a/core/io/file_access_buffered.cpp +++ b/core/io/file_access_buffered.cpp @@ -113,7 +113,7 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { int size = (cache.buffer.size() - (file.offset - cache.offset)); size = size - (size % 4); - //PoolVector<uint8_t>::Read read = cache.buffer.read(); + //const uint8_t* read = cache.buffer.ptr(); //memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size); memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size); p_dest += size; @@ -145,7 +145,7 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { } int r = MIN(left, to_read); - //PoolVector<uint8_t>::Read read = cache.buffer.read(); + //const uint8_t* read = cache.buffer.ptr(); //memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r); memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r); diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h index 5e2939c1a2..a6177c20be 100644 --- a/core/io/file_access_buffered.h +++ b/core/io/file_access_buffered.h @@ -32,7 +32,7 @@ #define FILE_ACCESS_BUFFERED_H #include "core/os/file_access.h" -#include "core/pool_vector.h" + #include "core/ustring.h" class FileAccessBuffered : public FileAccess { diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index c17652080c..6ec77d503b 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -54,8 +54,8 @@ class FileAccessBufferedFA : public FileAccessBuffered { cache.offset = p_offset; cache.buffer.resize(p_size); - // on PoolVector - //PoolVector<uint8_t>::Write write = cache.buffer.write(); + // on Vector + //uint8_t* write = cache.buffer.ptrw(); //f.get_buffer(write.ptrw(), p_size); // on vector diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 541bd3a7c8..ce7025de35 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -110,7 +110,7 @@ Ref<StreamPeer> HTTPClient::get_connection() const { return connection; } -Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) { +Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<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); @@ -152,10 +152,10 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector request += "\r\n"; CharString cs = request.utf8(); - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(cs.length()); { - PoolVector<uint8_t>::Write data_write = data.write(); + uint8_t *data_write = data.ptrw(); for (int i = 0; i < cs.length(); i++) { data_write[i] = cs[i]; } @@ -163,7 +163,7 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector data.append_array(p_body); - PoolVector<uint8_t>::Read r = data.read(); + const uint8_t *r = data.ptr(); Error err = connection->put_data(&r[0], data.size()); if (err) { @@ -517,11 +517,11 @@ int HTTPClient::get_response_body_length() const { return body_size; } -PoolByteArray HTTPClient::read_response_body_chunk() { +PackedByteArray HTTPClient::read_response_body_chunk() { - ERR_FAIL_COND_V(status != STATUS_BODY, PoolByteArray()); + ERR_FAIL_COND_V(status != STATUS_BODY, PackedByteArray()); - PoolByteArray ret; + PackedByteArray ret; Error err = OK; if (chunked) { @@ -622,8 +622,8 @@ PoolByteArray HTTPClient::read_response_body_chunk() { } ret.resize(chunk.size() - 2); - PoolByteArray::Write w = ret.write(); - copymem(w.ptr(), chunk.ptr(), chunk.size() - 2); + uint8_t *w = ret.ptrw(); + copymem(w, chunk.ptr(), chunk.size() - 2); chunk.clear(); } @@ -639,8 +639,8 @@ PoolByteArray HTTPClient::read_response_body_chunk() { while (to_read > 0) { int rec = 0; { - PoolByteArray::Write w = ret.write(); - err = _get_http_data(w.ptr() + _offset, to_read, rec); + uint8_t *w = ret.ptrw(); + err = _get_http_data(w + _offset, to_read, rec); } if (rec <= 0) { // Ended up reading less ret.resize(_offset); @@ -801,11 +801,11 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() { return ret; } -PoolStringArray HTTPClient::_get_response_headers() { +PackedStringArray HTTPClient::_get_response_headers() { List<String> rh; get_response_headers(&rh); - PoolStringArray ret; + PackedStringArray ret; ret.resize(rh.size()); int idx = 0; for (const List<String>::Element *E = rh.front(); E; E = E->next()) { diff --git a/core/io/http_client.h b/core/io/http_client.h index 3796eb992c..03ba20f8dd 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -191,7 +191,7 @@ private: #include "platform/javascript/http_client.h.inc" #endif - PoolStringArray _get_response_headers(); + PackedStringArray _get_response_headers(); Dictionary _get_response_headers_as_dictionary(); static void _bind_methods(); @@ -202,7 +202,7 @@ public: void set_connection(const Ref<StreamPeer> &p_connection); Ref<StreamPeer> get_connection() const; - Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body); + Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body); Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String()); void close(); @@ -215,7 +215,7 @@ 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. + PackedByteArray 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 bool is_blocking_mode_enabled() const; diff --git a/core/io/json.cpp b/core/io/json.cpp index 144e4bdc3b..3a0edceb81 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -70,10 +70,12 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ case Variant::NIL: return "null"; case Variant::BOOL: return p_var.operator bool() ? "true" : "false"; case Variant::INT: return itos(p_var); - case Variant::REAL: return rtos(p_var); - case Variant::POOL_INT_ARRAY: - case Variant::POOL_REAL_ARRAY: - case Variant::POOL_STRING_ARRAY: + case Variant::FLOAT: return rtos(p_var); + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + case Variant::PACKED_STRING_ARRAY: case Variant::ARRAY: { String s = "["; diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 17edc4982c..fbcaa582b7 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -147,7 +147,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::REAL: { + case Variant::FLOAT: { if (type & ENCODE_FLAG_64) { ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); @@ -186,7 +186,19 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (r_len) (*r_len) += 4 * 2; - } break; // 5 + } break; + case Variant::VECTOR2I: { + + ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA); + Vector2i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + r_variant = val; + + if (r_len) + (*r_len) += 4 * 2; + + } break; case Variant::RECT2: { ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); @@ -201,6 +213,20 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += 4 * 4; } break; + case Variant::RECT2I: { + + ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); + Rect2i val; + val.position.x = decode_uint32(&buf[0]); + val.position.y = decode_uint32(&buf[4]); + val.size.x = decode_uint32(&buf[8]); + val.size.y = decode_uint32(&buf[12]); + r_variant = val; + + if (r_len) + (*r_len) += 4 * 4; + + } break; case Variant::VECTOR3: { ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA); @@ -214,6 +240,19 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += 4 * 3; } break; + case Variant::VECTOR3I: { + + ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA); + Vector3i val; + val.x = decode_uint32(&buf[0]); + val.y = decode_uint32(&buf[4]); + val.z = decode_uint32(&buf[8]); + r_variant = val; + + if (r_len) + (*r_len) += 4 * 3; + + } break; case Variant::TRANSFORM2D: { ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA); @@ -328,6 +367,16 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int (*r_len) += 4 * 4; } break; + case Variant::STRING_NAME: { + + String str; + Error err = _decode_string(buf, len, r_len, str); + if (err) + return err; + r_variant = StringName(str); + + } break; + case Variant::NODE_PATH: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); @@ -455,6 +504,15 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; + case Variant::CALLABLE: { + + r_variant = Callable(); + } break; + case Variant::SIGNAL: { + + r_variant = Signal(); + } break; + case Variant::DICTIONARY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); @@ -535,7 +593,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; // arrays - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -543,11 +601,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int len -= 4; ERR_FAIL_COND_V(count < 0 || count > len, ERR_INVALID_DATA); - PoolVector<uint8_t> data; + Vector<uint8_t> data; if (count) { data.resize(count); - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = buf[i]; @@ -563,7 +621,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT32_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -572,12 +630,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA); - PoolVector<int> data; + Vector<int32_t> data; if (count) { //const int*rbuf=(const int*)buf; data.resize(count); - PoolVector<int>::Write w = data.write(); + int32_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = decode_uint32(&buf[i * 4]); @@ -585,11 +643,37 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } r_variant = Variant(data); if (r_len) { - (*r_len) += 4 + count * sizeof(int); + (*r_len) += 4 + count * sizeof(int32_t); } } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_INT64_ARRAY: { + + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int64_t count = decode_uint64(buf); + buf += 4; + len -= 4; + ERR_FAIL_MUL_OF(count, 8, ERR_INVALID_DATA); + ERR_FAIL_COND_V(count < 0 || count * 8 > len, ERR_INVALID_DATA); + + Vector<int64_t> data; + + if (count) { + //const int*rbuf=(const int*)buf; + data.resize(count); + int64_t *w = data.ptrw(); + for (int64_t i = 0; i < count; i++) { + + w[i] = decode_uint64(&buf[i * 8]); + } + } + r_variant = Variant(data); + if (r_len) { + (*r_len) += 4 + count * sizeof(int64_t); + } + + } break; + case Variant::PACKED_FLOAT32_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -598,12 +682,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 > len, ERR_INVALID_DATA); - PoolVector<float> data; + Vector<float> data; if (count) { //const float*rbuf=(const float*)buf; data.resize(count); - PoolVector<float>::Write w = data.write(); + float *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { w[i] = decode_float(&buf[i * 4]); @@ -616,12 +700,39 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_FLOAT64_ARRAY: { + + ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); + int64_t count = decode_uint64(buf); + buf += 4; + len -= 4; + ERR_FAIL_MUL_OF(count, 8, ERR_INVALID_DATA); + ERR_FAIL_COND_V(count < 0 || count * 8 > len, ERR_INVALID_DATA); + + Vector<double> data; + + if (count) { + //const double*rbuf=(const double*)buf; + data.resize(count); + double *w = data.ptrw(); + for (int64_t i = 0; i < count; i++) { + + w[i] = decode_double(&buf[i * 8]); + } + } + r_variant = data; + + if (r_len) { + (*r_len) += 4 + count * sizeof(double); + } + + } break; + case Variant::PACKED_STRING_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); - PoolVector<String> strings; + Vector<String> strings; buf += 4; len -= 4; @@ -642,7 +753,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = strings; } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -651,7 +762,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 2, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 2 > len, ERR_INVALID_DATA); - PoolVector<Vector2> varray; + Vector<Vector2> varray; if (r_len) { (*r_len) += 4; @@ -659,7 +770,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { varray.resize(count); - PoolVector<Vector2>::Write w = varray.write(); + Vector2 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -676,7 +787,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = varray; } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -686,7 +797,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 3, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 3 > len, ERR_INVALID_DATA); - PoolVector<Vector3> varray; + Vector<Vector3> varray; if (r_len) { (*r_len) += 4; @@ -694,7 +805,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { varray.resize(count); - PoolVector<Vector3>::Write w = varray.write(); + Vector3 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -712,7 +823,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = varray; } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -722,7 +833,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int ERR_FAIL_MUL_OF(count, 4 * 4, ERR_INVALID_DATA); ERR_FAIL_COND_V(count < 0 || count * 4 * 4 > len, ERR_INVALID_DATA); - PoolVector<Color> carray; + Vector<Color> carray; if (r_len) { (*r_len) += 4; @@ -730,7 +841,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int if (count) { carray.resize(count); - PoolVector<Color>::Write w = carray.write(); + Color *w = carray.ptrw(); for (int32_t i = 0; i < count; i++) { @@ -793,7 +904,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo flags |= ENCODE_FLAG_64; } } break; - case Variant::REAL: { + case Variant::FLOAT: { double d = p_variant; float f = d; @@ -860,7 +971,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; } } break; - case Variant::REAL: { + case Variant::FLOAT: { if (flags & ENCODE_FLAG_64) { if (buf) { @@ -930,6 +1041,11 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo _encode_string(p_variant, buf, r_len); } break; + case Variant::STRING_NAME: { + + _encode_string(p_variant, buf, r_len); + + } break; // math types case Variant::VECTOR2: { @@ -942,7 +1058,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 2 * 4; - } break; // 5 + } break; + case Variant::VECTOR2I: { + + if (buf) { + Vector2i v2 = p_variant; + encode_uint32(v2.x, &buf[0]); + encode_uint32(v2.y, &buf[4]); + } + + r_len += 2 * 4; + + } break; case Variant::RECT2: { if (buf) { @@ -955,6 +1082,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 4; } break; + case Variant::RECT2I: { + + if (buf) { + Rect2i r2 = p_variant; + encode_uint32(r2.position.x, &buf[0]); + encode_uint32(r2.position.y, &buf[4]); + encode_uint32(r2.size.x, &buf[8]); + encode_uint32(r2.size.y, &buf[12]); + } + r_len += 4 * 4; + + } break; case Variant::VECTOR3: { if (buf) { @@ -967,6 +1106,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 3 * 4; } break; + case Variant::VECTOR3I: { + + if (buf) { + Vector3i v3 = p_variant; + encode_uint32(v3.x, &buf[0]); + encode_uint32(v3.y, &buf[4]); + encode_uint32(v3.z, &buf[8]); + } + + r_len += 3 * 4; + + } break; case Variant::TRANSFORM2D: { if (buf) { @@ -1075,6 +1226,12 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo case Variant::_RID: { } break; + case Variant::CALLABLE: { + + } break; + case Variant::SIGNAL: { + + } break; case Variant::OBJECT: { if (p_full_objects) { @@ -1207,16 +1364,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; // arrays - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { - PoolVector<uint8_t> data = p_variant; + Vector<uint8_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(uint8_t); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<uint8_t>::Read r = data.read(); + const uint8_t *r = data.ptr(); copymem(buf, &r[0], datalen * datasize); buf += datalen * datasize; } @@ -1229,33 +1386,50 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT32_ARRAY: { - PoolVector<int> data = p_variant; + Vector<int32_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(int32_t); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<int>::Read r = data.read(); - for (int i = 0; i < datalen; i++) + const int32_t *r = data.ptr(); + for (int32_t i = 0; i < datalen; i++) encode_uint32(r[i], &buf[i * datasize]); } r_len += 4 + datalen * datasize; } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_INT64_ARRAY: { - PoolVector<real_t> data = p_variant; + Vector<int64_t> data = p_variant; int datalen = data.size(); - int datasize = sizeof(real_t); + int datasize = sizeof(int64_t); + + if (buf) { + encode_uint64(datalen, buf); + buf += 4; + const int64_t *r = data.ptr(); + for (int64_t i = 0; i < datalen; i++) + encode_uint64(r[i], &buf[i * datasize]); + } + + r_len += 4 + datalen * datasize; + + } break; + case Variant::PACKED_FLOAT32_ARRAY: { + + Vector<float> data = p_variant; + int datalen = data.size(); + int datasize = sizeof(float); if (buf) { encode_uint32(datalen, buf); buf += 4; - PoolVector<real_t>::Read r = data.read(); + const float *r = data.ptr(); for (int i = 0; i < datalen; i++) encode_float(r[i], &buf[i * datasize]); } @@ -1263,9 +1437,26 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + datalen * datasize; } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_FLOAT64_ARRAY: { + + Vector<double> data = p_variant; + int datalen = data.size(); + int datasize = sizeof(double); + + if (buf) { + encode_uint32(datalen, buf); + buf += 4; + const double *r = data.ptr(); + for (int i = 0; i < datalen; i++) + encode_double(r[i], &buf[i * datasize]); + } + + r_len += 4 + datalen * datasize; + + } break; + case Variant::PACKED_STRING_ARRAY: { - PoolVector<String> data = p_variant; + Vector<String> data = p_variant; int len = data.size(); if (buf) { @@ -1295,9 +1486,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { - PoolVector<Vector2> data = p_variant; + Vector<Vector2> data = p_variant; int len = data.size(); if (buf) { @@ -1322,9 +1513,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 2 * len; } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { - PoolVector<Vector3> data = p_variant; + Vector<Vector3> data = p_variant; int len = data.size(); if (buf) { @@ -1350,9 +1541,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 3 * len; } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { - PoolVector<Color> data = p_variant; + Vector<Color> data = p_variant; int len = data.size(); if (buf) { diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 3f66e00021..2aef0a3274 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -34,6 +34,10 @@ #include "scene/main/node.h" #include <stdint.h> +#define NODE_ID_COMPRESSION_SHIFT 3 +#define NAME_ID_COMPRESSION_SHIFT 5 +#define BYTE_ONLY_OR_NO_ARGS_SHIFT 6 + #ifdef DEBUG_ENABLED #include "core/os/os.h" #endif @@ -51,7 +55,7 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas case MultiplayerAPI::RPC_MODE_MASTERSYNC: { if (is_master) r_skip_rpc = true; // I am the master, so skip remote call. - FALLTHROUGH; + [[fallthrough]]; } case MultiplayerAPI::RPC_MODE_REMOTESYNC: case MultiplayerAPI::RPC_MODE_PUPPETSYNC: { @@ -145,22 +149,22 @@ void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_pee "Supplied NetworkedMultiplayerPeer must be connecting or connected."); if (network_peer.is_valid()) { - network_peer->disconnect("peer_connected", this, "_add_peer"); - network_peer->disconnect("peer_disconnected", this, "_del_peer"); - network_peer->disconnect("connection_succeeded", this, "_connected_to_server"); - network_peer->disconnect("connection_failed", this, "_connection_failed"); - network_peer->disconnect("server_disconnected", this, "_server_disconnected"); + network_peer->disconnect_compat("peer_connected", this, "_add_peer"); + network_peer->disconnect_compat("peer_disconnected", this, "_del_peer"); + network_peer->disconnect_compat("connection_succeeded", this, "_connected_to_server"); + network_peer->disconnect_compat("connection_failed", this, "_connection_failed"); + network_peer->disconnect_compat("server_disconnected", this, "_server_disconnected"); clear(); } network_peer = p_peer; if (network_peer.is_valid()) { - network_peer->connect("peer_connected", this, "_add_peer"); - network_peer->connect("peer_disconnected", this, "_del_peer"); - network_peer->connect("connection_succeeded", this, "_connected_to_server"); - network_peer->connect("connection_failed", this, "_connection_failed"); - network_peer->connect("server_disconnected", this, "_server_disconnected"); + network_peer->connect_compat("peer_connected", this, "_add_peer"); + network_peer->connect_compat("peer_disconnected", this, "_del_peer"); + network_peer->connect_compat("connection_succeeded", this, "_connected_to_server"); + network_peer->connect_compat("connection_failed", this, "_connection_failed"); + network_peer->connect_compat("server_disconnected", this, "_server_disconnected"); } } @@ -168,6 +172,16 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const { return network_peer; } +// Returns the packet size stripping the node path added when the node is not yet cached. +int get_packet_len(uint32_t p_node_target, int p_packet_len) { + if (p_node_target & 0x80000000) { + int ofs = p_node_target & 0x7FFFFFFF; + return p_packet_len - (p_packet_len - ofs); + } else { + return p_packet_len; + } +} + void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { ERR_FAIL_COND_MSG(root_node == NULL, "Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it."); @@ -204,8 +218,8 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ int name_id_offset = 1; ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); // Compute the meta size, which depends on the compression level. - int node_id_compression = (p_packet[0] & 24) >> 3; - int name_id_compression = (p_packet[0] & 32) >> 5; + int node_id_compression = (p_packet[0] & 24) >> NODE_ID_COMPRESSION_SHIFT; + int name_id_compression = (p_packet[0] & 32) >> NAME_ID_COMPRESSION_SHIFT; switch (node_id_compression) { case NETWORK_NODE_ID_COMPRESSION_8: @@ -250,6 +264,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ // Unreachable, checked before. CRASH_NOW(); } + Node *node = _process_get_node(p_from, p_packet, node_target, p_packet_len); ERR_FAIL_COND_MSG(node == NULL, "Invalid packet received. Requested node was not found."); @@ -266,13 +281,14 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ CRASH_NOW(); } + const int packet_len = get_packet_len(node_target, p_packet_len); if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - _process_rpc(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); + _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size); } else { - _process_rset(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); + _process_rset(node, name_id, p_from, p_packet, packet_len, packet_min_size); } } break; @@ -326,7 +342,7 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. StringName name = p_node->get_node_rpc_method(p_rpc_method_id); @@ -340,14 +356,30 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, bool can_call = _can_call_mode(p_node, rpc_mode, p_from); ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); - int argc = p_packet[p_offset]; + int argc = 0; + bool byte_only = false; + + const bool byte_only_or_no_args = ((p_packet[0] & 64) >> BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1; + if (byte_only_or_no_args) { + if (p_offset < p_packet_len) { + // This packet contains only bytes. + argc = 1; + byte_only = true; + } else { + // This rpc calls a method without parameters. + } + } else { + // Normal variant, takes the argument count from the packet. + ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + argc = p_packet[p_offset]; + p_offset += 1; + } + Vector<Variant> args; Vector<const Variant *> argp; args.resize(argc); argp.resize(argc); - p_offset++; - #ifdef DEBUG_ENABLED if (profiling) { ObjectID id = p_node->get_instance_id(); @@ -356,22 +388,32 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, } #endif - for (int i = 0; i < argc; i++) { + if (byte_only) { + Vector<uint8_t> pure_data; + const int len = p_packet_len - p_offset; + pure_data.resize(len); + memcpy(pure_data.ptrw(), &p_packet[p_offset], len); + args.write[0] = pure_data; + argp.write[0] = &args[0]; + p_offset += len; + } else { + for (int i = 0; i < argc; i++) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); - int vlen; - Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); - ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); + int vlen; + Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); + ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); - argp.write[i] = &args[i]; - p_offset += vlen; + argp.write[i] = &args[i]; + p_offset += vlen; + } } - Variant::CallError ce; + Callable::CallError ce; p_node->call(name, (const Variant **)argp.ptr(), argc, ce); - if (ce.error != Variant::CallError::CALL_OK) { + if (ce.error != Callable::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINT(error); @@ -742,10 +784,12 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p // - `NetworkCommands` in the first three bits. // - `NetworkNodeIdCompression` in the next 2 bits. // - `NetworkNameIdCompression` in the next 1 bit. - // - So we still have the last two bits free! + // - `byte_only_or_no_args` in the next 1 bit. + // - So we still have the last bit free! uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; uint8_t node_id_compression = UINT8_MAX; uint8_t name_id_compression = UINT8_MAX; + bool byte_only_or_no_args = false; MAKE_ROOM(1); // The meta is composed along the way, so just set 0 for now. @@ -835,17 +879,28 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p ofs += 2; } - // Call arguments. - MAKE_ROOM(ofs + 1); - packet_cache.write[ofs] = p_argcount; - ofs += 1; - for (int i = 0; i < p_argcount; i++) { - int len(0); - Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); - ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); - MAKE_ROOM(ofs + len); - _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); - ofs += len; + if (p_argcount == 0) { + byte_only_or_no_args = true; + } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) { + byte_only_or_no_args = true; + // Special optimization when only the byte vector is sent. + const Vector<uint8_t> data = *p_arg[0]; + MAKE_ROOM(ofs + data.size()); + copymem(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size()); + ofs += data.size(); + } else { + // Arguments + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = p_argcount; + ofs += 1; + for (int i = 0; i < p_argcount; i++) { + int len(0); + Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); + ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); + MAKE_ROOM(ofs + len); + _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); + ofs += len; + } } } @@ -854,7 +909,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p ERR_FAIL_COND(name_id_compression > 1); // We can now set the meta - packet_cache.write[0] = command_type + (node_id_compression << 3) + (name_id_compression << 5); + packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + ((byte_only_or_no_args ? 1 : 0) << BYTE_ONLY_OR_NO_ARGS_SHIFT); #ifdef DEBUG_ENABLED if (profiling) { @@ -989,10 +1044,10 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (call_local_native) { int temp_id = rpc_sender_id; rpc_sender_id = get_network_unique_id(); - Variant::CallError ce; + Callable::CallError ce; p_node->call(p_method, p_arg, p_argcount, ce); rpc_sender_id = temp_id; - if (ce.error != Variant::CallError::CALL_OK) { + if (ce.error != Callable::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in local call: - " + error + "."; ERR_PRINT(error); @@ -1003,11 +1058,11 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (call_local_script) { int temp_id = rpc_sender_id; rpc_sender_id = get_network_unique_id(); - Variant::CallError ce; - ce.error = Variant::CallError::CALL_OK; + Callable::CallError ce; + ce.error = Callable::CallError::CALL_OK; p_node->get_script_instance()->call(p_method, p_arg, p_argcount, ce); rpc_sender_id = temp_id; - if (ce.error != Variant::CallError::CALL_OK) { + if (ce.error != Callable::CallError::CALL_OK) { String error = Variant::get_call_error_text(p_node, p_method, p_arg, p_argcount, ce); error = "rpc() aborted in script local call: - " + error + "."; ERR_PRINT(error); @@ -1087,14 +1142,14 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const _send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1); } -Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) { +Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) { ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet."); ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active."); ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected."); MAKE_ROOM(p_data.size() + 1); - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); packet_cache.write[0] = NETWORK_COMMAND_RAW; memcpy(&packet_cache.write[1], &r[0], p_data.size()); @@ -1108,11 +1163,11 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); - PoolVector<uint8_t> out; + Vector<uint8_t> out; int len = p_packet_len - 1; out.resize(len); { - PoolVector<uint8_t>::Write w = out.write(); + uint8_t *w = out.ptrw(); memcpy(&w[0], &p_packet[1], len); } emit_signal("network_peer_packet", p_from, out); @@ -1284,7 +1339,7 @@ void MultiplayerAPI::_bind_methods() { ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); - ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "packet"))); + ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "packet"))); ADD_SIGNAL(MethodInfo("connected_to_server")); ADD_SIGNAL(MethodInfo("connection_failed")); ADD_SIGNAL(MethodInfo("server_disconnected")); diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index 8748dba03c..a706a0e450 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -145,7 +145,7 @@ public: void set_root_node(Node *p_node); void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer); Ref<NetworkedMultiplayerPeer> get_network_peer() const; - Error send_bytes(PoolVector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); + Error send_bytes(Vector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); // Called by Node.rpc void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount); diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 710df2dd78..376fd87a27 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -61,7 +61,7 @@ public: virtual Error connect_to_host(IP_Address p_addr, uint16_t p_port) = 0; virtual Error poll(PollType p_type, int timeout) const = 0; virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read) = 0; - virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port) = 0; + virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false) = 0; virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent) = 0; virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) = 0; virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port) = 0; diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 81d7b86161..2f5c493c2c 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -53,7 +53,7 @@ int PacketPeer::get_encode_buffer_max_size() const { return encode_buffer_max_size; } -Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { +Error PacketPeer::get_packet_buffer(Vector<uint8_t> &r_buffer) { const uint8_t *buffer; int buffer_size; @@ -65,20 +65,20 @@ Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) { if (buffer_size == 0) return OK; - PoolVector<uint8_t>::Write w = r_buffer.write(); + uint8_t *w = r_buffer.ptrw(); for (int i = 0; i < buffer_size; i++) w[i] = buffer[i]; return OK; } -Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) { +Error PacketPeer::put_packet_buffer(const Vector<uint8_t> &p_buffer) { int len = p_buffer.size(); if (len == 0) return OK; - PoolVector<uint8_t>::Read r = p_buffer.read(); + const uint8_t *r = p_buffer.ptr(); return put_packet(&r[0], len); } @@ -110,11 +110,11 @@ Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { encode_buffer.resize(next_power_of_2(len)); } - PoolVector<uint8_t>::Write w = encode_buffer.write(); - err = encode_variant(p_packet, w.ptr(), len, p_full_objects); + uint8_t *w = encode_buffer.ptrw(); + err = encode_variant(p_packet, w, len, p_full_objects); ERR_FAIL_COND_V_MSG(err != OK, err, "Error when trying to encode Variant."); - return put_packet(w.ptr(), len); + return put_packet(w, len); } Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { @@ -125,12 +125,12 @@ Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { return var; } -Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) { +Error PacketPeer::_put_packet(const Vector<uint8_t> &p_buffer) { return put_packet_buffer(p_buffer); } -PoolVector<uint8_t> PacketPeer::_get_packet() { +Vector<uint8_t> PacketPeer::_get_packet() { - PoolVector<uint8_t> raw; + Vector<uint8_t> raw; last_get_error = get_packet_buffer(raw); return raw; } diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index bee69f5ca9..62144259cc 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -43,14 +43,14 @@ class PacketPeer : public Reference { static void _bind_methods(); - Error _put_packet(const PoolVector<uint8_t> &p_buffer); - PoolVector<uint8_t> _get_packet(); + Error _put_packet(const Vector<uint8_t> &p_buffer); + Vector<uint8_t> _get_packet(); Error _get_packet_error() const; mutable Error last_get_error; int encode_buffer_max_size; - PoolVector<uint8_t> encode_buffer; + Vector<uint8_t> encode_buffer; public: virtual int get_available_packet_count() const = 0; @@ -61,8 +61,8 @@ public: /* helpers / binders */ - virtual Error get_packet_buffer(PoolVector<uint8_t> &r_buffer); - virtual Error put_packet_buffer(const PoolVector<uint8_t> &p_buffer); + virtual Error get_packet_buffer(Vector<uint8_t> &r_buffer); + virtual Error put_packet_buffer(const Vector<uint8_t> &p_buffer); virtual Error get_var(Variant &r_variant, bool p_allow_objects = false); virtual Error put_var(const Variant &p_packet, bool p_full_objects = false); diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp new file mode 100644 index 0000000000..01218a6881 --- /dev/null +++ b/core/io/packet_peer_dtls.cpp @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* packet_peer_dtls.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "packet_peer_dtls.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" + +PacketPeerDTLS *(*PacketPeerDTLS::_create)() = NULL; +bool PacketPeerDTLS::available = false; + +PacketPeerDTLS *PacketPeerDTLS::create() { + + return _create(); +} + +bool PacketPeerDTLS::is_available() { + return available; +} + +void PacketPeerDTLS::_bind_methods() { + + ClassDB::bind_method(D_METHOD("poll"), &PacketPeerDTLS::poll); + ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "validate_certs", "for_hostname", "valid_certificate"), &PacketPeerDTLS::connect_to_peer, DEFVAL(true), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("get_status"), &PacketPeerDTLS::get_status); + ClassDB::bind_method(D_METHOD("disconnect_from_peer"), &PacketPeerDTLS::disconnect_from_peer); + + BIND_ENUM_CONSTANT(STATUS_DISCONNECTED); + BIND_ENUM_CONSTANT(STATUS_HANDSHAKING); + BIND_ENUM_CONSTANT(STATUS_CONNECTED); + BIND_ENUM_CONSTANT(STATUS_ERROR); + BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH); +} + +PacketPeerDTLS::PacketPeerDTLS() { +} diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h new file mode 100644 index 0000000000..4f9f4535bc --- /dev/null +++ b/core/io/packet_peer_dtls.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* packet_peer_dtls.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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. */ +/*************************************************************************/ + +#ifndef PACKET_PEER_DTLS_H +#define PACKET_PEER_DTLS_H + +#include "core/crypto/crypto.h" +#include "core/io/packet_peer_udp.h" + +class PacketPeerDTLS : public PacketPeer { + GDCLASS(PacketPeerDTLS, PacketPeer); + +protected: + static PacketPeerDTLS *(*_create)(); + static void _bind_methods(); + + static bool available; + +public: + enum Status { + STATUS_DISCONNECTED, + STATUS_HANDSHAKING, + STATUS_CONNECTED, + STATUS_ERROR, + STATUS_ERROR_HOSTNAME_MISMATCH + }; + + virtual void poll() = 0; + virtual Error connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs = true, const String &p_for_hostname = String(), Ref<X509Certificate> p_ca_certs = Ref<X509Certificate>()) = 0; + virtual void disconnect_from_peer() = 0; + virtual Status get_status() const = 0; + + static PacketPeerDTLS *create(); + static bool is_available(); + + PacketPeerDTLS(); +}; + +VARIANT_ENUM_CAST(PacketPeerDTLS::Status); + +#endif // PACKET_PEER_DTLS_H diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index a8cfd741bb..f800ffc3db 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -133,7 +133,11 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { } do { - err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + if (connected) { + err = _sock->send(p_buffer, p_buffer_size, sent); + } else { + err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); + } if (err != OK) { if (err != ERR_BUSY) return FAILED; @@ -184,12 +188,69 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_ return OK; } +Error PacketPeerUDP::connect_socket(Ref<NetSocket> p_sock) { + Error err; + int read = 0; + uint16_t r_port; + IP_Address r_ip; + + err = p_sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, r_ip, r_port, true); + ERR_FAIL_COND_V(err != OK, err); + err = p_sock->connect_to_host(r_ip, r_port); + ERR_FAIL_COND_V(err != OK, err); + _sock = p_sock; + peer_addr = r_ip; + peer_port = r_port; + packet_ip = peer_addr; + packet_port = peer_port; + connected = true; + return OK; +} + +Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) { + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); + + Error err; + + if (!_sock->is_open()) { + IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + err = _sock->open(NetSocket::TYPE_UDP, ip_type); + ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN); + _sock->set_blocking_enabled(false); + } + + err = _sock->connect_to_host(p_host, p_port); + + // I see no reason why we should get ERR_BUSY (wouldblock/eagain) here. + // This is UDP, so connect is only used to tell the OS to which socket + // it shuold deliver packets when multiple are bound on the same address/port. + if (err != OK) { + close(); + ERR_FAIL_V_MSG(FAILED, "Unable to connect"); + } + + connected = true; + + peer_addr = p_host; + peer_port = p_port; + + // Flush any packet we might still have in queue. + rb.clear(); + return OK; +} + +bool PacketPeerUDP::is_connected_to_host() const { + return connected; +} + void PacketPeerUDP::close() { if (_sock.is_valid()) _sock->close(); rb.resize(16); queue_count = 0; + connected = false; } Error PacketPeerUDP::wait() { @@ -212,7 +273,13 @@ Error PacketPeerUDP::_poll() { uint16_t port; while (true) { - err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + if (connected) { + err = _sock->recv(recv_buffer, sizeof(recv_buffer), read); + ip = peer_addr; + port = peer_port; + } else { + err = _sock->recvfrom(recv_buffer, sizeof(recv_buffer), read, ip, port); + } if (err != OK) { if (err == ERR_BUSY) @@ -254,6 +321,7 @@ int PacketPeerUDP::get_packet_port() const { void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) { + ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets"); peer_addr = p_address; peer_port = p_port; } @@ -264,6 +332,8 @@ void PacketPeerUDP::_bind_methods() { ClassDB::bind_method(D_METHOD("close"), &PacketPeerUDP::close); ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("is_listening"), &PacketPeerUDP::is_listening); + ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host); + ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host); ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip); ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port); ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address); @@ -276,6 +346,7 @@ PacketPeerUDP::PacketPeerUDP() : packet_port(0), queue_count(0), peer_port(0), + connected(false), blocking(true), broadcast(false), _sock(Ref<NetSocket>(NetSocket::create())) { diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 15b4d00c37..b5a9fc9ec3 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -52,6 +52,7 @@ protected: IP_Address peer_addr; int peer_port; + bool connected; bool blocking; bool broadcast; Ref<NetSocket> _sock; @@ -70,6 +71,11 @@ public: void close(); Error wait(); bool is_listening() const; + + Error connect_socket(Ref<NetSocket> p_sock); // Used by UDPServer + Error connect_to_host(const IP_Address &p_host, int p_port); + bool is_connected_to_host() const; + IP_Address get_packet_address() const; int get_packet_port() const; void set_dest_address(const IP_Address &p_address, int p_port); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 02ae5788fc..8c343a0f43 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -46,7 +46,7 @@ enum { VARIANT_NIL = 1, VARIANT_BOOL = 2, VARIANT_INT = 3, - VARIANT_REAL = 4, + VARIANT_FLOAT = 4, VARIANT_STRING = 5, VARIANT_VECTOR2 = 10, VARIANT_RECT2 = 11, @@ -65,14 +65,22 @@ enum { VARIANT_DICTIONARY = 26, VARIANT_ARRAY = 30, VARIANT_RAW_ARRAY = 31, - VARIANT_INT_ARRAY = 32, - VARIANT_REAL_ARRAY = 33, + VARIANT_INT32_ARRAY = 32, + VARIANT_FLOAT32_ARRAY = 33, VARIANT_STRING_ARRAY = 34, VARIANT_VECTOR3_ARRAY = 35, VARIANT_COLOR_ARRAY = 36, VARIANT_VECTOR2_ARRAY = 37, VARIANT_INT64 = 40, VARIANT_DOUBLE = 41, + VARIANT_CALLABLE = 42, + VARIANT_SIGNAL = 43, + VARIANT_STRING_NAME = 44, + VARIANT_VECTOR2I = 45, + VARIANT_RECT2I = 46, + VARIANT_VECTOR3I = 47, + VARIANT_INT64_ARRAY = 48, + VARIANT_FLOAT64_ARRAY = 49, OBJECT_EMPTY = 0, OBJECT_EXTERNAL_RESOURCE = 1, OBJECT_INTERNAL_RESOURCE = 2, @@ -136,7 +144,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { r_v = int64_t(f->get_64()); } break; - case VARIANT_REAL: { + case VARIANT_FLOAT: { r_v = f->get_real(); } break; @@ -156,6 +164,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; + case VARIANT_VECTOR2I: { + + Vector2i v; + v.x = f->get_32(); + v.y = f->get_32(); + r_v = v; + + } break; case VARIANT_RECT2: { Rect2 v; @@ -166,6 +182,16 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; + case VARIANT_RECT2I: { + + Rect2i v; + v.position.x = f->get_32(); + v.position.y = f->get_32(); + v.size.x = f->get_32(); + v.size.y = f->get_32(); + r_v = v; + + } break; case VARIANT_VECTOR3: { Vector3 v; @@ -174,6 +200,14 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { v.z = f->get_real(); r_v = v; } break; + case VARIANT_VECTOR3I: { + + Vector3i v; + v.x = f->get_32(); + v.y = f->get_32(); + v.z = f->get_32(); + r_v = v; + } break; case VARIANT_PLANE: { Plane v; @@ -258,6 +292,10 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; + case VARIANT_STRING_NAME: { + + r_v = StringName(get_unicode_string()); + } break; case VARIANT_NODE_PATH: { @@ -363,6 +401,15 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } } break; + case VARIANT_CALLABLE: { + + r_v = Callable(); + } break; + case VARIANT_SIGNAL: { + + r_v = Signal(); + } break; + case VARIANT_DICTIONARY: { uint32_t len = f->get_32(); @@ -398,23 +445,23 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<uint8_t> array; + Vector<uint8_t> array; array.resize(len); - PoolVector<uint8_t>::Write w = array.write(); - f->get_buffer(w.ptr(), len); + uint8_t *w = array.ptrw(); + f->get_buffer(w, len); _advance_padding(len); - w.release(); + r_v = array; } break; - case VARIANT_INT_ARRAY: { + case VARIANT_INT32_ARRAY: { uint32_t len = f->get_32(); - PoolVector<int> array; + Vector<int32_t> array; array.resize(len); - PoolVector<int>::Write w = array.write(); - f->get_buffer((uint8_t *)w.ptr(), len * 4); + int32_t *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * sizeof(int32_t)); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -425,17 +472,38 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } #endif - w.release(); + r_v = array; } break; - case VARIANT_REAL_ARRAY: { + case VARIANT_INT64_ARRAY: { uint32_t len = f->get_32(); - PoolVector<real_t> array; + Vector<int64_t> array; array.resize(len); - PoolVector<real_t>::Write w = array.write(); - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t)); + int64_t *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * sizeof(int64_t)); +#ifdef BIG_ENDIAN_ENABLED + { + uint64_t *ptr = (uint64_t *)w.ptr(); + for (int i = 0; i < len; i++) { + + ptr[i] = BSWAP64(ptr[i]); + } + } + +#endif + + r_v = array; + } break; + case VARIANT_FLOAT32_ARRAY: { + + uint32_t len = f->get_32(); + + Vector<float> array; + array.resize(len); + float *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * sizeof(float)); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -447,18 +515,38 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { #endif - w.release(); + r_v = array; + } break; + case VARIANT_FLOAT64_ARRAY: { + + uint32_t len = f->get_32(); + + Vector<double> array; + array.resize(len); + double *w = array.ptrw(); + f->get_buffer((uint8_t *)w, len * sizeof(double)); +#ifdef BIG_ENDIAN_ENABLED + { + uint64_t *ptr = (uint64_t *)w.ptr(); + for (int i = 0; i < len; i++) { + + ptr[i] = BSWAP64(ptr[i]); + } + } + +#endif + r_v = array; } break; case VARIANT_STRING_ARRAY: { uint32_t len = f->get_32(); - PoolVector<String> array; + Vector<String> array; array.resize(len); - PoolVector<String>::Write w = array.write(); + String *w = array.ptrw(); for (uint32_t i = 0; i < len; i++) w[i] = get_unicode_string(); - w.release(); + r_v = array; } break; @@ -466,11 +554,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Vector2> array; + Vector<Vector2> array; array.resize(len); - PoolVector<Vector2>::Write w = array.write(); + Vector2 *w = array.ptrw(); if (sizeof(Vector2) == 8) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 2); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 2); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -485,7 +573,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector2 size is NOT 8!"); } - w.release(); + r_v = array; } break; @@ -493,11 +581,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(len); - PoolVector<Vector3>::Write w = array.write(); + Vector3 *w = array.ptrw(); if (sizeof(Vector3) == 12) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 3); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 3); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -512,7 +600,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector3 size is NOT 12!"); } - w.release(); + r_v = array; } break; @@ -520,11 +608,11 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { uint32_t len = f->get_32(); - PoolVector<Color> array; + Vector<Color> array; array.resize(len); - PoolVector<Color>::Write w = array.write(); + Color *w = array.ptrw(); if (sizeof(Color) == 16) { - f->get_buffer((uint8_t *)w.ptr(), len * sizeof(real_t) * 4); + f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 4); #ifdef BIG_ENDIAN_ENABLED { uint32_t *ptr = (uint32_t *)w.ptr(); @@ -539,7 +627,7 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) { } else { ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Color size is NOT 16!"); } - w.release(); + r_v = array; } break; default: { @@ -1249,7 +1337,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::REAL: { + case Variant::FLOAT: { double d = p_property; float fl = d; @@ -1258,7 +1346,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_double(d); } else { - f->store_32(VARIANT_REAL); + f->store_32(VARIANT_FLOAT); f->store_real(fl); } @@ -1278,6 +1366,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_real(val.y); } break; + case Variant::VECTOR2I: { + + f->store_32(VARIANT_VECTOR2I); + Vector2i val = p_property; + f->store_32(val.x); + f->store_32(val.y); + + } break; case Variant::RECT2: { f->store_32(VARIANT_RECT2); @@ -1288,6 +1384,16 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_real(val.size.y); } break; + case Variant::RECT2I: { + + f->store_32(VARIANT_RECT2I); + Rect2i val = p_property; + f->store_32(val.position.x); + f->store_32(val.position.y); + f->store_32(val.size.x); + f->store_32(val.size.y); + + } break; case Variant::VECTOR3: { f->store_32(VARIANT_VECTOR3); @@ -1297,6 +1403,15 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_real(val.z); } break; + case Variant::VECTOR3I: { + + f->store_32(VARIANT_VECTOR3I); + Vector3i val = p_property; + f->store_32(val.x); + f->store_32(val.y); + f->store_32(val.z); + + } break; case Variant::PLANE: { f->store_32(VARIANT_PLANE); @@ -1384,6 +1499,13 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_real(val.a); } break; + case Variant::STRING_NAME: { + + f->store_32(VARIANT_STRING_NAME); + String val = p_property; + save_unicode_string(f, val); + + } break; case Variant::NODE_PATH: { f->store_32(VARIANT_NODE_PATH); @@ -1441,6 +1563,17 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; + case Variant::CALLABLE: { + + f->store_32(VARIANT_CALLABLE); + WARN_PRINT("Can't save Callables."); + } break; + case Variant::SIGNAL: { + + f->store_32(VARIANT_SIGNAL); + WARN_PRINT("Can't save Signals."); + } break; + case Variant::DICTIONARY: { f->store_32(VARIANT_DICTIONARY); @@ -1473,59 +1606,82 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::POOL_BYTE_ARRAY: { + case Variant::PACKED_BYTE_ARRAY: { f->store_32(VARIANT_RAW_ARRAY); - PoolVector<uint8_t> arr = p_property; + Vector<uint8_t> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<uint8_t>::Read r = arr.read(); - f->store_buffer(r.ptr(), len); + const uint8_t *r = arr.ptr(); + f->store_buffer(r, len); _pad_buffer(f, len); } break; - case Variant::POOL_INT_ARRAY: { + case Variant::PACKED_INT32_ARRAY: { - f->store_32(VARIANT_INT_ARRAY); - PoolVector<int> arr = p_property; + f->store_32(VARIANT_INT32_ARRAY); + Vector<int32_t> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<int>::Read r = arr.read(); + const int32_t *r = arr.ptr(); for (int i = 0; i < len; i++) f->store_32(r[i]); } break; - case Variant::POOL_REAL_ARRAY: { + case Variant::PACKED_INT64_ARRAY: { - f->store_32(VARIANT_REAL_ARRAY); - PoolVector<real_t> arr = p_property; + f->store_32(VARIANT_INT64_ARRAY); + Vector<int64_t> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<real_t>::Read r = arr.read(); + const int64_t *r = arr.ptr(); + for (int i = 0; i < len; i++) + f->store_64(r[i]); + + } break; + case Variant::PACKED_FLOAT32_ARRAY: { + + f->store_32(VARIANT_FLOAT32_ARRAY); + Vector<float> arr = p_property; + int len = arr.size(); + f->store_32(len); + const float *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i]); } } break; - case Variant::POOL_STRING_ARRAY: { + case Variant::PACKED_FLOAT64_ARRAY: { + + f->store_32(VARIANT_FLOAT64_ARRAY); + Vector<double> arr = p_property; + int len = arr.size(); + f->store_32(len); + const double *r = arr.ptr(); + for (int i = 0; i < len; i++) { + f->store_double(r[i]); + } + + } break; + case Variant::PACKED_STRING_ARRAY: { f->store_32(VARIANT_STRING_ARRAY); - PoolVector<String> arr = p_property; + Vector<String> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<String>::Read r = arr.read(); + const String *r = arr.ptr(); for (int i = 0; i < len; i++) { save_unicode_string(f, r[i]); } } break; - case Variant::POOL_VECTOR3_ARRAY: { + case Variant::PACKED_VECTOR3_ARRAY: { f->store_32(VARIANT_VECTOR3_ARRAY); - PoolVector<Vector3> arr = p_property; + Vector<Vector3> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Vector3>::Read r = arr.read(); + const Vector3 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); @@ -1533,26 +1689,26 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::POOL_VECTOR2_ARRAY: { + case Variant::PACKED_VECTOR2_ARRAY: { f->store_32(VARIANT_VECTOR2_ARRAY); - PoolVector<Vector2> arr = p_property; + Vector<Vector2> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Vector2>::Read r = arr.read(); + const Vector2 *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].x); f->store_real(r[i].y); } } break; - case Variant::POOL_COLOR_ARRAY: { + case Variant::PACKED_COLOR_ARRAY: { f->store_32(VARIANT_COLOR_ARRAY); - PoolVector<Color> arr = p_property; + Vector<Color> arr = p_property; int len = arr.size(); f->store_32(len); - PoolVector<Color>::Read r = arr.read(); + const Color *r = arr.ptr(); for (int i = 0; i < len; i++) { f->store_real(r[i].r); f->store_real(r[i].g); diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 6877f816e1..39bbebefa6 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -157,10 +157,10 @@ bool ResourceFormatLoader::exists(const String &p_path) const { void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const { if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { - PoolStringArray exts = get_script_instance()->call("get_recognized_extensions"); + PackedStringArray exts = get_script_instance()->call("get_recognized_extensions"); { - PoolStringArray::Read r = exts.read(); + const String *r = exts.ptr(); for (int i = 0; i < exts.size(); ++i) { p_extensions->push_back(r[i]); } @@ -212,10 +212,10 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { if (get_script_instance() && get_script_instance()->has_method("get_dependencies")) { - PoolStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); + PackedStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); { - PoolStringArray::Read r = deps.read(); + const String *r = deps.ptr(); for (int i = 0; i < deps.size(); ++i) { p_dependencies->push_back(r[i]); } @@ -247,8 +247,8 @@ void ResourceFormatLoader::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), info); } - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING, "typename"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions")); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "handles_type", PropertyInfo(Variant::STRING_NAME, "typename"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type", PropertyInfo(Variant::STRING, "path"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "add_types"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "rename_dependencies", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "renames"))); @@ -743,7 +743,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem if (translation_remaps.has(p_path)) { // translation_remaps has the following format: - // { "res://path.png": PoolStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) } + // { "res://path.png": PackedStringArray( "res://path-ru.png:ru", "res://path-de.png:de" ) } // To find the path of the remapped resource, we extract the locale name after // the last ':' to match the project locale. @@ -905,10 +905,10 @@ 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"); + Vector<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(); + const String *r = remaps.ptr(); for (int i = 0; i < rc; i += 2) { diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 685d21107f..740aaf5cfa 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -61,10 +61,10 @@ bool ResourceFormatSaver::recognize(const RES &p_resource) const { void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { - PoolStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); + PackedStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); { - PoolStringArray::Read r = exts.read(); + const String *r = exts.ptr(); for (int i = 0; i < exts.size(); ++i) { p_extensions->push_back(r[i]); } @@ -81,7 +81,7 @@ void ResourceFormatSaver::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "save", arg0, arg1, arg2)); } - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::PACKED_STRING_ARRAY, "get_recognized_extensions", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "recognize", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"))); } diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index dee82de691..3c695c18fc 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -32,16 +32,16 @@ #include "core/io/marshalls.h" -Error StreamPeer::_put_data(const PoolVector<uint8_t> &p_data) { +Error StreamPeer::_put_data(const Vector<uint8_t> &p_data) { int len = p_data.size(); if (len == 0) return OK; - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); return put_data(&r[0], len); } -Array StreamPeer::_put_partial_data(const PoolVector<uint8_t> &p_data) { +Array StreamPeer::_put_partial_data(const Vector<uint8_t> &p_data) { Array ret; @@ -52,7 +52,7 @@ Array StreamPeer::_put_partial_data(const PoolVector<uint8_t> &p_data) { return ret; } - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); int sent; Error err = put_partial_data(&r[0], len, sent); @@ -68,18 +68,18 @@ Array StreamPeer::_get_data(int p_bytes) { Array ret; - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); - ret.push_back(PoolVector<uint8_t>()); + ret.push_back(Vector<uint8_t>()); return ret; } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); Error err = get_data(&w[0], p_bytes); - w.release(); + ret.push_back(err); ret.push_back(data); return ret; @@ -89,19 +89,18 @@ Array StreamPeer::_get_partial_data(int p_bytes) { Array ret; - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { ret.push_back(ERR_OUT_OF_MEMORY); - ret.push_back(PoolVector<uint8_t>()); + ret.push_back(Vector<uint8_t>()); return ret; } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); int received; Error err = get_partial_data(&w[0], p_bytes, received); - w.release(); if (err != OK) { data.resize(0); @@ -431,7 +430,7 @@ void StreamPeerBuffer::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &StreamPeerBuffer::clear); ClassDB::bind_method(D_METHOD("duplicate"), &StreamPeerBuffer::duplicate); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data_array"), "set_data_array", "get_data_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data_array"), "set_data_array", "get_data_array"); } Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { @@ -443,7 +442,7 @@ Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { data.resize(pointer + p_bytes); } - PoolVector<uint8_t>::Write w = data.write(); + uint8_t *w = data.ptrw(); copymem(&w[pointer], p_data, p_bytes); pointer += p_bytes; @@ -478,8 +477,8 @@ Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_ r_received = p_bytes; } - PoolVector<uint8_t>::Read r = data.read(); - copymem(p_buffer, r.ptr() + pointer, r_received); + const uint8_t *r = data.ptr(); + copymem(p_buffer, r + pointer, r_received); pointer += r_received; // FIXME: return what? OK or ERR_* @@ -513,13 +512,13 @@ void StreamPeerBuffer::resize(int p_size) { data.resize(p_size); } -void StreamPeerBuffer::set_data_array(const PoolVector<uint8_t> &p_data) { +void StreamPeerBuffer::set_data_array(const Vector<uint8_t> &p_data) { data = p_data; pointer = 0; } -PoolVector<uint8_t> StreamPeerBuffer::get_data_array() const { +Vector<uint8_t> StreamPeerBuffer::get_data_array() const { return data; } diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index d6ce7ddc16..9358a2c07c 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -41,8 +41,8 @@ protected: static void _bind_methods(); //bind helpers - Error _put_data(const PoolVector<uint8_t> &p_data); - Array _put_partial_data(const PoolVector<uint8_t> &p_data); + Error _put_data(const Vector<uint8_t> &p_data); + Array _put_partial_data(const Vector<uint8_t> &p_data); Array _get_data(int p_bytes); Array _get_partial_data(int p_bytes); @@ -96,7 +96,7 @@ class StreamPeerBuffer : public StreamPeer { GDCLASS(StreamPeerBuffer, StreamPeer); - PoolVector<uint8_t> data; + Vector<uint8_t> data; int pointer; protected: @@ -116,8 +116,8 @@ public: int get_position() const; void resize(int p_size); - void set_data_array(const PoolVector<uint8_t> &p_data); - PoolVector<uint8_t> get_data_array() const; + void set_data_array(const Vector<uint8_t> &p_data); + Vector<uint8_t> get_data_array() const; void clear(); diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp new file mode 100644 index 0000000000..16b7863cdd --- /dev/null +++ b/core/io/udp_server.cpp @@ -0,0 +1,119 @@ +/*************************************************************************/ +/* udp_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "udp_server.h" + +void UDPServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &UDPServer::listen, DEFVAL("*")); + ClassDB::bind_method(D_METHOD("is_connection_available"), &UDPServer::is_connection_available); + ClassDB::bind_method(D_METHOD("is_listening"), &UDPServer::is_listening); + ClassDB::bind_method(D_METHOD("take_connection"), &UDPServer::take_connection); + ClassDB::bind_method(D_METHOD("stop"), &UDPServer::stop); +} + +Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) { + + ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); + ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); + + Error err; + IP::Type ip_type = IP::TYPE_ANY; + + if (p_bind_address.is_valid()) + ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + + err = _sock->open(NetSocket::TYPE_UDP, ip_type); + + if (err != OK) + return ERR_CANT_CREATE; + + _sock->set_blocking_enabled(false); + _sock->set_reuse_address_enabled(true); + err = _sock->bind(p_bind_address, p_port); + + if (err != OK) { + stop(); + return err; + } + bind_address = p_bind_address; + bind_port = p_port; + return OK; +} + +bool UDPServer::is_listening() const { + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + return _sock->is_open(); +} + +bool UDPServer::is_connection_available() const { + + ERR_FAIL_COND_V(!_sock.is_valid(), false); + + if (!_sock->is_open()) + return false; + + Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); + return (err == OK); +} + +Ref<PacketPeerUDP> UDPServer::take_connection() { + + Ref<PacketPeerUDP> conn; + if (!is_connection_available()) { + return conn; + } + + conn = Ref<PacketPeerUDP>(memnew(PacketPeerUDP)); + conn->connect_socket(_sock); + _sock = Ref<NetSocket>(NetSocket::create()); + listen(bind_port, bind_address); + return conn; +} + +void UDPServer::stop() { + + if (_sock.is_valid()) { + _sock->close(); + } + bind_port = 0; + bind_address = IP_Address(); +} + +UDPServer::UDPServer() : + _sock(Ref<NetSocket>(NetSocket::create())) { +} + +UDPServer::~UDPServer() { + + stop(); +} diff --git a/core/io/udp_server.h b/core/io/udp_server.h new file mode 100644 index 0000000000..90bb82b62b --- /dev/null +++ b/core/io/udp_server.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* udp_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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. */ +/*************************************************************************/ + +#ifndef UDP_SERVER_H +#define UDP_SERVER_H + +#include "core/io/net_socket.h" +#include "core/io/packet_peer_udp.h" + +class UDPServer : public Reference { + GDCLASS(UDPServer, Reference); + +protected: + static void _bind_methods(); + int bind_port; + IP_Address bind_address; + Ref<NetSocket> _sock; + +public: + Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*")); + bool is_listening() const; + bool is_connection_available() const; + Ref<PacketPeerUDP> take_connection(); + + void stop(); + + UDPServer(); + ~UDPServer(); +}; + +#endif // UDP_SERVER_H |