From 348725dfe0685a5467b91928929385ffe9ab98b7 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sat, 2 Jun 2018 14:32:30 +0200 Subject: [PATCH] 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). --- doc/classes/MultiplayerAPI.xml | 9 ++++----- doc/classes/SceneTree.xml | 4 ++++ scene/main/scene_tree.cpp | 16 +++++++++++++++- scene/main/scene_tree.h | 3 +++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml index 31904631a9e..8c114a55c92 100644 --- a/doc/classes/MultiplayerAPI.xml +++ b/doc/classes/MultiplayerAPI.xml @@ -60,9 +60,8 @@ - Method used for polling the MultiplayerAPI. - You only need to worry about this if you are using [member Node.custom_multiplayer] override. - SceneTree will poll the default MultiplayerAPI for you. + 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. + 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]). @@ -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. - 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. 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]. - 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. Behave like [code]RPC_MODE_MASTER[/code] but also make the call or property change locally. Analogous to the [code]mastersync[/code] keyword. diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index b2cde861c8c..7c8feae5b3c 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -269,6 +269,10 @@ The default [MultiplayerAPI] instance for this SceneTree. + + 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. + 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. diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 607dbebf6cb..8d6e57b3355 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -485,7 +485,9 @@ bool SceneTree::idle(float p_time) { idle_process_time = p_time; - multiplayer->poll(); + if (multiplayer_poll) { + multiplayer->poll(); + } emit_signal("idle_frame"); @@ -1672,6 +1674,14 @@ Ref SceneTree::get_multiplayer() const { 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 p_multiplayer) { 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("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("get_network_peer"), &SceneTree::get_network_peer); 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, "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::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node"))); @@ -1934,6 +1947,7 @@ SceneTree::SceneTree() { root->set_world(Ref(memnew(World))); // Initialize network state + multiplayer_poll = true; set_multiplayer(Ref(memnew(MultiplayerAPI))); //root->set_world_2d( Ref( memnew( World2D ))); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 6e0156546e4..aa8d78b1e13 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -186,6 +186,7 @@ private: ///network/// Ref multiplayer; + bool multiplayer_poll; void _network_peer_connected(int p_id); void _network_peer_disconnected(int p_id); @@ -411,6 +412,8 @@ public: //network API Ref get_multiplayer() const; + void set_multiplayer_poll_enabled(bool p_enabled); + bool is_multiplayer_poll_enabled() const; void set_multiplayer(Ref p_multiplayer); void set_network_peer(const Ref &p_network_peer); Ref get_network_peer() const;