Skip to content
This repository was archived by the owner on Sep 3, 2022. It is now read-only.

Commit d219547

Browse files
committed
[Net] New replication interface, spawner and synchronizer nodes.
Initial implementation of the MultiplayerReplicationInterface and its default implementation (SceneReplicationInterface). New MultiplayerSpawner node helps dealing with instantiation of scenes on remote peers (e.g. clients). It supports both custom spawns via a `_spawn_custom` virtual function, and optional auto-spawn of known scenes via a TypedArray<PackedScenes> property. New MultiplayerSynchornizer helps synchronizing states between the local and remote peers, supports both sync and spawn properties and is configured via a `SceneReplicationConfig` resource. It can also sync via path (i.e. without being spawned by a MultiplayerSpawner if both peers has it in tree, but will not send the spawn state in that case, only the sync one.
1 parent 2e320dc commit d219547

29 files changed

+2011
-1212
lines changed

core/multiplayer/multiplayer_api.cpp

+107-26
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
#include "core/debugger/engine_debugger.h"
3434
#include "core/io/marshalls.h"
35-
#include "core/multiplayer/multiplayer_replicator.h"
3635
#include "core/multiplayer/rpc_manager.h"
3736
#include "scene/main/node.h"
3837

@@ -42,6 +41,8 @@
4241
#include "core/os/os.h"
4342
#endif
4443

44+
MultiplayerReplicationInterface *(*MultiplayerAPI::create_default_replication_interface)(MultiplayerAPI *p_multiplayer) = nullptr;
45+
4546
#ifdef DEBUG_ENABLED
4647
void MultiplayerAPI::profile_bandwidth(const String &p_inout, int p_size) {
4748
if (EngineDebugger::is_profiling("multiplayer")) {
@@ -74,24 +75,21 @@ void MultiplayerAPI::poll() {
7475
Error err = multiplayer_peer->get_packet(&packet, len);
7576
if (err != OK) {
7677
ERR_PRINT("Error getting packet!");
77-
break; // Something is wrong!
78+
return; // Something is wrong!
7879
}
7980

8081
remote_sender_id = sender;
8182
_process_packet(sender, packet, len);
8283
remote_sender_id = 0;
8384

8485
if (!multiplayer_peer.is_valid()) {
85-
break; // It's also possible that a packet or RPC caused a disconnection, so also check here.
86+
return; // It's also possible that a packet or RPC caused a disconnection, so also check here.
8687
}
8788
}
88-
if (multiplayer_peer.is_valid() && multiplayer_peer->get_connection_status() == MultiplayerPeer::CONNECTION_CONNECTED) {
89-
replicator->poll();
90-
}
89+
replicator->on_network_process();
9190
}
9291

9392
void MultiplayerAPI::clear() {
94-
replicator->clear();
9593
connected_peers.clear();
9694
path_get_cache.clear();
9795
path_send_cache.clear();
@@ -133,6 +131,7 @@ void MultiplayerAPI::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) {
133131
multiplayer_peer->connect("connection_failed", callable_mp(this, &MultiplayerAPI::_connection_failed));
134132
multiplayer_peer->connect("server_disconnected", callable_mp(this, &MultiplayerAPI::_server_disconnected));
135133
}
134+
replicator->on_reset();
136135
}
137136

138137
Ref<MultiplayerPeer> MultiplayerAPI::get_multiplayer_peer() const {
@@ -167,13 +166,13 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
167166
_process_raw(p_from, p_packet, p_packet_len);
168167
} break;
169168
case NETWORK_COMMAND_SPAWN: {
170-
replicator->process_spawn_despawn(p_from, p_packet, p_packet_len, true);
169+
replicator->on_spawn_receive(p_from, p_packet, p_packet_len);
171170
} break;
172171
case NETWORK_COMMAND_DESPAWN: {
173-
replicator->process_spawn_despawn(p_from, p_packet, p_packet_len, false);
172+
replicator->on_despawn_receive(p_from, p_packet, p_packet_len);
174173
} break;
175174
case NETWORK_COMMAND_SYNC: {
176-
replicator->process_sync(p_from, p_packet, p_packet_len);
175+
replicator->on_sync_receive(p_from, p_packet, p_packet_len);
177176
} break;
178177
}
179178
}
@@ -324,7 +323,7 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
324323
#define ENCODE_16 1 << 5
325324
#define ENCODE_32 2 << 5
326325
#define ENCODE_64 3 << 5
327-
Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {
326+
Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
328327
// Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
329328
CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
330329

@@ -385,7 +384,7 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint
385384
} break;
386385
default:
387386
// Any other case is not yet compressed.
388-
Error err = encode_variant(p_variant, r_buffer, r_len, allow_object_decoding);
387+
Error err = encode_variant(p_variant, r_buffer, r_len, p_allow_object_decoding);
389388
if (err != OK) {
390389
return err;
391390
}
@@ -399,7 +398,7 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint
399398
return OK;
400399
}
401400

