Skip to content

Commit

Permalink
[MP] Fix broken RPCs after dictionary keys type change
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Faless committed Sep 12, 2024
1 parent 83d54ab commit 32e4ab9
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
12 changes: 11 additions & 1 deletion modules/multiplayer/scene_rpc_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,24 @@ 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;
}
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();
Expand Down
2 changes: 2 additions & 0 deletions modules/multiplayer/scene_rpc_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class SceneRPCInterface : public RefCounted {
#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);
Expand Down

0 comments on commit 32e4ab9

Please sign in to comment.