summaryrefslogtreecommitdiff
path: root/core/io
diff options
context:
space:
mode:
Diffstat (limited to 'core/io')
-rw-r--r--core/io/config_file.cpp8
-rw-r--r--core/io/config_file.h4
-rw-r--r--core/io/dtls_server.cpp54
-rw-r--r--core/io/dtls_server.h57
-rw-r--r--core/io/file_access_buffered.cpp4
-rw-r--r--core/io/file_access_buffered.h2
-rw-r--r--core/io/file_access_buffered_fa.h4
-rw-r--r--core/io/http_client.cpp26
-rw-r--r--core/io/http_client.h6
-rw-r--r--core/io/json.cpp10
-rw-r--r--core/io/marshalls.cpp281
-rw-r--r--core/io/multiplayer_api.cpp157
-rw-r--r--core/io/multiplayer_api.h2
-rw-r--r--core/io/net_socket.h2
-rw-r--r--core/io/packet_peer.cpp20
-rw-r--r--core/io/packet_peer.h10
-rw-r--r--core/io/packet_peer_dtls.cpp62
-rw-r--r--core/io/packet_peer_dtls.h68
-rw-r--r--core/io/packet_peer_udp.cpp75
-rw-r--r--core/io/packet_peer_udp.h6
-rw-r--r--core/io/resource_format_binary.cpp274
-rw-r--r--core/io/resource_loader.cpp18
-rw-r--r--core/io/resource_saver.cpp6
-rw-r--r--core/io/stream_peer.cpp35
-rw-r--r--core/io/stream_peer.h10
-rw-r--r--core/io/udp_server.cpp119
-rw-r--r--core/io/udp_server.h58
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