402-
Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) {
401+
Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding) {
403402
const uint8_t *buf = p_buffer;
404403
int len = p_len;
405404

@@ -458,7 +457,7 @@ Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const ui
458457
}
459458
} break;
460459
default:
461-
Error err = decode_variant(r_variant, p_buffer, p_len, r_len, allow_object_decoding);
460+
Error err = decode_variant(r_variant, p_buffer, p_len, r_len, p_allow_object_decoding);
462461
if (err != OK) {
463462
return err;
464463
}
@@ -467,17 +466,84 @@ Error MultiplayerAPI::decode_and_decompress_variant(Variant &r_variant, const ui
467466
return OK;
468467
}
469468

469+
Error MultiplayerAPI::encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw, bool p_allow_object_decoding) {
470+
r_len = 0;
471+
int size = 0;
472+
473+
if (p_count == 0) {
474+
if (r_raw) {
475+
*r_raw = true;
476+
}
477+
return OK;
478+
}
479+
480+
// Try raw encoding optimization.
481+
if (r_raw && p_count == 1) {
482+
*r_raw = false;
483+
const Variant &v = *(p_variants[0]);
484+
if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
485+
*r_raw = true;
486+
const PackedByteArray pba = v;
487+
if (p_buffer) {
488+
memcpy(p_buffer, pba.ptr(), pba.size());
489+
}
490+
r_len += pba.size();
491+
} else {
492+
encode_and_compress_variant(v, p_buffer, size, p_allow_object_decoding);
493+
r_len += size;
494+
}
495+
return OK;
496+
}
497+
498+
// Regular encoding.
499+
for (int i = 0; i < p_count; i++) {
500+
const Variant &v = *(p_variants[i]);
501+
encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size, p_allow_object_decoding);
502+
r_len += size;
503+
}
504+
return OK;
505+
}
506+
507+
Error MultiplayerAPI::decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw, bool p_allow_object_decoding) {
508+
r_len = 0;
509+
int argc = r_variants.size();
510+
if (argc == 0 && p_raw) {
511+
return OK;
512+
}
513+
ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
514+
if (p_raw) {
515+
r_len = p_len;
516+
PackedByteArray pba;
517+
pba.resize(p_len);
518+
memcpy(pba.ptrw(), p_buffer, p_len);
519+
r_variants.write[0] = pba;
520+
return OK;
521+
}
522+
523+
Vector<Variant> args;
524+
Vector<const Variant *> argp;
525+
args.resize(argc);
526+
527+
for (int i = 0; i < argc; i++) {
528+
ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
529+
530+
int vlen;
531+
Error err = MultiplayerAPI::decode_and_decompress_variant(r_variants.write[i], &p_buffer[r_len], p_len - r_len, &vlen, p_allow_object_decoding);
532+
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
533+
r_len += vlen;
534+
}
535+
return OK;
536+
}
537+
470538
void MultiplayerAPI::_add_peer(int p_id) {
471539
connected_peers.insert(p_id);
472540
path_get_cache.insert(p_id, PathGetCache());
473-
if (is_server()) {
474-
replicator->spawn_all(p_id);
475-
}
541+
replicator->on_peer_change(p_id, true);
476542
emit_signal(SNAME("peer_connected"), p_id);
477543
}
478544

