[Net] Implement RPC channels in MultiplayerAPI.
This commit is contained in:
parent
c27ef1565f
commit
2cf39b97ae
16 changed files with 157 additions and 62 deletions
|
|
@ -51,10 +51,12 @@
|
|||
<return type="int" enum="Error" />
|
||||
<argument index="0" name="peer_id" type="int" />
|
||||
<argument index="1" name="server_compatibility" type="bool" default="false" />
|
||||
<argument index="2" name="channels_config" type="Array" default="[]" />
|
||||
<description>
|
||||
Initialize the multiplayer peer with the given [code]peer_id[/code] (must be between 1 and 2147483647).
|
||||
If [code]server_compatibilty[/code] is [code]false[/code] (default), the multiplayer peer will be immediately in state [constant MultiplayerPeer.CONNECTION_CONNECTED] and [signal MultiplayerPeer.connection_succeeded] will not be emitted.
|
||||
If [code]server_compatibilty[/code] is [code]true[/code] the peer will suppress all [signal MultiplayerPeer.peer_connected] signals until a peer with id [constant MultiplayerPeer.TARGET_PEER_SERVER] connects and then emit [signal MultiplayerPeer.connection_succeeded]. After that the signal [signal MultiplayerPeer.peer_connected] will be emitted for every already connected peer, and any new peer that might connect. If the server peer disconnects after that, signal [signal MultiplayerPeer.server_disconnected] will be emitted and state will become [constant MultiplayerPeer.CONNECTION_CONNECTED].
|
||||
You can optionally specify a [code]channels_config[/code] array of [enum MultiplayerPeer.TransferMode] which will be used to create extra channels (WebRTC only supports one transfer mode per channel).
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_peer">
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "core/os/os.h"
|
||||
|
||||
void WebRTCMultiplayerPeer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility"), &WebRTCMultiplayerPeer::initialize, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("initialize", "peer_id", "server_compatibility", "channels_config"), &WebRTCMultiplayerPeer::initialize, DEFVAL(false), DEFVAL(Array()));
|
||||
ClassDB::bind_method(D_METHOD("add_peer", "peer", "peer_id", "unreliable_lifetime"), &WebRTCMultiplayerPeer::add_peer, DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("remove_peer", "peer_id"), &WebRTCMultiplayerPeer::remove_peer);
|
||||
ClassDB::bind_method(D_METHOD("has_peer", "peer_id"), &WebRTCMultiplayerPeer::has_peer);
|
||||
|
|
@ -43,6 +43,14 @@ void WebRTCMultiplayerPeer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("close"), &WebRTCMultiplayerPeer::close);
|
||||
}
|
||||
|
||||
void WebRTCMultiplayerPeer::set_transfer_channel(int p_channel) {
|
||||
transfer_channel = p_channel;
|
||||
}
|
||||
|
||||
int WebRTCMultiplayerPeer::get_transfer_channel() const {
|
||||
return transfer_channel;
|
||||
}
|
||||
|
||||
void WebRTCMultiplayerPeer::set_transfer_mode(TransferMode p_mode) {
|
||||
transfer_mode = p_mode;
|
||||
}
|
||||
|
|
@ -192,8 +200,34 @@ MultiplayerPeer::ConnectionStatus WebRTCMultiplayerPeer::get_connection_status()
|
|||
return connection_status;
|
||||
}
|
||||
|
||||
Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat) {
|
||||
ERR_FAIL_COND_V(p_self_id < 0 || p_self_id > ~(1 << 31), ERR_INVALID_PARAMETER);
|
||||
Error WebRTCMultiplayerPeer::initialize(int p_self_id, bool p_server_compat, Array p_channels_config) {
|
||||
ERR_FAIL_COND_V(p_self_id < 1 || p_self_id > ~(1 << 31), ERR_INVALID_PARAMETER);
|
||||
channels_config.clear();
|
||||
for (int i = 0; i < p_channels_config.size(); i++) {
|
||||
ERR_FAIL_COND_V_MSG(p_channels_config[i].get_type() != Variant::INT, ERR_INVALID_PARAMETER, "The 'channels_config' array must contain only enum values from 'MultiplayerPeer.TransferMode'");
|
||||
int mode = p_channels_config[i].operator int();
|
||||
// Initialize data channel configurations.
|
||||
Dictionary cfg;
|
||||
cfg["id"] = CH_RESERVED_MAX + i + 1;
|
||||
cfg["negotiated"] = true;
|
||||
cfg["ordered"] = true;
|
||||
|
||||
switch (mode) {
|
||||
case TRANSFER_MODE_UNRELIABLE_ORDERED:
|
||||
cfg["maxPacketLifetime"] = 1;
|
||||
break;
|
||||
case TRANSFER_MODE_UNRELIABLE:
|
||||
cfg["maxPacketLifetime"] = 1;
|
||||
cfg["ordered"] = false;
|
||||
break;
|
||||
case TRANSFER_MODE_RELIABLE:
|
||||
break;
|
||||
default:
|
||||
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("The 'channels_config' array must contain only enum values from 'MultiplayerPeer.TransferMode'. Got: %d", mode));
|
||||
}
|
||||
channels_config.push_back(cfg);
|
||||
}
|
||||
|
||||
unique_id = p_self_id;
|
||||
server_compat = p_server_compat;
|
||||
|
||||
|
|
@ -260,17 +294,23 @@ Error WebRTCMultiplayerPeer::add_peer(Ref<WebRTCPeerConnection> p_peer, int p_pe
|
|||
|
||||
cfg["id"] = 1;
|
||||
peer->channels[CH_RELIABLE] = p_peer->create_data_channel("reliable", cfg);
|
||||
ERR_FAIL_COND_V(!peer->channels[CH_RELIABLE].is_valid(), FAILED);
|
||||
ERR_FAIL_COND_V(peer->channels[CH_RELIABLE].is_null(), FAILED);
|
||||
|
||||
cfg["id"] = 2;
|
||||
cfg["maxPacketLifetime"] = p_unreliable_lifetime;
|
||||
peer->channels[CH_ORDERED] = p_peer->create_data_channel("ordered", cfg);
|
||||
ERR_FAIL_COND_V(!peer->channels[CH_ORDERED].is_valid(), FAILED);
|
||||
ERR_FAIL_COND_V(peer->channels[CH_ORDERED].is_null(), FAILED);
|
||||
|
||||
cfg["id"] = 3;
|
||||
cfg["ordered"] = false;
|
||||
peer->channels[CH_UNRELIABLE] = p_peer->create_data_channel("unreliable", cfg);
|
||||
ERR_FAIL_COND_V(!peer->channels[CH_UNRELIABLE].is_valid(), FAILED);
|
||||
ERR_FAIL_COND_V(peer->channels[CH_UNRELIABLE].is_null(), FAILED);
|
||||
|
||||
for (const Dictionary &dict : channels_config) {
|
||||
Ref<WebRTCDataChannel> ch = p_peer->create_data_channel(String::num_int64(dict["id"]), dict);
|
||||
ERR_FAIL_COND_V(ch.is_null(), FAILED);
|
||||
peer->channels.push_back(ch);
|
||||
}
|
||||
|
||||
peer_map[p_peer_id] = peer; // add the new peer connection to the peer_map
|
||||
|
||||
|
|
@ -312,17 +352,21 @@ Error WebRTCMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_
|
|||
Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) {
|
||||
ERR_FAIL_COND_V(connection_status == CONNECTION_DISCONNECTED, ERR_UNCONFIGURED);
|
||||
|
||||
int ch = CH_RELIABLE;
|
||||
switch (transfer_mode) {
|
||||
case TRANSFER_MODE_RELIABLE:
|
||||
ch = CH_RELIABLE;
|
||||
break;
|
||||
case TRANSFER_MODE_UNRELIABLE_ORDERED:
|
||||
ch = CH_ORDERED;
|
||||
break;
|
||||
case TRANSFER_MODE_UNRELIABLE:
|
||||
ch = CH_UNRELIABLE;
|
||||
break;
|
||||
int ch = transfer_channel;
|
||||
if (ch == 0) {
|
||||
switch (transfer_mode) {
|
||||
case TRANSFER_MODE_RELIABLE:
|
||||
ch = CH_RELIABLE;
|
||||
break;
|
||||
case TRANSFER_MODE_UNRELIABLE_ORDERED:
|
||||
ch = CH_ORDERED;
|
||||
break;
|
||||
case TRANSFER_MODE_UNRELIABLE:
|
||||
ch = CH_UNRELIABLE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ch += CH_RESERVED_MAX - 1;
|
||||
}
|
||||
|
||||
Map<int, Ref<ConnectedPeer>>::Element *E = nullptr;
|
||||
|
|
@ -331,8 +375,8 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
|
|||
E = peer_map.find(target_peer);
|
||||
ERR_FAIL_COND_V_MSG(!E, ERR_INVALID_PARAMETER, "Invalid target peer: " + itos(target_peer) + ".");
|
||||
|
||||
ERR_FAIL_COND_V(E->value()->channels.size() <= ch, ERR_BUG);
|
||||
ERR_FAIL_COND_V(!E->value()->channels[ch].is_valid(), ERR_BUG);
|
||||
ERR_FAIL_COND_V_MSG(E->value()->channels.size() <= ch, ERR_INVALID_PARAMETER, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
|
||||
ERR_FAIL_COND_V(E->value()->channels[ch].is_null(), ERR_BUG);
|
||||
return E->value()->channels[ch]->put_packet(p_buffer, p_buffer_size);
|
||||
|
||||
} else {
|
||||
|
|
@ -344,7 +388,8 @@ Error WebRTCMultiplayerPeer::put_packet(const uint8_t *p_buffer, int p_buffer_si
|
|||
continue;
|
||||
}
|
||||
|
||||
ERR_CONTINUE(F->value()->channels.size() <= ch || !F->value()->channels[ch].is_valid());
|
||||
ERR_CONTINUE_MSG(F->value()->channels.size() <= ch, vformat("Unable to send packet on channel %d, max channels: %d", ch, E->value()->channels.size()));
|
||||
ERR_CONTINUE(F->value()->channels[ch].is_null());
|
||||
F->value()->channels[ch]->put_packet(p_buffer, p_buffer_size);
|
||||
}
|
||||
}
|
||||
|
|
@ -370,23 +415,13 @@ int WebRTCMultiplayerPeer::get_max_packet_size() const {
|
|||
|
||||
void WebRTCMultiplayerPeer::close() {
|
||||
peer_map.clear();
|
||||
channels_config.clear();
|
||||
unique_id = 0;
|
||||
next_packet_peer = 0;
|
||||
target_peer = 0;
|
||||
connection_status = CONNECTION_DISCONNECTED;
|
||||
}
|
||||
|
||||
WebRTCMultiplayerPeer::WebRTCMultiplayerPeer() {
|
||||
unique_id = 0;
|
||||
next_packet_peer = 0;
|
||||
target_peer = 0;
|
||||
client_count = 0;
|
||||
transfer_mode = TRANSFER_MODE_RELIABLE;
|
||||
refuse_connections = false;
|
||||
connection_status = CONNECTION_DISCONNECTED;
|
||||
server_compat = false;
|
||||
}
|
||||
|
||||
WebRTCMultiplayerPeer::~WebRTCMultiplayerPeer() {
|
||||
close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,25 +62,27 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
uint32_t unique_id;
|
||||
int target_peer;
|
||||
int client_count;
|
||||
bool refuse_connections;
|
||||
ConnectionStatus connection_status;
|
||||
TransferMode transfer_mode;
|
||||
int next_packet_peer;
|
||||
bool server_compat;
|
||||
uint32_t unique_id = 0;
|
||||
int target_peer = 0;
|
||||
int client_count = 0;
|
||||
bool refuse_connections = false;
|
||||
ConnectionStatus connection_status = CONNECTION_DISCONNECTED;
|
||||
int transfer_channel = 0;
|
||||
TransferMode transfer_mode = TRANSFER_MODE_RELIABLE;
|
||||
int next_packet_peer = 0;
|
||||
bool server_compat = false;
|
||||
|
||||
Map<int, Ref<ConnectedPeer>> peer_map;
|
||||
List<Dictionary> channels_config;
|
||||
|
||||
void _peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict);
|
||||
void _find_next_peer();
|
||||
|
||||
public:
|
||||
WebRTCMultiplayerPeer();
|
||||
WebRTCMultiplayerPeer() {}
|
||||
~WebRTCMultiplayerPeer();
|
||||
|
||||
Error initialize(int p_self_id, bool p_server_compat = false);
|
||||
Error initialize(int p_self_id, bool p_server_compat = false, Array p_channels_config = Array());
|
||||
Error add_peer(Ref<WebRTCPeerConnection> p_peer, int p_peer_id, int p_unreliable_lifetime = 1);
|
||||
void remove_peer(int p_peer_id);
|
||||
bool has_peer(int p_peer_id);
|
||||
|
|
@ -95,6 +97,8 @@ public:
|
|||
int get_max_packet_size() const override;
|
||||
|
||||
// MultiplayerPeer
|
||||
void set_transfer_channel(int p_channel) override;
|
||||
int get_transfer_channel() const override;
|
||||
void set_transfer_mode(TransferMode p_mode) override;
|
||||
TransferMode get_transfer_mode() const override;
|
||||
void set_target_peer(int p_peer_id) override;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue