Browse Source

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).
Fabio Alessandrelli 7 years ago
parent
commit
348725dfe0
4 changed files with 26 additions and 6 deletions
  1. 4 5
      doc/classes/MultiplayerAPI.xml
  2. 4 0
      doc/classes/SceneTree.xml
  3. 15 1
      scene/main/scene_tree.cpp
  4. 3 0
      scene/main/scene_tree.h

+ 4 - 5
doc/classes/MultiplayerAPI.xml

@@ -60,9 +60,8 @@
 			<return type="void">
 			</return>
 			<description>
-				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]).
 			</description>
 		</method>
 		<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.
 		</constant>
 		<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 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].
@@ -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].
 		</constant>
 		<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 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.

+ 4 - 0
doc/classes/SceneTree.xml

@@ -269,6 +269,10 @@
 		<member name="multiplayer" type="MultiplayerAPI" setter="set_multiplayer" getter="get_multiplayer">
 			The default [MultiplayerAPI] instance for this SceneTree.
 		</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">
 			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>

+ 15 - 1
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<MultiplayerAPI> 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<MultiplayerAPI> 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<World>(memnew(World)));
 
 	// Initialize network state
+	multiplayer_poll = true;
 	set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
 
 	//root->set_world_2d( Ref<World2D>( memnew( World2D )));

+ 3 - 0
scene/main/scene_tree.h

@@ -186,6 +186,7 @@ private:
 	///network///
 
 	Ref<MultiplayerAPI> 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<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_network_peer(const Ref<NetworkedMultiplayerPeer> &p_network_peer);
 	Ref<NetworkedMultiplayerPeer> get_network_peer() const;