479545
void MultiplayerAPI::_del_peer(int p_id) {
480-
connected_peers.erase(p_id);
546+
replicator->on_peer_change(p_id, false);
481547
// Cleanup get cache.
482548
path_get_cache.erase(p_id);
483549
// Cleanup sent cache.
@@ -488,6 +554,7 @@ void MultiplayerAPI::_del_peer(int p_id) {
488554
PathSentCache *psc = path_send_cache.getptr(E);
489555
psc->confirmed_peers.erase(p_id);
490556
}
557+
connected_peers.erase(p_id);
491558
emit_signal(SNAME("peer_disconnected"), p_id);
492559
}
493560

@@ -500,6 +567,7 @@ void MultiplayerAPI::_connection_failed() {
500567
}
501568

502569
void MultiplayerAPI::_server_disconnected() {
570+
replicator->on_reset();
503571
emit_signal(SNAME("server_disconnected"));
504572
}
505573

@@ -612,14 +680,26 @@ bool MultiplayerAPI::is_object_decoding_allowed() const {
612680
return allow_object_decoding;
613681
}
614682

615-
void MultiplayerAPI::scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter) {
616-
replicator->scene_enter_exit_notify(p_scene, p_node, p_enter);
617-
}
618-
619683
void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) {
620684
rpc_manager->rpcp(p_node, p_peer_id, p_method, p_arg, p_argcount);
621685
}
622686

687+
Error MultiplayerAPI::spawn(Object *p_object, Variant p_config) {
688+
return replicator->on_spawn(p_object, p_config);
689+
}
690+
691+
Error MultiplayerAPI::despawn(Object *p_object, Variant p_config) {
692+
return replicator->on_despawn(p_object, p_config);
693+
}
694+
695+
Error MultiplayerAPI::replication_start(Object *p_object, Variant p_config) {
696+
return replicator->on_replication_start(p_object, p_config);
697+
}
698+
699+
Error MultiplayerAPI::replication_stop(Object *p_object, Variant p_config) {
700+
return replicator->on_replication_stop(p_object, p_config);
701+
}
702+
623703
void MultiplayerAPI::_bind_methods() {
624704
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
625705
ClassDB::bind_method(D_METHOD("get_root_node"), &MultiplayerAPI::get_root_node);
@@ -638,14 +718,12 @@ void MultiplayerAPI::_bind_methods() {
638718
ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &MultiplayerAPI::is_refusing_new_connections);
639719
ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
640720
ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
641-
ClassDB::bind_method(D_METHOD("get_replicator"), &MultiplayerAPI::get_replicator);
642721

643722
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
644723
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
645724
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer_peer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerPeer", PROPERTY_USAGE_NONE), "set_multiplayer_peer", "get_multiplayer_peer");
646725
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_node", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_root_node", "get_root_node");
647726
ADD_PROPERTY_DEFAULT("refuse_new_connections", false);
648-
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "replicator", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerReplicator", PROPERTY_USAGE_NONE), "", "get_replicator");
649727

650728
ADD_SIGNAL(MethodInfo("peer_connected", PropertyInfo(Variant::INT, "id")));
651729
ADD_SIGNAL(MethodInfo("peer_disconnected", PropertyInfo(Variant::INT, "id")));
@@ -656,13 +734,16 @@ void MultiplayerAPI::_bind_methods() {
656734
}
657735

658736
MultiplayerAPI::MultiplayerAPI() {
659-
replicator = memnew(MultiplayerReplicator(this));
737+
if (create_default_replication_interface) {
738+
replicator = Ref<MultiplayerReplicationInterface>(create_default_replication_interface(this));
739+
} else {
740+
replicator.instantiate();
741+
}
660742
rpc_manager = memnew(RPCManager(this));
661743
clear();
662744
}
663745

