Add option to disable automatic multiplayer poll

Automatic poll from SceneTree is enabled by default.
This allows for polling (and thus RPCs/RSETs) manually in other loops
(e.g. physics, thread, specific step) and for proper mutex protecion
when accessing the multiplayer API from threads (e.g. for sending larger
files in chunks).
This commit is contained in:
Fabio Alessandrelli 2018-06-02 14:32:30 +02:00
parent 8684b63118
commit 348725dfe0
4 changed files with 26 additions and 6 deletions

View file

@ -60,9 +60,8 @@
<return type="void"> <return type="void">
</return> </return>
<description> <description>
Method used for polling the MultiplayerAPI. Method used for polling the MultiplayerAPI. You only need to worry about this if you are using [member Node.custom_multiplayer] override or you set [member SceneTree.multiplayer_poll] to [code]false[/code]. By default [SceneTree] will poll its MultiplayerAPI for you.
You only need to worry about this if you are using [member Node.custom_multiplayer] override. NOTE: This method results in RPCs and RSETs being called, so they will be executed in the same context of this function (e.g. [code]_process[/code], [code]physics[/code], [Thread]).
SceneTree will poll the default MultiplayerAPI for you.
</description> </description>
</method> </method>
<method name="send_bytes"> <method name="send_bytes">
@ -143,7 +142,7 @@
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 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.
</constant> </constant>
<constant name="RPC_MODE_SYNC" value="2" enum="RPCMode"> <constant name="RPC_MODE_SYNC" value="2" enum="RPCMode">
Behave like [constant RPC_MODE_REMOTE] but also make the call or property change locally. Analogous to the [code]sync[/code] keyword. Behave like [code]RPC_MODE_REMOTE[/code] but also make the call or property change locally. Analogous to the [code]sync[/code] keyword.
</constant> </constant>
<constant name="RPC_MODE_MASTER" value="3" enum="RPCMode"> <constant name="RPC_MODE_MASTER" value="3" enum="RPCMode">
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 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].
@ -152,7 +151,7 @@
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]. 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].
</constant> </constant>
<constant name="RPC_MODE_REMOTESYNC" value="5" enum="RPCMode"> <constant name="RPC_MODE_REMOTESYNC" value="5" enum="RPCMode">
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_REMOTE[/code] but also make the call or property change locally. Same as [code]RPC_MODE_SYNC[/code] which is only kept for compatibility. Analogous to the [code]remotesync[/code] keyword.
</constant> </constant>
<constant name="RPC_MODE_MASTERSYNC" value="6" enum="RPCMode"> <constant name="RPC_MODE_MASTERSYNC" value="6" enum="RPCMode">
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_MASTER[/code] but also make the call or property change locally. Analogous to the [code]mastersync[/code] keyword.

View file

@ -269,6 +269,10 @@
<member name="multiplayer" type="MultiplayerAPI" setter="set_multiplayer" getter="get_multiplayer"> <member name="multiplayer" type="MultiplayerAPI" setter="set_multiplayer" getter="get_multiplayer">
The default [MultiplayerAPI] instance for this SceneTree. The default [MultiplayerAPI] instance for this SceneTree.
</member> </member>
<member name="multiplayer_poll" type="bool" setter="set_multiplayer_poll_enabled" getter="is_multiplayer_poll_enabled">
If [code]true[/code] (default) enable the automatic polling of the [MultiplayerAPI] for this SceneTree during [signal idle_frame].
When [code]false[/code] you need to manually call [method MultiplayerAPI.poll] for processing network packets and delivering RPCs/RSETs. This allows to run RPCs/RSETs in a different loop (e.g. physics, thread, specific time step) and for manual [Mutex] protecion when accessing the [MultiplayerAPI] from threads.
</member>
<member name="network_peer" type="NetworkedMultiplayerPeer" setter="set_network_peer" getter="get_network_peer"> <member name="network_peer" type="NetworkedMultiplayerPeer" setter="set_network_peer" getter="get_network_peer">
The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the SceneTree will become a network server (check with [method is_network_server()]) and will set root node's network mode to master (see NETWORK_MODE_* constants in [Node]), or it will become a regular peer with root node set to slave. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to SceneTree's signals. The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the SceneTree will become a network server (check with [method is_network_server()]) and will set root node's network mode to master (see NETWORK_MODE_* constants in [Node]), or it will become a regular peer with root node set to slave. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to SceneTree's signals.
</member> </member>

