1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

[Net] Implement RPC channels in MultiplayerAPI.

This commit is contained in:
Fabio Alessandrelli
2021-07-27 12:06:48 +02:00
parent c27ef1565f
commit 2cf39b97ae
16 changed files with 157 additions and 62 deletions

View File

@@ -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();
}