summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2024-09-12 16:38:14 +0200
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2024-09-12 16:38:14 +0200
commit32e4ab91e8d1b266990ca98b5ec1ead19a1a1dd5 (patch)
treef16cc57006605e3df7ff277bf4980227d5c1b888
parent83d54ab2ad476ae265b323c2b88f4623b922f4c6 (diff)
downloadredot-engine-32e4ab91e8d1b266990ca98b5ec1ead19a1a1dd5.tar.gz
[MP] Fix broken RPCs after dictionary keys type change
As part of RPCs processing, they need to be sorted reliably across all peers, so that unique IDs can be assigned to greatly optimize the network layer. The RPC configuration nodes are stored in dictionaries which, until recently, always casted StringName keys to String. Since method names (keys) in the RPC configuration were StringName, a side effect of the above change is that sorting the dictionary keys no longer sort them alphabetically by default (StringName are compared using their pointers). This commit changes the RPC processing logic to use sort_custom to provide a function that can handle the StringName comparison.
-rw-r--r--modules/multiplayer/scene_rpc_interface.cpp12
-rw-r--r--modules/multiplayer/scene_rpc_interface.h2
2 files changed, 13 insertions, 1 deletions
diff --git a/modules/multiplayer/scene_rpc_interface.cpp b/modules/multiplayer/scene_rpc_interface.cpp
index 592bb18a71..69bb19c01c 100644
--- a/modules/multiplayer/scene_rpc_interface.cpp
+++ b/modules/multiplayer/scene_rpc_interface.cpp
@@ -73,6 +73,16 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) {
}
}
+bool SceneRPCInterface::_sort_rpc_names(const Variant &p_l, const Variant &p_r) {
+ if (likely(p_l.is_string() && p_r.is_string())) {
+ return p_l.operator String() < p_r.operator String();
+ }
+ bool valid = false;
+ Variant res;
+ Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid);
+ return valid ? res.operator bool() : false;
+}
+
void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_node, RPCConfigCache &r_cache) {
if (p_config.get_type() == Variant::NIL) {
return;
@@ -80,7 +90,7 @@ void SceneRPCInterface::_parse_rpc_config(const Variant &p_config, bool p_for_no
ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY);
const Dictionary config = p_config;
Array names = config.keys();
- names.sort(); // Ensure ID order
+ names.sort_custom(callable_mp_static(&SceneRPCInterface::_sort_rpc_names)); // Ensure ID order
for (int i = 0; i < names.size(); i++) {
ERR_CONTINUE(!names[i].is_string());
String name = names[i].operator String();
diff --git a/modules/multiplayer/scene_rpc_interface.h b/modules/multiplayer/scene_rpc_interface.h
index 5c9b66d5f5..852cef7830 100644
--- a/modules/multiplayer/scene_rpc_interface.h
+++ b/modules/multiplayer/scene_rpc_interface.h
@@ -91,6 +91,8 @@ private:
#endif
protected:
+ static bool _sort_rpc_names(const Variant &p_l, const Variant &p_r);
+
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const RPCConfig &p_config, const StringName &p_name, const Variant **p_arg, int p_argcount);