Merge pull request #18823 from Faless/multiplayer_raw

Allow sending raw bytes via the Multiplayer API
This commit is contained in:
Max Hilbrunner 2018-05-12 23:50:26 +02:00 committed by GitHub
commit ca10cb6eea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 11 deletions

View file

@ -76,7 +76,7 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND(root_node == NULL); ERR_FAIL_COND(root_node == NULL);
ERR_FAIL_COND(p_packet_len < 5); ERR_FAIL_COND(p_packet_len < 1);
uint8_t packet_type = p_packet[0]; uint8_t packet_type = p_packet[0];
@ -123,6 +123,11 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
} }
} break; } break;
case NETWORK_COMMAND_RAW: {
_process_raw(p_from, p_packet, p_packet_len);
} break;
} }
} }
@ -259,6 +264,8 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) { void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND(p_packet_len < 2);
String paths; String paths;
paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1); paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);
@ -648,6 +655,34 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
_send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1); _send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
} }
Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to) {
ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);
MAKE_ROOM(p_data.size() + 1);
PoolVector<uint8_t>::Read r = p_data.read();
packet_cache[0] = NETWORK_COMMAND_RAW;
memcpy(&packet_cache[1], &r[0], p_data.size());
network_peer->set_target_peer(p_to);
return network_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
}
void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND(p_packet_len < 2);
PoolVector<uint8_t> out;
int len = p_packet_len - 1;
out.resize(len);
{
PoolVector<uint8_t>::Write w = out.write();
memcpy(&w[0], &p_packet[1], len);
}
emit_signal("network_peer_packet", p_from, out);
}
int MultiplayerAPI::get_network_unique_id() const { int MultiplayerAPI::get_network_unique_id() const {
ERR_FAIL_COND_V(!network_peer.is_valid(), 0); ERR_FAIL_COND_V(!network_peer.is_valid(), 0);
@ -686,6 +721,7 @@ Vector<int> MultiplayerAPI::get_network_connected_peers() const {
void MultiplayerAPI::_bind_methods() { void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node); ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST));
ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer); ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer); ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer);
ClassDB::bind_method(D_METHOD("get_network_unique_id"), &MultiplayerAPI::get_network_unique_id); ClassDB::bind_method(D_METHOD("get_network_unique_id"), &MultiplayerAPI::get_network_unique_id);
@ -708,6 +744,7 @@ void MultiplayerAPI::_bind_methods() {
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id"))); ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "packet")));
ADD_SIGNAL(MethodInfo("connected_to_server")); ADD_SIGNAL(MethodInfo("connected_to_server"));
ADD_SIGNAL(MethodInfo("connection_failed")); ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL(MethodInfo("server_disconnected")); ADD_SIGNAL(MethodInfo("server_disconnected"));

View file

@ -43,6 +43,7 @@ protected:
Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len); Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset); void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount); void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_from); bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_from);
@ -53,6 +54,7 @@ public:
NETWORK_COMMAND_REMOTE_SET, NETWORK_COMMAND_REMOTE_SET,
NETWORK_COMMAND_SIMPLIFY_PATH, NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH, NETWORK_COMMAND_CONFIRM_PATH,
NETWORK_COMMAND_RAW,
}; };
void poll(); void poll();
@ -60,6 +62,7 @@ public:
void set_root_node(Node *p_node); void set_root_node(Node *p_node);
void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer); void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer);
Ref<NetworkedMultiplayerPeer> get_network_peer() const; Ref<NetworkedMultiplayerPeer> get_network_peer() const;
Error send_bytes(PoolVector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST);
// Called by Node.rpc // Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount); void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);

View file

@ -61,10 +61,21 @@
</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 [memeber Node.custom_multplayer] override. You only need to worry about this if you are using [member Node.custom_multplayer] override.
SceneTree will poll the default MultiplayerAPI for you. SceneTree will poll the default MultiplayerAPI for you.
</description> </description>
</method> </method>
<method name="send_bytes">
<return type="int" enum="Error">
</return>
<argument index="0" name="bytes" type="PoolByteArray">
</argument>
<argument index="1" name="id" type="int" default="0">
</argument>
<description>
Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
</description>
</method>
<method name="set_root_node"> <method name="set_root_node">
<return type="void"> <return type="void">
</return> </return>
@ -78,7 +89,7 @@
</methods> </methods>
<members> <members>
<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 MultiplayerAPI 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 MultiplayerAPI's signals. The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI 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 MultiplayerAPI's signals.
</member> </member>
<member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections"> <member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections">
If [code]true[/code] the MultiplayerAPI's [member network_peer] refuses new incoming connections. If [code]true[/code] the MultiplayerAPI's [member network_peer] refuses new incoming connections.
@ -109,9 +120,18 @@
Emitted whenever this MultiplayerAPI's [member network_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server. Emitted whenever this MultiplayerAPI's [member network_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server.
</description> </description>
</signal> </signal>
<signal name="network_peer_packet">
<argument index="0" name="id" type="int">
</argument>
<argument index="1" name="packet" type="PoolByteArray">
</argument>
<description>
Emitted whenever this MultiplayerAPI's [member network_peer] receive a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
</description>
</signal>
<signal name="server_disconnected"> <signal name="server_disconnected">
<description> <description>
Emitted whenever this MultiplayerAPI's [member network_peer] disconnected from server. Only emitted on clients. Emitted whenever this MultiplayerAPI's [member network_peer] disconnects from server. Only emitted on clients.
</description> </description>
</signal> </signal>
</signals> </signals>

View file

@ -46,7 +46,8 @@
<argument index="0" name="id" type="int"> <argument index="0" name="id" type="int">
</argument> </argument>
<description> <description>
The peer to which packets will be sent. Default value: [code]0[/code]. Sets the peer to which packets will be sent.
The [code]id[/code] can be one of: [code]TARGET_PEER_BROADCAST[/code] to send to all connected peers, [code]TARGET_PEER_SERVER[/code] to send to the peer acting as server, a valid peer ID to send to that specific peer, a negative peer ID to send to all peers except that one. Default: [code]TARGET_PEER_BROADCAST[/code]
</description> </description>
</method> </method>
</methods> </methods>

View file

@ -586,7 +586,7 @@
<argument index="1" name="method" type="String"> <argument index="1" name="method" type="String">
</argument> </argument>
<description> <description>
Sends a [method rpc] to a specific peer identified by [code]peer_id[/code]. Returns an empty [Variant]. Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description> </description>
</method> </method>
<method name="rpc_unreliable" qualifiers="vararg"> <method name="rpc_unreliable" qualifiers="vararg">
@ -606,7 +606,7 @@
<argument index="1" name="method" type="String"> <argument index="1" name="method" type="String">
</argument> </argument>
<description> <description>
Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol. Returns an empty [Variant]. Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description> </description>
</method> </method>
<method name="rset"> <method name="rset">
@ -641,7 +641,7 @@
<argument index="2" name="value" type="Variant"> <argument index="2" name="value" type="Variant">
</argument> </argument>
<description> <description>
Remotely changes the property's value on a specific peer identified by [code]peer_id[/code]. Remotely changes the property's value on a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]).
</description> </description>
</method> </method>
<method name="rset_unreliable"> <method name="rset_unreliable">
@ -665,7 +665,7 @@
<argument index="2" name="value" type="Variant"> <argument index="2" name="value" type="Variant">
</argument> </argument>
<description> <description>
Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol. Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]).
</description> </description>
</method> </method>
<method name="set_display_folded"> <method name="set_display_folded">
@ -703,7 +703,7 @@
<argument index="0" name="enable" type="bool"> <argument index="0" name="enable" type="bool">
</argument> </argument>
<description> <description>
Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method]_physics_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes behaviour. Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method _physics_process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
</description> </description>
</method> </method>
<method name="set_process"> <method name="set_process">
@ -730,7 +730,7 @@
<argument index="0" name="enable" type="bool"> <argument index="0" name="enable" type="bool">
</argument> </argument>
<description> <description>
Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method]_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes behaviour. Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method _process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
</description> </description>
</method> </method>
<method name="set_process_unhandled_input"> <method name="set_process_unhandled_input">