664746
MultiplayerAPI::~MultiplayerAPI() {
665747
clear();
666-
memdelete(replicator);
667748
memdelete(rpc_manager);
668749
}

core/multiplayer/multiplayer_api.h

+33-8
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,26 @@
3535
#include "core/multiplayer/multiplayer_peer.h"
3636
#include "core/object/ref_counted.h"
3737

38-
class MultiplayerReplicator;
38+
class MultiplayerAPI;
39+
40+
class MultiplayerReplicationInterface : public RefCounted {
41+
GDCLASS(MultiplayerReplicationInterface, RefCounted);
42+
43+
public:
44+
virtual void on_peer_change(int p_id, bool p_connected) {}
45+
virtual void on_reset() {}
46+
virtual Error on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
47+
virtual Error on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
48+
virtual Error on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) { return ERR_UNAVAILABLE; }
49+
virtual Error on_spawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
50+
virtual Error on_despawn(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
51+
virtual Error on_replication_start(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
52+
virtual Error on_replication_stop(Object *p_obj, Variant p_config) { return ERR_UNAVAILABLE; }
53+
virtual void on_network_process() {}
54+
55+
MultiplayerReplicationInterface() {}
56+
};
57+
3958
class RPCManager;
4059

4160
class MultiplayerAPI : public RefCounted {
@@ -95,7 +114,7 @@ class MultiplayerAPI : public RefCounted {
95114
Node *root_node = nullptr;
96115
bool allow_object_decoding = false;
97116

98-
MultiplayerReplicator *replicator = nullptr;
117+
Ref<MultiplayerReplicationInterface> replicator;
99118
RPCManager *rpc_manager = nullptr;
100119

101120
protected:
@@ -108,6 +127,13 @@ class MultiplayerAPI : public RefCounted {
108127
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
109128

110129
public:
130+
static MultiplayerReplicationInterface *(*create_default_replication_interface)(MultiplayerAPI *p_multiplayer);
131+
132+
static Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len, bool p_allow_object_decoding);
133+
static Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_object_decoding);
134+
static Error encode_and_compress_variants(const Variant **p_variants, int p_count, uint8_t *p_buffer, int &r_len, bool *r_raw = nullptr, bool p_allow_object_decoding = false);
135+
static Error decode_and_decompress_variants(Vector<Variant> &r_variants, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw = false, bool p_allow_object_decoding = false);
136+
111137
void poll();
112138
void clear();
113139
void set_root_node(Node *p_node);
@@ -117,13 +143,13 @@ class MultiplayerAPI : public RefCounted {
117143

118144
Error send_bytes(Vector<uint8_t> p_data, int p_to = MultiplayerPeer::TARGET_PEER_BROADCAST, Multiplayer::TransferMode p_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0);
119145

120-
Error encode_and_compress_variant(const Variant &p_variant, uint8_t *p_buffer, int &r_len);
121-
Error decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len);
122-
123146
// Called by Node.rpc
124147
void rpcp(Node *p_node, int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
125-
// Called by Node._notification
126-
void scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter);
148+
// Replication API
149+
Error spawn(Object *p_object, Variant p_config);
150+
Error despawn(Object *p_object, Variant p_config);
151+
Error replication_start(Object *p_object, Variant p_config);
152+
Error replication_stop(Object *p_object, Variant p_config);
127153
// Called by replicator
128154
bool send_confirm_path(Node *p_node, NodePath p_path, int p_target, int &p_id);
129155
Node *get_cached_node(int p_from, uint32_t p_node_id);
@@ -148,7 +174,6 @@ class MultiplayerAPI : public RefCounted {
148174
void set_allow_object_decoding(bool p_enable);
149175
bool is_object_decoding_allowed() const;
150176

151-
MultiplayerReplicator *get_replicator() const { return replicator; }
152177
RPCManager *get_rpc_manager() const { return rpc_manager; }
153178

154179
#ifdef DEBUG_ENABLED

0 commit comments

Comments
 (0)