From 1400f6fdc444650ebf37c83bb4164e25e641bab1 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 13 May 2018 07:07:56 +0200 Subject: Refactor RPCMode enum and checks --- core/io/multiplayer_api.cpp | 147 +++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 64 deletions(-) (limited to 'core/io/multiplayer_api.cpp') diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index b0f2ca754..de98a195e 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -32,6 +32,55 @@ #include "core/io/marshalls.h" #include "scene/main/node.h" +_FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) { + + switch (mode) { + + case MultiplayerAPI::RPC_MODE_DISABLED: { + //do nothing + } break; + case MultiplayerAPI::RPC_MODE_REMOTE: { + //do nothing also, no need to call local + } break; + case MultiplayerAPI::RPC_MODE_SYNC: { + //call it, sync always results in call + return true; + } break; + case MultiplayerAPI::RPC_MODE_MASTER: { + if (is_master) + r_skip_rpc = true; //no other master so.. + return is_master; + } break; + case MultiplayerAPI::RPC_MODE_SLAVE: { + return !is_master; + } break; + } + return false; +} + +_FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) { + switch (mode) { + + case MultiplayerAPI::RPC_MODE_DISABLED: { + return false; + } break; + case MultiplayerAPI::RPC_MODE_REMOTE: { + return true; + } break; + case MultiplayerAPI::RPC_MODE_SYNC: { + return true; + } break; + case MultiplayerAPI::RPC_MODE_MASTER: { + return p_node->is_network_master(); + } break; + case MultiplayerAPI::RPC_MODE_SLAVE: { + return !p_node->is_network_master() && p_remote_id == p_node->get_network_master(); + } break; + } + + return false; +} + void MultiplayerAPI::poll() { if (!network_peer.is_valid() || network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) @@ -202,11 +251,19 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, int } void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - if (!p_node->can_call_rpc(p_name, p_from)) - return; ERR_FAIL_COND(p_offset >= p_packet_len); + // Check that remote can call the RPC on this node + RPCMode rpc_mode = RPC_MODE_DISABLED; + const Map::Element *E = p_node->get_node_rpc_mode(p_name); + if (E) { + rpc_mode = E->get(); + } else if (p_node->get_script_instance()) { + rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_name); + } + ERR_FAIL_COND(!_can_call_mode(p_node, rpc_mode, p_from)); + int argc = p_packet[p_offset]; Vector args; Vector argp; @@ -238,11 +295,18 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const StringName &p_name, int p_ void MultiplayerAPI::_process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - if (!p_node->can_call_rset(p_name, p_from)) - return; - ERR_FAIL_COND(p_offset >= p_packet_len); + // Check that remote can call the RSET on this node + RPCMode rset_mode = RPC_MODE_DISABLED; + const Map::Element *E = p_node->get_node_rset_mode(p_name); + if (E) { + rset_mode = E->get(); + } else if (p_node->get_script_instance()) { + rset_mode = p_node->get_script_instance()->get_rset_mode(p_name); + } + ERR_FAIL_COND(!_can_call_mode(p_node, rset_mode, p_from)); + Variant value; decode_variant(value, &p_packet[p_offset], p_packet_len - p_offset); @@ -522,57 +586,6 @@ void MultiplayerAPI::_server_disconnected() { emit_signal("server_disconnected"); } -bool _should_call_native(Node::RPCMode mode, bool is_master, bool &r_skip_rpc) { - - switch (mode) { - - case Node::RPC_MODE_DISABLED: { - //do nothing - } break; - case Node::RPC_MODE_REMOTE: { - //do nothing also, no need to call local - } break; - case Node::RPC_MODE_SYNC: { - //call it, sync always results in call - return true; - } break; - case Node::RPC_MODE_MASTER: { - if (is_master) - r_skip_rpc = true; //no other master so.. - return is_master; - } break; - case Node::RPC_MODE_SLAVE: { - return !is_master; - } break; - } - return false; -} - -bool _should_call_script(ScriptInstance::RPCMode mode, bool is_master, bool &r_skip_rpc) { - switch (mode) { - - case ScriptInstance::RPC_MODE_DISABLED: { - //do nothing - } break; - case ScriptInstance::RPC_MODE_REMOTE: { - //do nothing also, no need to call local - } break; - case ScriptInstance::RPC_MODE_SYNC: { - //call it, sync always results in call - return true; - } break; - case ScriptInstance::RPC_MODE_MASTER: { - if (is_master) - r_skip_rpc = true; //no other master so.. - return is_master; - } break; - case ScriptInstance::RPC_MODE_SLAVE: { - return !is_master; - } break; - } - return false; -} - void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) { ERR_FAIL_COND(!p_node->is_inside_tree()); @@ -587,17 +600,17 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const if (p_peer_id == 0 || p_peer_id == node_id || (p_peer_id < 0 && p_peer_id != -node_id)) { //check that send mode can use local call - const Map::Element *E = p_node->get_node_rpc_mode(p_method); + const Map::Element *E = p_node->get_node_rpc_mode(p_method); if (E) { - call_local_native = _should_call_native(E->get(), is_master, skip_rpc); + call_local_native = _should_call_local(E->get(), is_master, skip_rpc); } if (call_local_native) { // done below } else if (p_node->get_script_instance()) { //attempt with script - ScriptInstance::RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); - call_local_script = _should_call_script(rpc_mode, is_master, skip_rpc); + RPCMode rpc_mode = p_node->get_script_instance()->get_rpc_mode(p_method); + call_local_script = _should_call_local(rpc_mode, is_master, skip_rpc); } } @@ -643,10 +656,10 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const bool set_local = false; - const Map::Element *E = p_node->get_node_rset_mode(p_property); + const Map::Element *E = p_node->get_node_rset_mode(p_property); if (E) { - set_local = _should_call_native(E->get(), is_master, skip_rset); + set_local = _should_call_local(E->get(), is_master, skip_rset); } if (set_local) { @@ -660,9 +673,9 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const } } else if (p_node->get_script_instance()) { //attempt with script - ScriptInstance::RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); + RPCMode rpc_mode = p_node->get_script_instance()->get_rset_mode(p_property); - set_local = _should_call_script(rpc_mode, is_master, skip_rset); + set_local = _should_call_local(rpc_mode, is_master, skip_rset); if (set_local) { @@ -778,6 +791,12 @@ void MultiplayerAPI::_bind_methods() { ADD_SIGNAL(MethodInfo("connected_to_server")); ADD_SIGNAL(MethodInfo("connection_failed")); ADD_SIGNAL(MethodInfo("server_disconnected")); + + BIND_ENUM_CONSTANT(RPC_MODE_DISABLED); + BIND_ENUM_CONSTANT(RPC_MODE_REMOTE); + BIND_ENUM_CONSTANT(RPC_MODE_SYNC); + BIND_ENUM_CONSTANT(RPC_MODE_MASTER); + BIND_ENUM_CONSTANT(RPC_MODE_SLAVE); } MultiplayerAPI::MultiplayerAPI() { -- cgit v1.2.3-70-g09d2 From 4524153b6ece766e496d7b9c1a4f9216ea9e34cc Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sat, 26 May 2018 10:28:28 +0200 Subject: New sync RPC modes to match all combinations --- core/io/multiplayer_api.cpp | 9 +++++++++ core/io/multiplayer_api.h | 3 +++ doc/classes/MultiplayerAPI.xml | 17 +++++++++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'core/io/multiplayer_api.cpp') diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index de98a195e..846c89510 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -42,6 +42,9 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas case MultiplayerAPI::RPC_MODE_REMOTE: { //do nothing also, no need to call local } break; + case MultiplayerAPI::RPC_MODE_REMOTESYNC: + case MultiplayerAPI::RPC_MODE_MASTERSYNC: + case MultiplayerAPI::RPC_MODE_SLAVESYNC: case MultiplayerAPI::RPC_MODE_SYNC: { //call it, sync always results in call return true; @@ -67,12 +70,15 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, i case MultiplayerAPI::RPC_MODE_REMOTE: { return true; } break; + case MultiplayerAPI::RPC_MODE_REMOTESYNC: case MultiplayerAPI::RPC_MODE_SYNC: { return true; } break; + case MultiplayerAPI::RPC_MODE_MASTERSYNC: case MultiplayerAPI::RPC_MODE_MASTER: { return p_node->is_network_master(); } break; + case MultiplayerAPI::RPC_MODE_SLAVESYNC: case MultiplayerAPI::RPC_MODE_SLAVE: { return !p_node->is_network_master() && p_remote_id == p_node->get_network_master(); } break; @@ -797,6 +803,9 @@ void MultiplayerAPI::_bind_methods() { BIND_ENUM_CONSTANT(RPC_MODE_SYNC); BIND_ENUM_CONSTANT(RPC_MODE_MASTER); BIND_ENUM_CONSTANT(RPC_MODE_SLAVE); + BIND_ENUM_CONSTANT(RPC_MODE_REMOTESYNC); + BIND_ENUM_CONSTANT(RPC_MODE_MASTERSYNC); + BIND_ENUM_CONSTANT(RPC_MODE_SLAVESYNC); } MultiplayerAPI::MultiplayerAPI() { diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index f9284a0bd..ef56c4c7f 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -94,6 +94,9 @@ public: RPC_MODE_SYNC, // Using rpc() on it will call method / set property in all remote peers and locally RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote RPC_MODE_SLAVE, // Using rpc() on it will call method for all slaves + RPC_MODE_REMOTESYNC, // Same as RPC_MODE_SYNC, compatibility + RPC_MODE_MASTERSYNC, // Using rpc() on it will call method / set property in the master peer and locally + RPC_MODE_SLAVESYNC, // Using rpc() on it will call method / set property in all slave peers and locally }; void poll(); diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index 21a13c15d..31904631a 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -140,16 +140,25 @@ Used with [method Node.rpc_config] or [method Node.rset_config] to disable a method or property for all RPC calls, making it unavailable. Default for all methods. - Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. + Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the remote end, not locally. Analogous to the [code]remote[/code] keyword. Calls and property changes are accepted from all remote peers, no matter if they are node's master or slaves. - Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed both on the remote end and locally. Analogous to the [code]sync[/code] keyword. + Behave like [constant RPC_MODE_REMOTE] but also make the call or property change locally. Analogous to the [code]sync[/code] keyword. - Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. See [method Node.set_network_master]. + Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on the network master for this node. Analogous to the [code]master[/code] keyword. Only accepts calls or property changes from the node's network slaves, see [method Node.set_network_master]. - Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on slaves for this node. Analogous to the [code]slave[/code] keyword. See [method Node.set_network_master]. + Used with [method Node.rpc_config] or [method Node.rset_config] to set a method to be called or a property to be changed only on slaves for this node. Analogous to the [code]slave[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master]. + + + Behave like [code]RPC_MODE_REMOTE[/code] but also make the call or property change locally. Same as [constant RPC_MODE_SYNC] which is only kept for compatibility. Analogous to the [code]remotesync[/code] keyword. + + + Behave like [code]RPC_MODE_MASTER[/code] but also make the call or property change locally. Analogous to the [code]mastersync[/code] keyword. + + + Behave like [code]RPC_MODE_SLAVE[/code] but also make the call or property change locally. Analogous to the [code]slavesync[/code] keyword. -- cgit v1.2.3-70-g09d2