scene_replication_interface.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. /**************************************************************************/
  2. /* scene_replication_interface.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "scene_replication_interface.h"
  31. #include "scene_multiplayer.h"
  32. #include "core/debugger/engine_debugger.h"
  33. #include "core/io/marshalls.h"
  34. #include "scene/main/node.h"
  35. #include "scene/scene_string_names.h"
  36. #define MAKE_ROOM(m_amount) \
  37. if (packet_cache.size() < m_amount) \
  38. packet_cache.resize(m_amount);
  39. #ifdef DEBUG_ENABLED
  40. _FORCE_INLINE_ void SceneReplicationInterface::_profile_node_data(const String &p_what, ObjectID p_id, int p_size) {
  41. if (EngineDebugger::is_profiling("multiplayer:replication")) {
  42. Array values;
  43. values.push_back(p_what);
  44. values.push_back(p_id);
  45. values.push_back(p_size);
  46. EngineDebugger::profiler_add_frame_data("multiplayer:replication", values);
  47. }
  48. }
  49. #endif
  50. SceneReplicationInterface::TrackedNode &SceneReplicationInterface::_track(const ObjectID &p_id) {
  51. if (!tracked_nodes.has(p_id)) {
  52. tracked_nodes[p_id] = TrackedNode(p_id);
  53. Node *node = get_id_as<Node>(p_id);
  54. node->connect(SceneStringNames::get_singleton()->tree_exited, callable_mp(this, &SceneReplicationInterface::_untrack).bind(p_id), Node::CONNECT_ONE_SHOT);
  55. }
  56. return tracked_nodes[p_id];
  57. }
  58. void SceneReplicationInterface::_untrack(const ObjectID &p_id) {
  59. if (!tracked_nodes.has(p_id)) {
  60. return;
  61. }
  62. uint32_t net_id = tracked_nodes[p_id].net_id;
  63. uint32_t peer = tracked_nodes[p_id].remote_peer;
  64. tracked_nodes.erase(p_id);
  65. // If it was spawned by a remote, remove it from the received nodes.
  66. if (peer && peers_info.has(peer)) {
  67. peers_info[peer].recv_nodes.erase(net_id);
  68. }
  69. // If we spawned or synced it, we need to remove it from any peer it was sent to.
  70. if (net_id || peer == 0) {
  71. for (KeyValue<int, PeerInfo> &E : peers_info) {
  72. E.value.spawn_nodes.erase(p_id);
  73. }
  74. }
  75. }
  76. void SceneReplicationInterface::_free_remotes(const PeerInfo &p_info) {
  77. for (const KeyValue<uint32_t, ObjectID> &E : p_info.recv_nodes) {
  78. Node *node = tracked_nodes.has(E.value) ? get_id_as<Node>(E.value) : nullptr;
  79. ERR_CONTINUE(!node);
  80. node->queue_free();
  81. }
  82. }
  83. bool SceneReplicationInterface::_has_authority(const Node *p_node) {
  84. return multiplayer->has_multiplayer_peer() && p_node->get_multiplayer_authority() == multiplayer->get_unique_id();
  85. }
  86. void SceneReplicationInterface::on_peer_change(int p_id, bool p_connected) {
  87. if (p_connected) {
  88. peers_info[p_id] = PeerInfo();
  89. for (const ObjectID &oid : spawned_nodes) {
  90. _update_spawn_visibility(p_id, oid);
  91. }
  92. for (const ObjectID &oid : sync_nodes) {
  93. _update_sync_visibility(p_id, get_id_as<MultiplayerSynchronizer>(oid));
  94. }
  95. } else {
  96. ERR_FAIL_COND(!peers_info.has(p_id));
  97. _free_remotes(peers_info[p_id]);
  98. peers_info.erase(p_id);
  99. }
  100. }
  101. void SceneReplicationInterface::on_reset() {
  102. for (const KeyValue<int, PeerInfo> &E : peers_info) {
  103. _free_remotes(E.value);
  104. }
  105. peers_info.clear();
  106. // Tracked nodes are cleared on deletion, here we only reset the ids so they can be later re-assigned.
  107. for (KeyValue<ObjectID, TrackedNode> &E : tracked_nodes) {
  108. TrackedNode &tobj = E.value;
  109. tobj.net_id = 0;
  110. tobj.remote_peer = 0;
  111. }
  112. for (const ObjectID &oid : sync_nodes) {
  113. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(oid);
  114. ERR_CONTINUE(!sync);
  115. sync->reset();
  116. }
  117. last_net_id = 0;
  118. }
  119. void SceneReplicationInterface::on_network_process() {
  120. // Prevent endless stalling in case of unforeseen spawn errors.
  121. if (spawn_queue.size()) {
  122. ERR_PRINT("An error happened during last spawn, this usually means the 'ready' signal was not emitted by the spawned node.");
  123. for (const ObjectID &oid : spawn_queue) {
  124. Node *node = get_id_as<Node>(oid);
  125. ERR_CONTINUE(!node);
  126. if (node->is_connected(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready))) {
  127. node->disconnect(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready));
  128. }
  129. }
  130. spawn_queue.clear();
  131. }
  132. // Process syncs.
  133. uint64_t usec = OS::get_singleton()->get_ticks_usec();
  134. for (KeyValue<int, PeerInfo> &E : peers_info) {
  135. const HashSet<ObjectID> to_sync = E.value.sync_nodes;
  136. if (to_sync.is_empty()) {
  137. continue; // Nothing to sync
  138. }
  139. uint16_t sync_net_time = ++E.value.last_sent_sync;
  140. _send_sync(E.key, to_sync, sync_net_time, usec);
  141. _send_delta(E.key, to_sync, usec, E.value.last_watch_usecs);
  142. }
  143. }
  144. Error SceneReplicationInterface::on_spawn(Object *p_obj, Variant p_config) {
  145. Node *node = Object::cast_to<Node>(p_obj);
  146. ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
  147. MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
  148. ERR_FAIL_NULL_V(spawner, ERR_INVALID_PARAMETER);
  149. // Track node.
  150. const ObjectID oid = node->get_instance_id();
  151. TrackedNode &tobj = _track(oid);
  152. // Spawn state needs to be callected after "ready", but the spawn order follows "enter_tree".
  153. ERR_FAIL_COND_V(tobj.spawner != ObjectID(), ERR_ALREADY_IN_USE);
  154. tobj.spawner = spawner->get_instance_id();
  155. spawn_queue.insert(oid);
  156. node->connect(SceneStringNames::get_singleton()->ready, callable_mp(this, &SceneReplicationInterface::_node_ready).bind(oid), Node::CONNECT_ONE_SHOT);
  157. return OK;
  158. }
  159. void SceneReplicationInterface::_node_ready(const ObjectID &p_oid) {
  160. ERR_FAIL_COND(!spawn_queue.has(p_oid)); // Bug.
  161. // If we are a nested spawn, we need to wait until the parent is ready.
  162. if (p_oid != *(spawn_queue.begin())) {
  163. return;
  164. }
  165. for (const ObjectID &oid : spawn_queue) {
  166. ERR_CONTINUE(!tracked_nodes.has(oid));
  167. TrackedNode &tobj = tracked_nodes[oid];
  168. MultiplayerSpawner *spawner = get_id_as<MultiplayerSpawner>(tobj.spawner);
  169. ERR_CONTINUE(!spawner);
  170. spawned_nodes.insert(oid);
  171. if (_has_authority(spawner)) {
  172. _update_spawn_visibility(0, oid);
  173. }
  174. }
  175. spawn_queue.clear();
  176. }
  177. Error SceneReplicationInterface::on_despawn(Object *p_obj, Variant p_config) {
  178. Node *node = Object::cast_to<Node>(p_obj);
  179. ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
  180. MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(p_config.get_validated_object());
  181. ERR_FAIL_COND_V(!p_obj || !spawner, ERR_INVALID_PARAMETER);
  182. // Forcibly despawn to all peers that knowns me.
  183. int len = 0;
  184. Error err = _make_despawn_packet(node, len);
  185. ERR_FAIL_COND_V(err != OK, ERR_BUG);
  186. const ObjectID oid = p_obj->get_instance_id();
  187. for (const KeyValue<int, PeerInfo> &E : peers_info) {
  188. if (!E.value.spawn_nodes.has(oid)) {
  189. continue;
  190. }
  191. _send_raw(packet_cache.ptr(), len, E.key, true);
  192. }
  193. // Also remove spawner tracking from the replication state.
  194. ERR_FAIL_COND_V(!tracked_nodes.has(oid), ERR_INVALID_PARAMETER);
  195. TrackedNode &tobj = _track(oid);
  196. ERR_FAIL_COND_V(tobj.spawner != spawner->get_instance_id(), ERR_INVALID_PARAMETER);
  197. tobj.spawner = ObjectID();
  198. spawned_nodes.erase(oid);
  199. for (KeyValue<int, PeerInfo> &E : peers_info) {
  200. E.value.spawn_nodes.erase(oid);
  201. }
  202. return OK;
  203. }
  204. Error SceneReplicationInterface::on_replication_start(Object *p_obj, Variant p_config) {
  205. Node *node = Object::cast_to<Node>(p_obj);
  206. ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
  207. MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
  208. ERR_FAIL_NULL_V(sync, ERR_INVALID_PARAMETER);
  209. // Add to synchronizer list.
  210. TrackedNode &tobj = _track(p_obj->get_instance_id());
  211. const ObjectID sid = sync->get_instance_id();
  212. tobj.synchronizers.insert(sid);
  213. sync_nodes.insert(sid);
  214. // Update visibility.
  215. sync->connect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed).bind(sync->get_instance_id()));
  216. _update_sync_visibility(0, sync);
  217. if (pending_spawn == p_obj->get_instance_id() && sync->get_multiplayer_authority() == pending_spawn_remote) {
  218. // Try to apply synchronizer Net ID
  219. ERR_FAIL_COND_V_MSG(pending_sync_net_ids.is_empty(), ERR_INVALID_DATA, vformat("The MultiplayerSynchronizer at path \"%s\" is unable to process the pending spawn since it has no network ID. This might happen when changing the multiplayer authority during the \"_ready\" callback. Make sure to only change the authority of multiplayer synchronizers during \"_enter_tree\" or the \"_spawn_custom\" callback of their multiplayer spawner.", sync->get_path()));
  220. ERR_FAIL_COND_V(!peers_info.has(pending_spawn_remote), ERR_INVALID_DATA);
  221. uint32_t net_id = pending_sync_net_ids[0];
  222. pending_sync_net_ids.pop_front();
  223. peers_info[pending_spawn_remote].recv_sync_ids[net_id] = sync->get_instance_id();
  224. sync->set_net_id(net_id);
  225. // Try to apply spawn state (before ready).
  226. if (pending_buffer_size > 0) {
  227. ERR_FAIL_COND_V(!node || !sync->get_replication_config_ptr(), ERR_UNCONFIGURED);
  228. int consumed = 0;
  229. const List<NodePath> props = sync->get_replication_config_ptr()->get_spawn_properties();
  230. Vector<Variant> vars;
  231. vars.resize(props.size());
  232. Error err = MultiplayerAPI::decode_and_decompress_variants(vars, pending_buffer, pending_buffer_size, consumed);
  233. ERR_FAIL_COND_V(err, err);
  234. if (consumed > 0) {
  235. pending_buffer += consumed;
  236. pending_buffer_size -= consumed;
  237. err = MultiplayerSynchronizer::set_state(props, node, vars);
  238. ERR_FAIL_COND_V(err, err);
  239. }
  240. }
  241. }
  242. return OK;
  243. }
  244. Error SceneReplicationInterface::on_replication_stop(Object *p_obj, Variant p_config) {
  245. Node *node = Object::cast_to<Node>(p_obj);
  246. ERR_FAIL_COND_V(!node || p_config.get_type() != Variant::OBJECT, ERR_INVALID_PARAMETER);
  247. MultiplayerSynchronizer *sync = Object::cast_to<MultiplayerSynchronizer>(p_config.get_validated_object());
  248. ERR_FAIL_NULL_V(sync, ERR_INVALID_PARAMETER);
  249. sync->disconnect("visibility_changed", callable_mp(this, &SceneReplicationInterface::_visibility_changed));
  250. // Untrack synchronizer.
  251. const ObjectID oid = node->get_instance_id();
  252. const ObjectID sid = sync->get_instance_id();
  253. ERR_FAIL_COND_V(!tracked_nodes.has(oid), ERR_INVALID_PARAMETER);
  254. TrackedNode &tobj = _track(oid);
  255. tobj.synchronizers.erase(sid);
  256. sync_nodes.erase(sid);
  257. for (KeyValue<int, PeerInfo> &E : peers_info) {
  258. E.value.sync_nodes.erase(sid);
  259. E.value.last_watch_usecs.erase(sid);
  260. if (sync->get_net_id()) {
  261. E.value.recv_sync_ids.erase(sync->get_net_id());
  262. }
  263. }
  264. return OK;
  265. }
  266. void SceneReplicationInterface::_visibility_changed(int p_peer, ObjectID p_sid) {
  267. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(p_sid);
  268. ERR_FAIL_NULL(sync); // Bug.
  269. Node *node = sync->get_root_node();
  270. ERR_FAIL_NULL(node); // Bug.
  271. const ObjectID oid = node->get_instance_id();
  272. if (spawned_nodes.has(oid) && p_peer != multiplayer->get_unique_id()) {
  273. _update_spawn_visibility(p_peer, oid);
  274. }
  275. _update_sync_visibility(p_peer, sync);
  276. }
  277. bool SceneReplicationInterface::is_rpc_visible(const ObjectID &p_oid, int p_peer) const {
  278. if (!tracked_nodes.has(p_oid)) {
  279. return true; // Untracked nodes are always visible to RPCs.
  280. }
  281. ERR_FAIL_COND_V(p_peer < 0, false);
  282. const TrackedNode &tnode = tracked_nodes[p_oid];
  283. if (tnode.synchronizers.is_empty()) {
  284. return true; // No synchronizers means no visibility restrictions.
  285. }
  286. if (tnode.remote_peer && uint32_t(p_peer) == tnode.remote_peer) {
  287. return true; // RPCs on spawned nodes are always visible to spawner.
  288. } else if (spawned_nodes.has(p_oid)) {
  289. // It's a spawned node we control, this can be fast.
  290. if (p_peer) {
  291. return peers_info.has(p_peer) && peers_info[p_peer].spawn_nodes.has(p_oid);
  292. } else {
  293. for (const KeyValue<int, PeerInfo> &E : peers_info) {
  294. if (!E.value.spawn_nodes.has(p_oid)) {
  295. return false; // Not public.
  296. }
  297. }
  298. return true; // All peers have this node.
  299. }
  300. } else {
  301. // Cycle object synchronizers to check visibility.
  302. for (const ObjectID &sid : tnode.synchronizers) {
  303. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(sid);
  304. ERR_CONTINUE(!sync);
  305. // RPC visibility is composed using OR when multiple synchronizers are present.
  306. // Note that we don't really care about authority here which may lead to unexpected
  307. // results when using multiple synchronizers to control the same node.
  308. if (sync->is_visible_to(p_peer)) {
  309. return true;
  310. }
  311. }
  312. return false; // Not visible.
  313. }
  314. }
  315. Error SceneReplicationInterface::_update_sync_visibility(int p_peer, MultiplayerSynchronizer *p_sync) {
  316. ERR_FAIL_NULL_V(p_sync, ERR_BUG);
  317. if (!_has_authority(p_sync) || p_peer == multiplayer->get_unique_id()) {
  318. return OK;
  319. }
  320. const ObjectID &sid = p_sync->get_instance_id();
  321. bool is_visible = p_sync->is_visible_to(p_peer);
  322. if (p_peer == 0) {
  323. for (KeyValue<int, PeerInfo> &E : peers_info) {
  324. // Might be visible to this specific peer.
  325. bool is_visible_to_peer = is_visible || p_sync->is_visible_to(E.key);
  326. if (is_visible_to_peer == E.value.sync_nodes.has(sid)) {
  327. continue;
  328. }
  329. if (is_visible_to_peer) {
  330. E.value.sync_nodes.insert(sid);
  331. } else {
  332. E.value.sync_nodes.erase(sid);
  333. E.value.last_watch_usecs.erase(sid);
  334. }
  335. }
  336. return OK;
  337. } else {
  338. ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
  339. if (is_visible == peers_info[p_peer].sync_nodes.has(sid)) {
  340. return OK;
  341. }
  342. if (is_visible) {
  343. peers_info[p_peer].sync_nodes.insert(sid);
  344. } else {
  345. peers_info[p_peer].sync_nodes.erase(sid);
  346. peers_info[p_peer].last_watch_usecs.erase(sid);
  347. }
  348. return OK;
  349. }
  350. }
  351. Error SceneReplicationInterface::_update_spawn_visibility(int p_peer, const ObjectID &p_oid) {
  352. const TrackedNode *tnode = tracked_nodes.getptr(p_oid);
  353. ERR_FAIL_NULL_V(tnode, ERR_BUG);
  354. MultiplayerSpawner *spawner = get_id_as<MultiplayerSpawner>(tnode->spawner);
  355. Node *node = get_id_as<Node>(p_oid);
  356. ERR_FAIL_NULL_V(node, ERR_BUG);
  357. ERR_FAIL_NULL_V(spawner, ERR_BUG);
  358. ERR_FAIL_COND_V(!_has_authority(spawner), ERR_BUG);
  359. ERR_FAIL_COND_V(!tracked_nodes.has(p_oid), ERR_BUG);
  360. const HashSet<ObjectID> synchronizers = tracked_nodes[p_oid].synchronizers;
  361. bool is_visible = true;
  362. for (const ObjectID &sid : synchronizers) {
  363. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(sid);
  364. ERR_CONTINUE(!sync);
  365. if (!_has_authority(sync)) {
  366. continue;
  367. }
  368. // Spawn visibility is composed using OR when multiple synchronizers are present.
  369. if (sync->is_visible_to(p_peer)) {
  370. is_visible = true;
  371. break;
  372. }
  373. is_visible = false;
  374. }
  375. // Spawn (and despawn) when needed.
  376. HashSet<int> to_spawn;
  377. HashSet<int> to_despawn;
  378. if (p_peer) {
  379. ERR_FAIL_COND_V(!peers_info.has(p_peer), ERR_INVALID_PARAMETER);
  380. if (is_visible == peers_info[p_peer].spawn_nodes.has(p_oid)) {
  381. return OK;
  382. }
  383. if (is_visible) {
  384. to_spawn.insert(p_peer);
  385. } else {
  386. to_despawn.insert(p_peer);
  387. }
  388. } else {
  389. // Check visibility for each peers.
  390. for (const KeyValue<int, PeerInfo> &E : peers_info) {
  391. if (is_visible) {
  392. // This is fast, since the the object is visible to everyone, we don't need to check each peer.
  393. if (E.value.spawn_nodes.has(p_oid)) {
  394. // Already spawned.
  395. continue;
  396. }
  397. to_spawn.insert(E.key);
  398. } else {
  399. // Need to check visibility for each peer.
  400. _update_spawn_visibility(E.key, p_oid);
  401. }
  402. }
  403. }
  404. if (to_spawn.size()) {
  405. int len = 0;
  406. _make_spawn_packet(node, spawner, len);
  407. for (int pid : to_spawn) {
  408. ERR_CONTINUE(!peers_info.has(pid));
  409. int path_id;
  410. multiplayer_cache->send_object_cache(spawner, pid, path_id);
  411. _send_raw(packet_cache.ptr(), len, pid, true);
  412. peers_info[pid].spawn_nodes.insert(p_oid);
  413. }
  414. }
  415. if (to_despawn.size()) {
  416. int len = 0;
  417. _make_despawn_packet(node, len);
  418. for (int pid : to_despawn) {
  419. ERR_CONTINUE(!peers_info.has(pid));
  420. peers_info[pid].spawn_nodes.erase(p_oid);
  421. _send_raw(packet_cache.ptr(), len, pid, true);
  422. }
  423. }
  424. return OK;
  425. }
  426. Error SceneReplicationInterface::_send_raw(const uint8_t *p_buffer, int p_size, int p_peer, bool p_reliable) {
  427. ERR_FAIL_COND_V(!p_buffer || p_size < 1, ERR_INVALID_PARAMETER);
  428. Ref<MultiplayerPeer> peer = multiplayer->get_multiplayer_peer();
  429. ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
  430. peer->set_transfer_channel(0);
  431. peer->set_transfer_mode(p_reliable ? MultiplayerPeer::TRANSFER_MODE_RELIABLE : MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
  432. return multiplayer->send_command(p_peer, p_buffer, p_size);
  433. }
  434. Error SceneReplicationInterface::_make_spawn_packet(Node *p_node, MultiplayerSpawner *p_spawner, int &r_len) {
  435. ERR_FAIL_COND_V(!multiplayer || !p_node || !p_spawner, ERR_BUG);
  436. const ObjectID oid = p_node->get_instance_id();
  437. TrackedNode *tnode = tracked_nodes.getptr(oid);
  438. ERR_FAIL_NULL_V(tnode, ERR_INVALID_PARAMETER);
  439. if (tnode->net_id == 0) {
  440. // Ensure the node has an ID.
  441. tnode->net_id = ++last_net_id;
  442. }
  443. uint32_t nid = tnode->net_id;
  444. ERR_FAIL_COND_V(!nid, ERR_UNCONFIGURED);
  445. // Prepare custom arg and scene_id
  446. uint8_t scene_id = p_spawner->find_spawnable_scene_index_from_object(oid);
  447. bool is_custom = scene_id == MultiplayerSpawner::INVALID_ID;
  448. Variant spawn_arg = p_spawner->get_spawn_argument(oid);
  449. int spawn_arg_size = 0;
  450. if (is_custom) {
  451. Error err = MultiplayerAPI::encode_and_compress_variant(spawn_arg, nullptr, spawn_arg_size, false);
  452. ERR_FAIL_COND_V(err, err);
  453. }
  454. // Prepare spawn state.
  455. List<NodePath> state_props;
  456. List<uint32_t> sync_ids;
  457. const HashSet<ObjectID> synchronizers = tnode->synchronizers;
  458. for (const ObjectID &sid : synchronizers) {
  459. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(sid);
  460. if (!_has_authority(sync)) {
  461. continue;
  462. }
  463. ERR_CONTINUE(!sync);
  464. ERR_FAIL_NULL_V(sync->get_replication_config_ptr(), ERR_BUG);
  465. for (const NodePath &prop : sync->get_replication_config_ptr()->get_spawn_properties()) {
  466. state_props.push_back(prop);
  467. }
  468. // Ensure the synchronizer has an ID.
  469. if (sync->get_net_id() == 0) {
  470. sync->set_net_id(++last_net_id);
  471. }
  472. sync_ids.push_back(sync->get_net_id());
  473. }
  474. int state_size = 0;
  475. Vector<Variant> state_vars;
  476. Vector<const Variant *> state_varp;
  477. if (state_props.size()) {
  478. Error err = MultiplayerSynchronizer::get_state(state_props, p_node, state_vars, state_varp);
  479. ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to retrieve spawn state.");
  480. err = MultiplayerAPI::encode_and_compress_variants(state_varp.ptrw(), state_varp.size(), nullptr, state_size);
  481. ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to encode spawn state.");
  482. }
  483. // Encode scene ID, path ID, net ID, node name.
  484. int path_id = multiplayer_cache->make_object_cache(p_spawner);
  485. CharString cname = p_node->get_name().operator String().utf8();
  486. int nlen = encode_cstring(cname.get_data(), nullptr);
  487. MAKE_ROOM(1 + 1 + 4 + 4 + 4 + 4 * sync_ids.size() + 4 + nlen + (is_custom ? 4 + spawn_arg_size : 0) + state_size);
  488. uint8_t *ptr = packet_cache.ptrw();
  489. ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_SPAWN;
  490. ptr[1] = scene_id;
  491. int ofs = 2;
  492. ofs += encode_uint32(path_id, &ptr[ofs]);
  493. ofs += encode_uint32(nid, &ptr[ofs]);
  494. ofs += encode_uint32(sync_ids.size(), &ptr[ofs]);
  495. ofs += encode_uint32(nlen, &ptr[ofs]);
  496. for (uint32_t snid : sync_ids) {
  497. ofs += encode_uint32(snid, &ptr[ofs]);
  498. }
  499. ofs += encode_cstring(cname.get_data(), &ptr[ofs]);
  500. // Write args
  501. if (is_custom) {
  502. ofs += encode_uint32(spawn_arg_size, &ptr[ofs]);
  503. Error err = MultiplayerAPI::encode_and_compress_variant(spawn_arg, &ptr[ofs], spawn_arg_size, false);
  504. ERR_FAIL_COND_V(err, err);
  505. ofs += spawn_arg_size;
  506. }
  507. // Write state.
  508. if (state_size) {
  509. Error err = MultiplayerAPI::encode_and_compress_variants(state_varp.ptrw(), state_varp.size(), &ptr[ofs], state_size);
  510. ERR_FAIL_COND_V(err, err);
  511. ofs += state_size;
  512. }
  513. r_len = ofs;
  514. return OK;
  515. }
  516. Error SceneReplicationInterface::_make_despawn_packet(Node *p_node, int &r_len) {
  517. const ObjectID oid = p_node->get_instance_id();
  518. const TrackedNode *tnode = tracked_nodes.getptr(oid);
  519. ERR_FAIL_NULL_V(tnode, ERR_INVALID_PARAMETER);
  520. MAKE_ROOM(5);
  521. uint8_t *ptr = packet_cache.ptrw();
  522. ptr[0] = (uint8_t)SceneMultiplayer::NETWORK_COMMAND_DESPAWN;
  523. int ofs = 1;
  524. uint32_t nid = tnode->net_id;
  525. ofs += encode_uint32(nid, &ptr[ofs]);
  526. r_len = ofs;
  527. return OK;
  528. }
  529. Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) {
  530. ERR_FAIL_COND_V_MSG(p_buffer_len < 18, ERR_INVALID_DATA, "Invalid spawn packet received");
  531. int ofs = 1; // The spawn/despawn command.
  532. uint8_t scene_id = p_buffer[ofs];
  533. ofs += 1;
  534. uint32_t node_target = decode_uint32(&p_buffer[ofs]);
  535. ofs += 4;
  536. MultiplayerSpawner *spawner = Object::cast_to<MultiplayerSpawner>(multiplayer_cache->get_cached_object(p_from, node_target));
  537. ERR_FAIL_NULL_V(spawner, ERR_DOES_NOT_EXIST);
  538. ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
  539. uint32_t net_id = decode_uint32(&p_buffer[ofs]);
  540. ofs += 4;
  541. uint32_t sync_len = decode_uint32(&p_buffer[ofs]);
  542. ofs += 4;
  543. uint32_t name_len = decode_uint32(&p_buffer[ofs]);
  544. ofs += 4;
  545. ERR_FAIL_COND_V_MSG(name_len + (sync_len * 4) > uint32_t(p_buffer_len - ofs), ERR_INVALID_DATA, vformat("Invalid spawn packet size: %d, wants: %d", p_buffer_len, ofs + name_len + (sync_len * 4)));
  546. List<uint32_t> sync_ids;
  547. for (uint32_t i = 0; i < sync_len; i++) {
  548. sync_ids.push_back(decode_uint32(&p_buffer[ofs]));
  549. ofs += 4;
  550. }
  551. ERR_FAIL_COND_V_MSG(name_len < 1, ERR_INVALID_DATA, "Zero spawn name size.");
  552. // We need to make sure no trickery happens here, but we want to allow autogenerated ("@") node names.
  553. const String name = String::utf8((const char *)&p_buffer[ofs], name_len);
  554. ERR_FAIL_COND_V_MSG(name.validate_node_name() != name, ERR_INVALID_DATA, vformat("Invalid node name received: '%s'. Make sure to add nodes via 'add_child(node, true)' remotely.", name));
  555. ofs += name_len;
  556. // Check that we can spawn.
  557. Node *parent = spawner->get_node_or_null(spawner->get_spawn_path());
  558. ERR_FAIL_NULL_V(parent, ERR_UNCONFIGURED);
  559. ERR_FAIL_COND_V(parent->has_node(name), ERR_INVALID_DATA);
  560. Node *node = nullptr;
  561. if (scene_id == MultiplayerSpawner::INVALID_ID) {
  562. // Custom spawn.
  563. ERR_FAIL_COND_V(p_buffer_len - ofs < 4, ERR_INVALID_DATA);
  564. uint32_t arg_size = decode_uint32(&p_buffer[ofs]);
  565. ofs += 4;
  566. ERR_FAIL_COND_V(arg_size > uint32_t(p_buffer_len - ofs), ERR_INVALID_DATA);
  567. Variant v;
  568. Error err = MultiplayerAPI::decode_and_decompress_variant(v, &p_buffer[ofs], arg_size, nullptr, false);
  569. ERR_FAIL_COND_V(err != OK, err);
  570. ofs += arg_size;
  571. node = spawner->instantiate_custom(v);
  572. } else {
  573. // Scene based spawn.
  574. node = spawner->instantiate_scene(scene_id);
  575. }
  576. ERR_FAIL_NULL_V(node, ERR_UNAUTHORIZED);
  577. node->set_name(name);
  578. // Add and track remote
  579. ERR_FAIL_COND_V(!peers_info.has(p_from), ERR_UNAVAILABLE);
  580. ERR_FAIL_COND_V(peers_info[p_from].recv_nodes.has(net_id), ERR_ALREADY_IN_USE);
  581. ObjectID oid = node->get_instance_id();
  582. TrackedNode &tobj = _track(oid);
  583. tobj.spawner = spawner->get_instance_id();
  584. tobj.net_id = net_id;
  585. tobj.remote_peer = p_from;
  586. peers_info[p_from].recv_nodes[net_id] = oid;
  587. // The initial state will be applied during the sync config (i.e. before _ready).
  588. pending_spawn = node->get_instance_id();
  589. pending_spawn_remote = p_from;
  590. pending_buffer_size = p_buffer_len - ofs;
  591. pending_buffer = pending_buffer_size > 0 ? &p_buffer[ofs] : nullptr;
  592. pending_sync_net_ids = sync_ids;
  593. parent->add_child(node);
  594. spawner->emit_signal(SNAME("spawned"), node);
  595. pending_spawn = ObjectID();
  596. pending_spawn_remote = 0;
  597. pending_buffer = nullptr;
  598. pending_buffer_size = 0;
  599. if (pending_sync_net_ids.size()) {
  600. pending_sync_net_ids.clear();
  601. ERR_FAIL_V(ERR_INVALID_DATA); // Should have been consumed.
  602. }
  603. return OK;
  604. }
  605. Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) {
  606. ERR_FAIL_COND_V_MSG(p_buffer_len < 5, ERR_INVALID_DATA, "Invalid spawn packet received");
  607. int ofs = 1; // The spawn/despawn command.
  608. uint32_t net_id = decode_uint32(&p_buffer[ofs]);
  609. ofs += 4;
  610. // Untrack remote
  611. ERR_FAIL_COND_V(!peers_info.has(p_from), ERR_UNAUTHORIZED);
  612. PeerInfo &pinfo = peers_info[p_from];
  613. ERR_FAIL_COND_V(!pinfo.recv_nodes.has(net_id), ERR_UNAUTHORIZED);
  614. Node *node = get_id_as<Node>(pinfo.recv_nodes[net_id]);
  615. ERR_FAIL_NULL_V(node, ERR_BUG);
  616. pinfo.recv_nodes.erase(net_id);
  617. const ObjectID oid = node->get_instance_id();
  618. ERR_FAIL_COND_V(!tracked_nodes.has(oid), ERR_BUG);
  619. MultiplayerSpawner *spawner = get_id_as<MultiplayerSpawner>(tracked_nodes[oid].spawner);
  620. ERR_FAIL_NULL_V(spawner, ERR_DOES_NOT_EXIST);
  621. ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
  622. if (node->get_parent() != nullptr) {
  623. node->get_parent()->remove_child(node);
  624. }
  625. node->queue_free();
  626. spawner->emit_signal(SNAME("despawned"), node);
  627. return OK;
  628. }
  629. bool SceneReplicationInterface::_verify_synchronizer(int p_peer, MultiplayerSynchronizer *p_sync, uint32_t &r_net_id) {
  630. r_net_id = p_sync->get_net_id();
  631. if (r_net_id == 0 || (r_net_id & 0x80000000)) {
  632. int path_id = 0;
  633. bool verified = multiplayer_cache->send_object_cache(p_sync, p_peer, path_id);
  634. ERR_FAIL_COND_V_MSG(path_id < 0, false, "This should never happen!");
  635. if (r_net_id == 0) {
  636. // First time path based ID.
  637. r_net_id = path_id | 0x80000000;
  638. p_sync->set_net_id(r_net_id | 0x80000000);
  639. }
  640. return verified;
  641. }
  642. return true;
  643. }
  644. MultiplayerSynchronizer *SceneReplicationInterface::_find_synchronizer(int p_peer, uint32_t p_net_id) {
  645. MultiplayerSynchronizer *sync = nullptr;
  646. if (p_net_id & 0x80000000) {
  647. sync = Object::cast_to<MultiplayerSynchronizer>(multiplayer_cache->get_cached_object(p_peer, p_net_id & 0x7FFFFFFF));
  648. } else if (peers_info[p_peer].recv_sync_ids.has(p_net_id)) {
  649. const ObjectID &sid = peers_info[p_peer].recv_sync_ids[p_net_id];
  650. sync = get_id_as<MultiplayerSynchronizer>(sid);
  651. }
  652. return sync;
  653. }
  654. void SceneReplicationInterface::_send_delta(int p_peer, const HashSet<ObjectID> p_synchronizers, uint64_t p_usec, const HashMap<ObjectID, uint64_t> p_last_watch_usecs) {
  655. MAKE_ROOM(/* header */ 1 + /* element */ 4 + 8 + 4 + delta_mtu);
  656. uint8_t *ptr = packet_cache.ptrw();
  657. ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC | (1 << SceneMultiplayer::CMD_FLAG_0_SHIFT);
  658. int ofs = 1;
  659. for (const ObjectID &oid : p_synchronizers) {
  660. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(oid);
  661. ERR_CONTINUE(!sync || !sync->get_replication_config_ptr() || !_has_authority(sync));
  662. uint32_t net_id;
  663. if (!_verify_synchronizer(p_peer, sync, net_id)) {
  664. continue;
  665. }
  666. uint64_t last_usec = p_last_watch_usecs.has(oid) ? p_last_watch_usecs[oid] : 0;
  667. uint64_t indexes;
  668. List<Variant> delta = sync->get_delta_state(p_usec, last_usec, indexes);
  669. if (!delta.size()) {
  670. continue; // Nothing to update.
  671. }
  672. Vector<const Variant *> varp;
  673. varp.resize(delta.size());
  674. const Variant **vptr = varp.ptrw();
  675. int i = 0;
  676. for (const Variant &v : delta) {
  677. vptr[i] = &v;
  678. i++;
  679. }
  680. int size;
  681. Error err = MultiplayerAPI::encode_and_compress_variants(vptr, varp.size(), nullptr, size);
  682. ERR_CONTINUE_MSG(err != OK, "Unable to encode delta state.");
  683. ERR_CONTINUE_MSG(size > delta_mtu, vformat("Synchronizer delta bigger than MTU will not be sent (%d > %d): %s", size, delta_mtu, sync->get_path()));
  684. if (ofs + 4 + 8 + 4 + size > delta_mtu) {
  685. // Send what we got, and reset write.
  686. _send_raw(packet_cache.ptr(), ofs, p_peer, true);
  687. ofs = 1;
  688. }
  689. if (size) {
  690. ofs += encode_uint32(sync->get_net_id(), &ptr[ofs]);
  691. ofs += encode_uint64(indexes, &ptr[ofs]);
  692. ofs += encode_uint32(size, &ptr[ofs]);
  693. MultiplayerAPI::encode_and_compress_variants(vptr, varp.size(), &ptr[ofs], size);
  694. ofs += size;
  695. }
  696. #ifdef DEBUG_ENABLED
  697. _profile_node_data("delta_out", oid, size);
  698. #endif
  699. peers_info[p_peer].last_watch_usecs[oid] = p_usec;
  700. }
  701. if (ofs > 1) {
  702. // Got some left over to send.
  703. _send_raw(packet_cache.ptr(), ofs, p_peer, true);
  704. }
  705. }
  706. Error SceneReplicationInterface::on_delta_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) {
  707. int ofs = 1;
  708. while (ofs + 4 + 8 + 4 < p_buffer_len) {
  709. uint32_t net_id = decode_uint32(&p_buffer[ofs]);
  710. ofs += 4;
  711. uint64_t indexes = decode_uint64(&p_buffer[ofs]);
  712. ofs += 8;
  713. uint32_t size = decode_uint32(&p_buffer[ofs]);
  714. ofs += 4;
  715. ERR_FAIL_COND_V(size > uint32_t(p_buffer_len - ofs), ERR_INVALID_DATA);
  716. MultiplayerSynchronizer *sync = _find_synchronizer(p_from, net_id);
  717. Node *node = sync ? sync->get_root_node() : nullptr;
  718. if (!sync || sync->get_multiplayer_authority() != p_from || !node) {
  719. ofs += size;
  720. ERR_CONTINUE_MSG(true, "Ignoring delta for non-authority or invalid synchronizer.");
  721. }
  722. List<NodePath> props = sync->get_delta_properties(indexes);
  723. ERR_FAIL_COND_V(props.size() == 0, ERR_INVALID_DATA);
  724. Vector<Variant> vars;
  725. vars.resize(props.size());
  726. int consumed = 0;
  727. Error err = MultiplayerAPI::decode_and_decompress_variants(vars, p_buffer + ofs, size, consumed);
  728. ERR_FAIL_COND_V(err != OK, err);
  729. ERR_FAIL_COND_V(uint32_t(consumed) != size, ERR_INVALID_DATA);
  730. err = MultiplayerSynchronizer::set_state(props, node, vars);
  731. ERR_FAIL_COND_V(err != OK, err);
  732. ofs += size;
  733. sync->emit_signal(SNAME("delta_synchronized"));
  734. #ifdef DEBUG_ENABLED
  735. _profile_node_data("delta_in", sync->get_instance_id(), size);
  736. #endif
  737. }
  738. return OK;
  739. }
  740. void SceneReplicationInterface::_send_sync(int p_peer, const HashSet<ObjectID> p_synchronizers, uint16_t p_sync_net_time, uint64_t p_usec) {
  741. MAKE_ROOM(/* header */ 3 + /* element */ 4 + 4 + sync_mtu);
  742. uint8_t *ptr = packet_cache.ptrw();
  743. ptr[0] = SceneMultiplayer::NETWORK_COMMAND_SYNC;
  744. int ofs = 1;
  745. ofs += encode_uint16(p_sync_net_time, &ptr[1]);
  746. // Can only send updates for already notified nodes.
  747. // This is a lazy implementation, we could optimize much more here with by grouping by replication config.
  748. for (const ObjectID &oid : p_synchronizers) {
  749. MultiplayerSynchronizer *sync = get_id_as<MultiplayerSynchronizer>(oid);
  750. ERR_CONTINUE(!sync || !sync->get_replication_config_ptr() || !_has_authority(sync));
  751. if (!sync->update_outbound_sync_time(p_usec)) {
  752. continue; // nothing to sync.
  753. }
  754. Node *node = sync->get_root_node();
  755. ERR_CONTINUE(!node);
  756. uint32_t net_id = sync->get_net_id();
  757. if (!_verify_synchronizer(p_peer, sync, net_id)) {
  758. // The path based sync is not yet confirmed, skipping.
  759. continue;
  760. }
  761. int size;
  762. Vector<Variant> vars;
  763. Vector<const Variant *> varp;
  764. const List<NodePath> props = sync->get_replication_config_ptr()->get_sync_properties();
  765. Error err = MultiplayerSynchronizer::get_state(props, node, vars, varp);
  766. ERR_CONTINUE_MSG(err != OK, "Unable to retrieve sync state.");
  767. err = MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), nullptr, size);
  768. ERR_CONTINUE_MSG(err != OK, "Unable to encode sync state.");
  769. // TODO Handle single state above MTU.
  770. ERR_CONTINUE_MSG(size > sync_mtu, vformat("Node states bigger than MTU will not be sent (%d > %d): %s", size, sync_mtu, node->get_path()));
  771. if (ofs + 4 + 4 + size > sync_mtu) {
  772. // Send what we got, and reset write.
  773. _send_raw(packet_cache.ptr(), ofs, p_peer, false);
  774. ofs = 3;
  775. }
  776. if (size) {
  777. ofs += encode_uint32(sync->get_net_id(), &ptr[ofs]);
  778. ofs += encode_uint32(size, &ptr[ofs]);
  779. MultiplayerAPI::encode_and_compress_variants(varp.ptrw(), varp.size(), &ptr[ofs], size);
  780. ofs += size;
  781. }
  782. #ifdef DEBUG_ENABLED
  783. _profile_node_data("sync_out", oid, size);
  784. #endif
  785. }
  786. if (ofs > 3) {
  787. // Got some left over to send.
  788. _send_raw(packet_cache.ptr(), ofs, p_peer, false);
  789. }
  790. }
  791. Error SceneReplicationInterface::on_sync_receive(int p_from, const uint8_t *p_buffer, int p_buffer_len) {
  792. ERR_FAIL_COND_V_MSG(p_buffer_len < 11, ERR_INVALID_DATA, "Invalid sync packet received");
  793. bool is_delta = (p_buffer[0] & (1 << SceneMultiplayer::CMD_FLAG_0_SHIFT)) != 0;
  794. if (is_delta) {
  795. return on_delta_receive(p_from, p_buffer, p_buffer_len);
  796. }
  797. uint16_t time = decode_uint16(&p_buffer[1]);
  798. int ofs = 3;
  799. while (ofs + 8 < p_buffer_len) {
  800. uint32_t net_id = decode_uint32(&p_buffer[ofs]);
  801. ofs += 4;
  802. uint32_t size = decode_uint32(&p_buffer[ofs]);
  803. ofs += 4;
  804. ERR_FAIL_COND_V(size > uint32_t(p_buffer_len - ofs), ERR_INVALID_DATA);
  805. MultiplayerSynchronizer *sync = _find_synchronizer(p_from, net_id);
  806. if (!sync) {
  807. // Not received yet.
  808. ofs += size;
  809. continue;
  810. }
  811. Node *node = sync->get_root_node();
  812. if (sync->get_multiplayer_authority() != p_from || !node) {
  813. // Not valid for me.
  814. ofs += size;
  815. ERR_CONTINUE_MSG(true, "Ignoring sync data from non-authority or for missing node.");
  816. }
  817. if (!sync->update_inbound_sync_time(time)) {
  818. // State is too old.
  819. ofs += size;
  820. continue;
  821. }
  822. const List<NodePath> props = sync->get_replication_config_ptr()->get_sync_properties();
  823. Vector<Variant> vars;
  824. vars.resize(props.size());
  825. int consumed;
  826. Error err = MultiplayerAPI::decode_and_decompress_variants(vars, &p_buffer[ofs], size, consumed);
  827. ERR_FAIL_COND_V(err, err);
  828. err = MultiplayerSynchronizer::set_state(props, node, vars);
  829. ERR_FAIL_COND_V(err, err);
  830. ofs += size;
  831. sync->emit_signal(SNAME("synchronized"));
  832. #ifdef DEBUG_ENABLED
  833. _profile_node_data("sync_in", sync->get_instance_id(), size);
  834. #endif
  835. }
  836. return OK;
  837. }
  838. void SceneReplicationInterface::set_max_sync_packet_size(int p_size) {
  839. ERR_FAIL_COND_MSG(p_size < 128, "Sync maximum packet size must be at least 128 bytes.");
  840. sync_mtu = p_size;
  841. }
  842. int SceneReplicationInterface::get_max_sync_packet_size() const {
  843. return sync_mtu;
  844. }
  845. void SceneReplicationInterface::set_max_delta_packet_size(int p_size) {
  846. ERR_FAIL_COND_MSG(p_size < 128, "Sync maximum packet size must be at least 128 bytes.");
  847. delta_mtu = p_size;
  848. }
  849. int SceneReplicationInterface::get_max_delta_packet_size() const {
  850. return delta_mtu;
  851. }