multiplayer_replicator.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*************************************************************************/
  2. /* multiplayer_replicator.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  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 "core/io/multiplayer_replicator.h"
  31. #include "core/io/marshalls.h"
  32. #include "scene/main/node.h"
  33. #include "scene/resources/packed_scene.h"
  34. #define MAKE_ROOM(m_amount) \
  35. if (packet_cache.size() < m_amount) \
  36. packet_cache.resize(m_amount);
  37. Error MultiplayerReplicator::_sync_all_default(const ResourceUID::ID &p_scene_id, int p_peer) {
  38. ERR_FAIL_COND_V(!replications.has(p_scene_id), ERR_INVALID_PARAMETER);
  39. SceneConfig &cfg = replications[p_scene_id];
  40. int full_size = 0;
  41. bool same_size = true;
  42. int last_size = 0;
  43. bool all_raw = true;
  44. struct EncodeInfo {
  45. int size = 0;
  46. bool raw = false;
  47. List<Variant> state;
  48. };
  49. Map<ObjectID, struct EncodeInfo> state;
  50. if (tracked_objects.has(p_scene_id)) {
  51. for (const ObjectID &obj_id : tracked_objects[p_scene_id]) {
  52. Object *obj = ObjectDB::get_instance(obj_id);
  53. if (obj) {
  54. struct EncodeInfo info;
  55. Error err = _get_state(cfg.sync_properties, obj, info.state);
  56. ERR_CONTINUE(err);
  57. err = _encode_state(info.state, nullptr, info.size, &info.raw);
  58. ERR_CONTINUE(err);
  59. state[obj_id] = info;
  60. full_size += info.size;
  61. if (last_size && info.size != last_size) {
  62. same_size = false;
  63. }
  64. all_raw = all_raw && info.raw;
  65. last_size = info.size;
  66. }
  67. }
  68. }
  69. // Default implementation do not send empty updates.
  70. if (!full_size) {
  71. return OK;
  72. }
  73. #ifdef DEBUG_ENABLED
  74. if (full_size > 4096 && cfg.sync_interval) {
  75. WARN_PRINT_ONCE(vformat("The timed state update for scene %d is big (%d bytes) consider optimizing it", p_scene_id));
  76. }
  77. #endif
  78. if (same_size) {
  79. // This is fast and small. Should we allow more than 256 objects per type?
  80. // This costs us 1 byte.
  81. MAKE_ROOM(SYNC_CMD_OFFSET + 1 + 2 + 2 + full_size);
  82. } else {
  83. MAKE_ROOM(SYNC_CMD_OFFSET + 1 + 2 + state.size() * 2 + full_size);
  84. }
  85. int ofs = 0;
  86. uint8_t *ptr = packet_cache.ptrw();
  87. ptr[0] = MultiplayerAPI::NETWORK_COMMAND_SYNC + ((same_size ? 1 : 0) << MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT);
  88. ofs = 1;
  89. ofs += encode_uint64(p_scene_id, &ptr[ofs]);
  90. ptr[ofs] = cfg.sync_recv++;
  91. ofs += 1;
  92. ofs += encode_uint16(state.size(), &ptr[ofs]);
  93. if (same_size) {
  94. ofs += encode_uint16(last_size + (all_raw ? 1 << 15 : 0), &ptr[ofs]);
  95. }
  96. for (const ObjectID &obj_id : tracked_objects[p_scene_id]) {
  97. if (!state.has(obj_id)) {
  98. continue;
  99. }
  100. struct EncodeInfo &info = state[obj_id];
  101. Object *obj = ObjectDB::get_instance(obj_id);
  102. ERR_CONTINUE(!obj);
  103. int size = 0;
  104. if (!same_size) {
  105. // We need to encode the size of every object.
  106. ofs += encode_uint16(info.size + (info.raw ? 1 << 15 : 0), &ptr[ofs]);
  107. }
  108. Error err = _encode_state(info.state, &ptr[ofs], size, &info.raw);
  109. ERR_CONTINUE(err);
  110. ofs += size;
  111. }
  112. Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
  113. network_peer->set_target_peer(p_peer);
  114. network_peer->set_transfer_channel(0);
  115. network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_UNRELIABLE);
  116. return network_peer->put_packet(ptr, ofs);
  117. }
  118. void MultiplayerReplicator::_process_default_sync(const ResourceUID::ID &p_id, const uint8_t *p_packet, int p_packet_len) {
  119. ERR_FAIL_COND_MSG(p_packet_len < SYNC_CMD_OFFSET + 5, "Invalid spawn packet received");
  120. ERR_FAIL_COND_MSG(!replications.has(p_id), "Invalid spawn ID received " + itos(p_id));
  121. SceneConfig &cfg = replications[p_id];
  122. ERR_FAIL_COND_MSG(cfg.mode != REPLICATION_MODE_SERVER || multiplayer->is_network_server(), "The defualt implementation only allows sync packets from the server");
  123. const bool same_size = ((p_packet[0] & 64) >> MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1;
  124. int ofs = SYNC_CMD_OFFSET;
  125. int time = p_packet[ofs];
  126. // Skip old update.
  127. if (time < cfg.sync_recv && cfg.sync_recv - time < 127) {
  128. return;
  129. }
  130. cfg.sync_recv = time;
  131. ofs += 1;
  132. int count = decode_uint16(&p_packet[ofs]);
  133. ofs += 2;
  134. #ifdef DEBUG_ENABLED
  135. ERR_FAIL_COND(!tracked_objects.has(p_id) || tracked_objects[p_id].size() != count);
  136. #else
  137. if (!tracked_objects.has(p_id) || tracked_objects[p_id].size() != count) {
  138. return;
  139. }
  140. #endif
  141. int data_size = 0;
  142. bool raw = false;
  143. if (same_size) {
  144. // This is fast and optimized.
  145. data_size = decode_uint16(&p_packet[ofs]);
  146. raw = (data_size & (1 << 15)) != 0;
  147. data_size = data_size & ~(1 << 15);
  148. ofs += 2;
  149. ERR_FAIL_COND(p_packet_len - ofs < data_size * count);
  150. }
  151. for (const ObjectID &obj_id : tracked_objects[p_id]) {
  152. Object *obj = ObjectDB::get_instance(obj_id);
  153. ERR_CONTINUE(!obj);
  154. if (!same_size) {
  155. // This is slow and wasteful.
  156. data_size = decode_uint16(&p_packet[ofs]);
  157. raw = (data_size & (1 << 15)) != 0;
  158. data_size = data_size & ~(1 << 15);
  159. ofs += 2;
  160. ERR_FAIL_COND(p_packet_len - ofs < data_size);
  161. }
  162. int size = 0;
  163. Error err = _decode_state(cfg.sync_properties, obj, &p_packet[ofs], data_size, size, raw);
  164. ofs += data_size;
  165. ERR_CONTINUE(err);
  166. ERR_CONTINUE(size != data_size);
  167. }
  168. }
  169. Error MultiplayerReplicator::_send_default_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, Object *p_obj, const NodePath &p_path, bool p_spawn) {
  170. ERR_FAIL_COND_V(p_spawn && !p_obj, ERR_INVALID_PARAMETER);
  171. ERR_FAIL_COND_V(!replications.has(p_scene_id), ERR_INVALID_PARAMETER);
  172. Error err;
  173. // Prepare state
  174. List<Variant> state_variants;
  175. int state_len = 0;
  176. const SceneConfig &cfg = replications[p_scene_id];
  177. if (p_spawn) {
  178. if ((err = _get_state(cfg.properties, p_obj, state_variants)) != OK) {
  179. return err;
  180. }
  181. }
  182. bool is_raw = false;
  183. if (state_variants.size() == 1 && state_variants[0].get_type() == Variant::PACKED_BYTE_ARRAY) {
  184. is_raw = true;
  185. } else if (state_variants.size()) {
  186. err = _encode_state(state_variants, nullptr, state_len);
  187. ERR_FAIL_COND_V(err, err);
  188. } else {
  189. is_raw = true;
  190. }
  191. int ofs = 0;
  192. // Prepare simplified path
  193. const Node *root_node = multiplayer->get_root_node();
  194. ERR_FAIL_COND_V(!root_node, ERR_UNCONFIGURED);
  195. NodePath rel_path = (root_node->get_path()).rel_path_to(p_path);
  196. const Vector<StringName> names = rel_path.get_names();
  197. ERR_FAIL_COND_V(names.size() < 2, ERR_INVALID_PARAMETER);
  198. NodePath parent = NodePath(names.subarray(0, names.size() - 2), false);
  199. ERR_FAIL_COND_V_MSG(!root_node->has_node(parent), ERR_INVALID_PARAMETER, "Path not found: " + parent);
  200. int path_id = 0;
  201. multiplayer->send_confirm_path(root_node->get_node(parent), parent, p_peer_id, path_id);
  202. // Encode name and parent ID.
  203. CharString cname = String(names[names.size() - 1]).utf8();
  204. int nlen = encode_cstring(cname.get_data(), nullptr);
  205. MAKE_ROOM(SPAWN_CMD_OFFSET + 4 + 4 + nlen + state_len);
  206. uint8_t *ptr = packet_cache.ptrw();
  207. ptr[0] = (p_spawn ? MultiplayerAPI::NETWORK_COMMAND_SPAWN : MultiplayerAPI::NETWORK_COMMAND_DESPAWN) + ((is_raw ? 1 : 0) << MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT);
  208. ofs = 1;
  209. ofs += encode_uint64(p_scene_id, &ptr[ofs]);
  210. ofs += encode_uint32(path_id, &ptr[ofs]);
  211. ofs += encode_uint32(nlen, &ptr[ofs]);
  212. ofs += encode_cstring(cname.get_data(), &ptr[ofs]);
  213. // Encode state.
  214. if (!is_raw) {
  215. _encode_state(state_variants, &ptr[ofs], state_len);
  216. } else if (state_len) {
  217. PackedByteArray pba = state_variants[0];
  218. memcpy(&ptr[ofs], pba.ptr(), state_len);
  219. }
  220. Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
  221. network_peer->set_target_peer(p_peer_id);
  222. network_peer->set_transfer_channel(0);
  223. network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
  224. return network_peer->put_packet(ptr, ofs + state_len);
  225. }
  226. void MultiplayerReplicator::_process_default_spawn_despawn(int p_from, const ResourceUID::ID &p_scene_id, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
  227. ERR_FAIL_COND_MSG(p_packet_len < SPAWN_CMD_OFFSET + 9, "Invalid spawn packet received");
  228. int ofs = SPAWN_CMD_OFFSET;
  229. uint32_t node_target = decode_uint32(&p_packet[ofs]);
  230. Node *parent = multiplayer->get_cached_node(p_from, node_target);
  231. ofs += 4;
  232. ERR_FAIL_COND_MSG(parent == nullptr, "Invalid packet received. Requested node was not found.");
  233. uint32_t name_len = decode_uint32(&p_packet[ofs]);
  234. ofs += 4;
  235. ERR_FAIL_COND_MSG(name_len > uint32_t(p_packet_len - ofs), vformat("Invalid spawn packet size: %d, wants: %d", p_packet_len, ofs + name_len));
  236. ERR_FAIL_COND_MSG(name_len < 1, "Zero spawn name size.");
  237. const String name = String::utf8((const char *)&p_packet[ofs], name_len);
  238. // We need to make sure no trickery happens here (e.g. despawning a subpath), but we want to allow autogenerated ("@") node names.
  239. ERR_FAIL_COND_MSG(name.validate_node_name() != name.replace("@", ""), vformat("Invalid node name received: '%s'", name));
  240. ofs += name_len;
  241. const SceneConfig &cfg = replications[p_scene_id];
  242. if (cfg.mode == REPLICATION_MODE_SERVER && p_from == 1) {
  243. String scene_path = ResourceUID::get_singleton()->get_id_path(p_scene_id);
  244. if (p_spawn) {
  245. const bool is_raw = ((p_packet[0] & 64) >> MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1;
  246. ERR_FAIL_COND_MSG(parent->has_node(name), vformat("Unable to spawn node. Node already exists: %s/%s", parent->get_path(), name));
  247. RES res = ResourceLoader::load(scene_path);
  248. ERR_FAIL_COND_MSG(!res.is_valid(), "Unable to load scene to spawn at path: " + scene_path);
  249. PackedScene *scene = Object::cast_to<PackedScene>(res.ptr());
  250. ERR_FAIL_COND(!scene);
  251. Node *node = scene->instantiate();
  252. ERR_FAIL_COND(!node);
  253. replicated_nodes[node->get_instance_id()] = p_scene_id;
  254. _track(p_scene_id, node);
  255. int size;
  256. _decode_state(cfg.properties, node, &p_packet[ofs], p_packet_len - ofs, size, is_raw);
  257. parent->_add_child_nocheck(node, name);
  258. emit_signal(SNAME("spawned"), p_scene_id, node);
  259. } else {
  260. ERR_FAIL_COND_MSG(!parent->has_node(name), vformat("Path not found: %s/%s", parent->get_path(), name));
  261. Node *node = parent->get_node(name);
  262. ERR_FAIL_COND_MSG(!replicated_nodes.has(node->get_instance_id()), vformat("Trying to despawn a Node that was not replicated: %s/%s", parent->get_path(), name));
  263. emit_signal(SNAME("despawned"), p_scene_id, node);
  264. _untrack(p_scene_id, node);
  265. replicated_nodes.erase(node->get_instance_id());
  266. node->queue_delete();
  267. }
  268. } else {
  269. PackedByteArray data;
  270. if (p_packet_len > ofs) {
  271. data.resize(p_packet_len - ofs);
  272. memcpy(data.ptrw(), &p_packet[ofs], data.size());
  273. }
  274. if (p_spawn) {
  275. emit_signal(SNAME("spawn_requested"), p_from, p_scene_id, parent, name, data);
  276. } else {
  277. emit_signal(SNAME("despawn_requested"), p_from, p_scene_id, parent, name, data);
  278. }
  279. }
  280. }
  281. void MultiplayerReplicator::process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
  282. ERR_FAIL_COND_MSG(p_packet_len < SPAWN_CMD_OFFSET, "Invalid spawn packet received");
  283. ResourceUID::ID id = decode_uint64(&p_packet[1]);
  284. ERR_FAIL_COND_MSG(!replications.has(id), "Invalid spawn ID received " + itos(id));
  285. const SceneConfig &cfg = replications[id];
  286. if (cfg.on_spawn_despawn_receive.is_valid()) {
  287. int ofs = SPAWN_CMD_OFFSET;
  288. bool is_raw = ((p_packet[0] & 64) >> MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1;
  289. Variant data;
  290. int left = p_packet_len - ofs;
  291. if (is_raw && left) {
  292. PackedByteArray pba;
  293. pba.resize(left);
  294. memcpy(pba.ptrw(), &p_packet[ofs], pba.size());
  295. data = pba;
  296. } else if (left) {
  297. ERR_FAIL_COND(decode_variant(data, &p_packet[ofs], left) != OK);
  298. }
  299. Variant args[4];
  300. args[0] = p_from;
  301. args[1] = id;
  302. args[2] = data;
  303. args[3] = p_spawn;
  304. const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
  305. Callable::CallError ce;
  306. Variant ret;
  307. cfg.on_spawn_despawn_receive.call(argp, 4, ret, ce);
  308. ERR_FAIL_COND_MSG(ce.error != Callable::CallError::CALL_OK, "Custom receive function failed");
  309. } else {
  310. _process_default_spawn_despawn(p_from, id, p_packet, p_packet_len, p_spawn);
  311. }
  312. }
  313. void MultiplayerReplicator::process_sync(int p_from, const uint8_t *p_packet, int p_packet_len) {
  314. ERR_FAIL_COND_MSG(p_packet_len < SPAWN_CMD_OFFSET, "Invalid spawn packet received");
  315. ResourceUID::ID id = decode_uint64(&p_packet[1]);
  316. ERR_FAIL_COND_MSG(!replications.has(id), "Invalid spawn ID received " + itos(id));
  317. const SceneConfig &cfg = replications[id];
  318. if (cfg.on_sync_receive.is_valid()) {
  319. Array objs;
  320. if (tracked_objects.has(id)) {
  321. objs.resize(tracked_objects[id].size());
  322. int idx = 0;
  323. for (const ObjectID &obj_id : tracked_objects[id]) {
  324. objs[idx++] = ObjectDB::get_instance(obj_id);
  325. }
  326. }
  327. PackedByteArray pba;
  328. pba.resize(p_packet_len - SPAWN_CMD_OFFSET);
  329. if (pba.size()) {
  330. memcpy(pba.ptrw(), p_packet, p_packet_len - SPAWN_CMD_OFFSET);
  331. }
  332. Variant args[4] = { p_from, id, objs, pba };
  333. Variant *argp[4] = { args, &args[1], &args[2], &args[3] };
  334. Callable::CallError ce;
  335. Variant ret;
  336. cfg.on_sync_receive.call((const Variant **)argp, 4, ret, ce);
  337. ERR_FAIL_COND_MSG(ce.error != Callable::CallError::CALL_OK, "Custom sync function failed");
  338. } else {
  339. ERR_FAIL_COND_MSG(p_from != 1, "Default sync implementation only allow syncing from server to client");
  340. _process_default_sync(id, p_packet, p_packet_len);
  341. }
  342. }
  343. Error MultiplayerReplicator::_get_state(const List<StringName> &p_properties, const Object *p_obj, List<Variant> &r_variant) {
  344. ERR_FAIL_COND_V_MSG(!p_obj, ERR_INVALID_PARAMETER, "Cannot encode null object");
  345. for (const StringName &prop : p_properties) {
  346. bool valid = false;
  347. const Variant v = p_obj->get(prop, &valid);
  348. ERR_FAIL_COND_V_MSG(!valid, ERR_INVALID_DATA, vformat("Property '%s' not found.", prop));
  349. r_variant.push_back(v);
  350. }
  351. return OK;
  352. }
  353. Error MultiplayerReplicator::_encode_state(const List<Variant> &p_variants, uint8_t *p_buffer, int &r_len, bool *r_raw) {
  354. r_len = 0;
  355. int size = 0;
  356. // Try raw encoding optimization.
  357. if (r_raw && p_variants.size() == 1) {
  358. *r_raw = false;
  359. const Variant v = p_variants[0];
  360. if (v.get_type() == Variant::PACKED_BYTE_ARRAY) {
  361. *r_raw = true;
  362. const PackedByteArray pba = v;
  363. if (p_buffer) {
  364. memcpy(p_buffer, pba.ptr(), pba.size());
  365. }
  366. r_len += pba.size();
  367. } else {
  368. multiplayer->encode_and_compress_variant(v, p_buffer, size);
  369. r_len += size;
  370. }
  371. return OK;
  372. }
  373. // Regular encoding.
  374. for (const Variant &v : p_variants) {
  375. multiplayer->encode_and_compress_variant(v, p_buffer ? p_buffer + r_len : nullptr, size);
  376. r_len += size;
  377. }
  378. return OK;
  379. }
  380. Error MultiplayerReplicator::_decode_state(const List<StringName> &p_properties, Object *p_obj, const uint8_t *p_buffer, int p_len, int &r_len, bool p_raw) {
  381. r_len = 0;
  382. int argc = p_properties.size();
  383. if (argc == 0 && p_raw) {
  384. ERR_FAIL_COND_V_MSG(p_len != 0, ERR_INVALID_DATA, "Buffer has trailing bytes.");
  385. return OK;
  386. }
  387. ERR_FAIL_COND_V(p_raw && argc != 1, ERR_INVALID_DATA);
  388. if (p_raw) {
  389. r_len = p_len;
  390. PackedByteArray pba;
  391. pba.resize(p_len);
  392. memcpy(pba.ptrw(), p_buffer, p_len);
  393. p_obj->set(p_properties[0], pba);
  394. return OK;
  395. }
  396. Vector<Variant> args;
  397. Vector<const Variant *> argp;
  398. args.resize(argc);
  399. for (int i = 0; i < argc; i++) {
  400. ERR_FAIL_COND_V_MSG(r_len >= p_len, ERR_INVALID_DATA, "Invalid packet received. Size too small.");
  401. int vlen;
  402. Error err = multiplayer->decode_and_decompress_variant(args.write[i], &p_buffer[r_len], p_len - r_len, &vlen);
  403. ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid packet received. Unable to decode state variable.");
  404. r_len += vlen;
  405. }
  406. ERR_FAIL_COND_V_MSG(p_len - r_len != 0, ERR_INVALID_DATA, "Buffer has trailing bytes.");
  407. int i = 0;
  408. for (const StringName &prop : p_properties) {
  409. p_obj->set(prop, args[i]);
  410. i += 1;
  411. }
  412. return OK;
  413. }
  414. Error MultiplayerReplicator::spawn_config(const ResourceUID::ID &p_id, ReplicationMode p_mode, const TypedArray<StringName> &p_props, const Callable &p_on_send, const Callable &p_on_recv) {
  415. ERR_FAIL_COND_V(p_mode < REPLICATION_MODE_NONE || p_mode > REPLICATION_MODE_CUSTOM, ERR_INVALID_PARAMETER);
  416. ERR_FAIL_COND_V(!ResourceUID::get_singleton()->has_id(p_id), ERR_INVALID_PARAMETER);
  417. ERR_FAIL_COND_V_MSG(p_on_send.is_valid() != p_on_recv.is_valid(), ERR_INVALID_PARAMETER, "Send and receive custom callables must be both valid or both empty");
  418. #ifdef TOOLS_ENABLED
  419. if (!p_on_send.is_valid()) {
  420. // We allow non scene spawning with custom callables.
  421. String path = ResourceUID::get_singleton()->get_id_path(p_id);
  422. RES res = ResourceLoader::load(path);
  423. ERR_FAIL_COND_V(!res->is_class("PackedScene"), ERR_INVALID_PARAMETER);
  424. }
  425. #endif
  426. if (p_mode == REPLICATION_MODE_NONE) {
  427. if (replications.has(p_id)) {
  428. replications.erase(p_id);
  429. }
  430. } else {
  431. SceneConfig cfg;
  432. cfg.mode = p_mode;
  433. for (int i = 0; i < p_props.size(); i++) {
  434. cfg.properties.push_back(StringName(p_props[i]));
  435. }
  436. cfg.on_spawn_despawn_send = p_on_send;
  437. cfg.on_spawn_despawn_receive = p_on_recv;
  438. replications[p_id] = cfg;
  439. }
  440. return OK;
  441. }
  442. Error MultiplayerReplicator::sync_config(const ResourceUID::ID &p_id, uint64_t p_interval, const TypedArray<StringName> &p_props, const Callable &p_on_send, const Callable &p_on_recv) {
  443. ERR_FAIL_COND_V(!ResourceUID::get_singleton()->has_id(p_id), ERR_INVALID_PARAMETER);
  444. ERR_FAIL_COND_V_MSG(p_on_send.is_valid() != p_on_recv.is_valid(), ERR_INVALID_PARAMETER, "Send and receive custom callables must be both valid or both empty");
  445. ERR_FAIL_COND_V(!replications.has(p_id), ERR_UNCONFIGURED);
  446. SceneConfig &cfg = replications[p_id];
  447. ERR_FAIL_COND_V_MSG(p_interval && cfg.mode != REPLICATION_MODE_SERVER && !p_on_send.is_valid(), ERR_INVALID_PARAMETER, "Timed updates in custom mode are only allowed if custom callbacks are also specified");
  448. for (int i = 0; i < p_props.size(); i++) {
  449. cfg.sync_properties.push_back(p_props[i]);
  450. }
  451. cfg.on_sync_send = p_on_send;
  452. cfg.on_sync_receive = p_on_recv;
  453. cfg.sync_interval = p_interval * 1000;
  454. return OK;
  455. }
  456. Error MultiplayerReplicator::_send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, bool p_spawn) {
  457. int data_size = 0;
  458. int is_raw = false;
  459. if (p_data.get_type() == Variant::PACKED_BYTE_ARRAY) {
  460. const PackedByteArray pba = p_data;
  461. is_raw = true;
  462. data_size = p_data.operator PackedByteArray().size();
  463. } else if (p_data.get_type() == Variant::NIL) {
  464. is_raw = true;
  465. } else {
  466. Error err = encode_variant(p_data, nullptr, data_size);
  467. ERR_FAIL_COND_V(err, err);
  468. }
  469. MAKE_ROOM(SPAWN_CMD_OFFSET + data_size);
  470. uint8_t *ptr = packet_cache.ptrw();
  471. ptr[0] = (p_spawn ? MultiplayerAPI::NETWORK_COMMAND_SPAWN : MultiplayerAPI::NETWORK_COMMAND_DESPAWN) + ((is_raw ? 1 : 0) << MultiplayerAPI::BYTE_ONLY_OR_NO_ARGS_SHIFT);
  472. encode_uint64(p_scene_id, &ptr[1]);
  473. if (p_data.get_type() == Variant::PACKED_BYTE_ARRAY) {
  474. const PackedByteArray pba = p_data;
  475. memcpy(&ptr[SPAWN_CMD_OFFSET], pba.ptr(), pba.size());
  476. } else if (data_size) {
  477. encode_variant(p_data, &ptr[SPAWN_CMD_OFFSET], data_size);
  478. }
  479. Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
  480. network_peer->set_target_peer(p_peer_id);
  481. network_peer->set_transfer_channel(0);
  482. network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
  483. return network_peer->put_packet(ptr, SPAWN_CMD_OFFSET + data_size);
  484. }
  485. Error MultiplayerReplicator::send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, const NodePath &p_path) {
  486. ERR_FAIL_COND_V(!multiplayer->has_network_peer(), ERR_UNCONFIGURED);
  487. ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
  488. const SceneConfig &cfg = replications[p_scene_id];
  489. if (cfg.on_spawn_despawn_send.is_valid()) {
  490. return _send_spawn_despawn(p_peer_id, p_scene_id, p_data, true);
  491. } else {
  492. ERR_FAIL_COND_V_MSG(cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server(), ERR_UNAVAILABLE, "Manual despawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests.");
  493. NodePath path = p_path;
  494. Object *obj = p_data.get_type() == Variant::OBJECT ? p_data.get_validated_object() : nullptr;
  495. if (path.is_empty() && obj) {
  496. Node *node = Object::cast_to<Node>(obj);
  497. if (node && node->is_inside_tree()) {
  498. path = node->get_path();
  499. }
  500. }
  501. ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Despawn default implementation requires a despawn path, or the data to be a node inside the SceneTree");
  502. return _send_default_spawn_despawn(p_peer_id, p_scene_id, obj, path, false);
  503. }
  504. }
  505. Error MultiplayerReplicator::send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const Variant &p_data, const NodePath &p_path) {
  506. ERR_FAIL_COND_V(!multiplayer->has_network_peer(), ERR_UNCONFIGURED);
  507. ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
  508. const SceneConfig &cfg = replications[p_scene_id];
  509. if (cfg.on_spawn_despawn_send.is_valid()) {
  510. return _send_spawn_despawn(p_peer_id, p_scene_id, p_data, false);
  511. } else {
  512. ERR_FAIL_COND_V_MSG(cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server(), ERR_UNAVAILABLE, "Manual spawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests.");
  513. NodePath path = p_path;
  514. Object *obj = p_data.get_type() == Variant::OBJECT ? p_data.get_validated_object() : nullptr;
  515. ERR_FAIL_COND_V_MSG(!obj, ERR_INVALID_PARAMETER, "Spawn default implementation requires the data to be an object.");
  516. if (path.is_empty()) {
  517. Node *node = Object::cast_to<Node>(obj);
  518. if (node && node->is_inside_tree()) {
  519. path = node->get_path();
  520. }
  521. }
  522. ERR_FAIL_COND_V_MSG(path.is_empty(), ERR_INVALID_PARAMETER, "Spawn default implementation requires a spawn path, or the data to be a node inside the SceneTree");
  523. return _send_default_spawn_despawn(p_peer_id, p_scene_id, obj, path, true);
  524. }
  525. }
  526. Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer, bool p_spawn) {
  527. ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
  528. const SceneConfig &cfg = replications[p_scene_id];
  529. if (cfg.on_spawn_despawn_send.is_valid()) {
  530. Variant args[4];
  531. args[0] = p_peer;
  532. args[1] = p_scene_id;
  533. args[2] = p_obj;
  534. args[3] = true;
  535. const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] };
  536. Callable::CallError ce;
  537. Variant ret;
  538. cfg.on_spawn_despawn_send.call(argp, 4, ret, ce);
  539. ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, FAILED, "Custom send function failed");
  540. return OK;
  541. } else {
  542. Node *node = Object::cast_to<Node>(p_obj);
  543. ERR_FAIL_COND_V_MSG(!p_obj, ERR_INVALID_PARAMETER, "Only nodes can be replicated by the default implementation");
  544. return _send_default_spawn_despawn(p_peer, p_scene_id, node, node->get_path(), p_spawn);
  545. }
  546. }
  547. Error MultiplayerReplicator::spawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer) {
  548. return _spawn_despawn(p_scene_id, p_obj, p_peer, true);
  549. }
  550. Error MultiplayerReplicator::despawn(ResourceUID::ID p_scene_id, Object *p_obj, int p_peer) {
  551. return _spawn_despawn(p_scene_id, p_obj, p_peer, false);
  552. }
  553. PackedByteArray MultiplayerReplicator::encode_state(const ResourceUID::ID &p_scene_id, const Object *p_obj, bool p_initial) {
  554. PackedByteArray state;
  555. ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), state, vformat("Spawnable not found: %d", p_scene_id));
  556. const SceneConfig &cfg = replications[p_scene_id];
  557. int len = 0;
  558. List<Variant> state_vars;
  559. const List<StringName> props = p_initial ? cfg.properties : cfg.sync_properties;
  560. Error err = _get_state(props, p_obj, state_vars);
  561. ERR_FAIL_COND_V_MSG(err != OK, state, "Unable to retrieve object state.");
  562. err = _encode_state(state_vars, nullptr, len);
  563. ERR_FAIL_COND_V_MSG(err != OK, state, "Unable to encode object state.");
  564. state.resize(len);
  565. _encode_state(state_vars, state.ptrw(), len);
  566. return state;
  567. }
  568. Error MultiplayerReplicator::decode_state(const ResourceUID::ID &p_scene_id, Object *p_obj, const PackedByteArray p_data, bool p_initial) {
  569. ERR_FAIL_COND_V_MSG(!replications.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
  570. const SceneConfig &cfg = replications[p_scene_id];
  571. const List<StringName> props = p_initial ? cfg.properties : cfg.sync_properties;
  572. int size;
  573. return _decode_state(props, p_obj, p_data.ptr(), p_data.size(), size);
  574. }
  575. void MultiplayerReplicator::scene_enter_exit_notify(const String &p_scene, Node *p_node, bool p_enter) {
  576. if (!multiplayer->has_network_peer()) {
  577. return;
  578. }
  579. Node *root_node = multiplayer->get_root_node();
  580. ERR_FAIL_COND(!p_node || !p_node->get_parent() || !root_node);
  581. NodePath path = (root_node->get_path()).rel_path_to(p_node->get_parent()->get_path());
  582. if (path.is_empty()) {
  583. return;
  584. }
  585. ResourceUID::ID id = ResourceLoader::get_resource_uid(p_scene);
  586. if (!replications.has(id)) {
  587. return;
  588. }
  589. const SceneConfig &cfg = replications[id];
  590. if (p_enter) {
  591. if (cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server()) {
  592. replicated_nodes[p_node->get_instance_id()] = id;
  593. _track(id, p_node);
  594. spawn(id, p_node, 0);
  595. }
  596. emit_signal(SNAME("replicated_instance_added"), id, p_node);
  597. } else {
  598. if (cfg.mode == REPLICATION_MODE_SERVER && multiplayer->is_network_server() && replicated_nodes.has(p_node->get_instance_id())) {
  599. replicated_nodes.erase(p_node->get_instance_id());
  600. _untrack(id, p_node);
  601. despawn(id, p_node, 0);
  602. }
  603. emit_signal(SNAME("replicated_instance_removed"), id, p_node);
  604. }
  605. }
  606. void MultiplayerReplicator::spawn_all(int p_peer) {
  607. for (const KeyValue<ObjectID, ResourceUID::ID> &E : replicated_nodes) {
  608. // Only server mode adds to replicated_nodes, no need to check it.
  609. Object *obj = ObjectDB::get_instance(E.key);
  610. ERR_CONTINUE(!obj);
  611. Node *node = Object::cast_to<Node>(obj);
  612. ERR_CONTINUE(!node);
  613. spawn(E.value, node, p_peer);
  614. }
  615. }
  616. void MultiplayerReplicator::poll() {
  617. for (KeyValue<ResourceUID::ID, SceneConfig> &E : replications) {
  618. if (!E.value.sync_interval) {
  619. continue;
  620. }
  621. if (E.value.mode == REPLICATION_MODE_SERVER && !multiplayer->is_network_server()) {
  622. continue;
  623. }
  624. uint64_t time = OS::get_singleton()->get_ticks_usec();
  625. if (E.value.sync_last + E.value.sync_interval <= time) {
  626. sync_all(E.key, 0);
  627. E.value.sync_last = time;
  628. }
  629. // Handle wrapping.
  630. if (E.value.sync_last > time) {
  631. E.value.sync_last = time;
  632. }
  633. }
  634. }
  635. void MultiplayerReplicator::track(const ResourceUID::ID &p_scene_id, Object *p_obj) {
  636. ERR_FAIL_COND(!replications.has(p_scene_id));
  637. const SceneConfig &cfg = replications[p_scene_id];
  638. ERR_FAIL_COND_MSG(cfg.mode == REPLICATION_MODE_SERVER, "Manual object tracking is not allowed in server mode.");
  639. _track(p_scene_id, p_obj);
  640. }
  641. void MultiplayerReplicator::_track(const ResourceUID::ID &p_scene_id, Object *p_obj) {
  642. ERR_FAIL_COND(!p_obj);
  643. ERR_FAIL_COND(!replications.has(p_scene_id));
  644. if (!tracked_objects.has(p_scene_id)) {
  645. tracked_objects[p_scene_id] = List<ObjectID>();
  646. }
  647. tracked_objects[p_scene_id].push_back(p_obj->get_instance_id());
  648. }
  649. void MultiplayerReplicator::untrack(const ResourceUID::ID &p_scene_id, Object *p_obj) {
  650. ERR_FAIL_COND(!replications.has(p_scene_id));
  651. const SceneConfig &cfg = replications[p_scene_id];
  652. ERR_FAIL_COND_MSG(cfg.mode == REPLICATION_MODE_SERVER, "Manual object tracking is not allowed in server mode.");
  653. _untrack(p_scene_id, p_obj);
  654. }
  655. void MultiplayerReplicator::_untrack(const ResourceUID::ID &p_scene_id, Object *p_obj) {
  656. ERR_FAIL_COND(!p_obj);
  657. ERR_FAIL_COND(!replications.has(p_scene_id));
  658. if (tracked_objects.has(p_scene_id)) {
  659. tracked_objects[p_scene_id].erase(p_obj->get_instance_id());
  660. }
  661. }
  662. Error MultiplayerReplicator::sync_all(const ResourceUID::ID &p_scene_id, int p_peer) {
  663. ERR_FAIL_COND_V(!replications.has(p_scene_id), ERR_INVALID_PARAMETER);
  664. if (!tracked_objects.has(p_scene_id)) {
  665. return OK;
  666. }
  667. const SceneConfig &cfg = replications[p_scene_id];
  668. if (cfg.on_sync_send.is_valid()) {
  669. Array objs;
  670. if (tracked_objects.has(p_scene_id)) {
  671. objs.resize(tracked_objects[p_scene_id].size());
  672. int idx = 0;
  673. for (const ObjectID &obj_id : tracked_objects[p_scene_id]) {
  674. objs[idx++] = ObjectDB::get_instance(obj_id);
  675. }
  676. }
  677. Variant args[3] = { p_scene_id, objs, p_peer };
  678. Variant *argp[3] = { args, &args[1], &args[2] };
  679. Callable::CallError ce;
  680. Variant ret;
  681. cfg.on_sync_send.call((const Variant **)argp, 3, ret, ce);
  682. ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, FAILED, "Custom sync function failed");
  683. return OK;
  684. } else if (cfg.sync_properties.size()) {
  685. return _sync_all_default(p_scene_id, p_peer);
  686. }
  687. return OK;
  688. }
  689. Error MultiplayerReplicator::send_sync(int p_peer_id, const ResourceUID::ID &p_scene_id, PackedByteArray p_data, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel) {
  690. ERR_FAIL_COND_V(!multiplayer->has_network_peer(), ERR_UNCONFIGURED);
  691. ERR_FAIL_COND_V(!replications.has(p_scene_id), ERR_INVALID_PARAMETER);
  692. const SceneConfig &cfg = replications[p_scene_id];
  693. ERR_FAIL_COND_V_MSG(!cfg.on_sync_send.is_valid(), ERR_UNCONFIGURED, "Sending raw sync messages is only available with custom functions");
  694. MAKE_ROOM(SYNC_CMD_OFFSET + p_data.size());
  695. uint8_t *ptr = packet_cache.ptrw();
  696. ptr[0] = MultiplayerAPI::NETWORK_COMMAND_SYNC;
  697. encode_uint64(p_scene_id, &ptr[1]);
  698. Ref<MultiplayerPeer> network_peer = multiplayer->get_network_peer();
  699. network_peer->set_target_peer(p_peer_id);
  700. network_peer->set_transfer_channel(p_channel);
  701. network_peer->set_transfer_mode(p_transfer_mode);
  702. return network_peer->put_packet(ptr, SYNC_CMD_OFFSET + p_data.size());
  703. }
  704. void MultiplayerReplicator::clear() {
  705. tracked_objects.clear();
  706. replicated_nodes.clear();
  707. }
  708. void MultiplayerReplicator::_bind_methods() {
  709. ClassDB::bind_method(D_METHOD("spawn_config", "scene_id", "spawn_mode", "properties", "custom_send", "custom_receive"), &MultiplayerReplicator::spawn_config, DEFVAL(TypedArray<StringName>()), DEFVAL(Callable()), DEFVAL(Callable()));
  710. ClassDB::bind_method(D_METHOD("sync_config", "scene_id", "interval", "properties", "custom_send", "custom_receive"), &MultiplayerReplicator::sync_config, DEFVAL(TypedArray<StringName>()), DEFVAL(Callable()), DEFVAL(Callable()));
  711. ClassDB::bind_method(D_METHOD("despawn", "scene_id", "object", "peer_id"), &MultiplayerReplicator::despawn, DEFVAL(0));
  712. ClassDB::bind_method(D_METHOD("spawn", "scene_id", "object", "peer_id"), &MultiplayerReplicator::spawn, DEFVAL(0));
  713. ClassDB::bind_method(D_METHOD("send_despawn", "peer_id", "scene_id", "data", "path"), &MultiplayerReplicator::send_despawn, DEFVAL(Variant()), DEFVAL(NodePath()));
  714. ClassDB::bind_method(D_METHOD("send_spawn", "peer_id", "scene_id", "data", "path"), &MultiplayerReplicator::send_spawn, DEFVAL(Variant()), DEFVAL(NodePath()));
  715. ClassDB::bind_method(D_METHOD("send_sync", "peer_id", "scene_id", "data", "transfer_mode", "channel"), &MultiplayerReplicator::send_sync, DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
  716. ClassDB::bind_method(D_METHOD("sync_all", "scene_id", "peer_id"), &MultiplayerReplicator::sync_all, DEFVAL(0));
  717. ClassDB::bind_method(D_METHOD("track", "scene_id", "object"), &MultiplayerReplicator::track);
  718. ClassDB::bind_method(D_METHOD("untrack", "scene_id", "object"), &MultiplayerReplicator::untrack);
  719. ClassDB::bind_method(D_METHOD("encode_state", "scene_id", "object", "initial"), &MultiplayerReplicator::encode_state, DEFVAL(true));
  720. ClassDB::bind_method(D_METHOD("decode_state", "scene_id", "object", "data", "initial"), &MultiplayerReplicator::decode_state, DEFVAL(true));
  721. ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  722. ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  723. ADD_SIGNAL(MethodInfo("despawn_requested", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
  724. ADD_SIGNAL(MethodInfo("spawn_requested", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
  725. ADD_SIGNAL(MethodInfo("replicated_instance_added", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  726. ADD_SIGNAL(MethodInfo("replicated_instance_removed", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
  727. BIND_ENUM_CONSTANT(REPLICATION_MODE_NONE);
  728. BIND_ENUM_CONSTANT(REPLICATION_MODE_SERVER);
  729. BIND_ENUM_CONSTANT(REPLICATION_MODE_CUSTOM);
  730. }