View file

@ -485,7 +485,9 @@ bool SceneTree::idle(float p_time) {
idle_process_time = p_time; idle_process_time = p_time;
if (multiplayer_poll) {
multiplayer->poll(); multiplayer->poll();
}
emit_signal("idle_frame"); emit_signal("idle_frame");
@ -1672,6 +1674,14 @@ Ref<MultiplayerAPI> SceneTree::get_multiplayer() const {
return multiplayer; return multiplayer;
} }
void SceneTree::set_multiplayer_poll_enabled(bool p_enabled) {
multiplayer_poll = p_enabled;
}
bool SceneTree::is_multiplayer_poll_enabled() const {
return multiplayer_poll;
}
void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { void SceneTree::set_multiplayer(Ref<MultiplayerAPI> p_multiplayer) {
ERR_FAIL_COND(!p_multiplayer.is_valid()); ERR_FAIL_COND(!p_multiplayer.is_valid());
@ -1802,6 +1812,8 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer); ClassDB::bind_method(D_METHOD("set_multiplayer", "multiplayer"), &SceneTree::set_multiplayer);
ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer); ClassDB::bind_method(D_METHOD("get_multiplayer"), &SceneTree::get_multiplayer);
ClassDB::bind_method(D_METHOD("set_multiplayer_poll_enabled", "enabled"), &SceneTree::set_multiplayer_poll_enabled);
ClassDB::bind_method(D_METHOD("is_multiplayer_poll_enabled"), &SceneTree::is_multiplayer_poll_enabled);
ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer); ClassDB::bind_method(D_METHOD("set_network_peer", "peer"), &SceneTree::set_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer); ClassDB::bind_method(D_METHOD("get_network_peer"), &SceneTree::get_network_peer);
ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server); ClassDB::bind_method(D_METHOD("is_network_server"), &SceneTree::is_network_server);
@ -1830,6 +1842,7 @@ void SceneTree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_multiplayer", "get_multiplayer"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_multiplayer", "get_multiplayer");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled");
ADD_SIGNAL(MethodInfo("tree_changed")); ADD_SIGNAL(MethodInfo("tree_changed"));
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node"))); ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node")));
@ -1934,6 +1947,7 @@ SceneTree::SceneTree() {
root->set_world(Ref<World>(memnew(World))); root->set_world(Ref<World>(memnew(World)));
// Initialize network state // Initialize network state
multiplayer_poll = true;
set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI))); set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
//root->set_world_2d( Ref<World2D>( memnew( World2D ))); //root->set_world_2d( Ref<World2D>( memnew( World2D )));

View file

@ -186,6 +186,7 @@ private:
///network/// ///network///
Ref<MultiplayerAPI> multiplayer; Ref<MultiplayerAPI> multiplayer;
bool multiplayer_poll;
void _network_peer_connected(int p_id); void _network_peer_connected(int p_id);
void _network_peer_disconnected(int p_id); void _network_peer_disconnected(int p_id);
@ -411,6 +412,8 @@ public:
//network API //network API
Ref<MultiplayerAPI> get_multiplayer() const; Ref<MultiplayerAPI> get_multiplayer() const;
void set_multiplayer_poll_enabled(bool p_enabled);
bool is_multiplayer_poll_enabled() const;
void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer); void set_multiplayer(Ref<MultiplayerAPI> p_multiplayer);
void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer); void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer);
Ref<NetworkedMultiplayerPeer> get_network_peer() const; Ref<NetworkedMultiplayerPeer> get_network_peer() const;