diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 4b2a9df8c48..d5fd4bff09c 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -65,6 +65,20 @@ Disconnect the given peer. If "now" is set to true, the connection will be closed immediately without flushing queued messages. + + + + + Returns the channel of the last packet fetched via [method PacketPeer.get_packet] + + + + + + + Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet_peer] + + @@ -94,9 +108,18 @@ + + Always use [code]TRANSFER_MODE_ORDERED[/code] in place of [code]TRANSFER_MODE_UNRELIABLE[/code]. This is the only way to use ordering with the RPC system. + + + The number of channels to be used by ENet. Default: [code]3[/code]. Channels are used to separate different kinds of data. In realiable or ordered mode, for example, the packet delivery order is ensured on a per channel basis. + The compression method used for network packets. Default is no compression. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all. + + Set the default channel to be used to transfer data. By default this value is [code]-1[/code] which means that ENet will only use 2 channels, one for reliable and one for unreliable packets. Channel [code]0[/code] is reserved, and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data. + diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index e948df27428..88768829d73 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -55,6 +55,22 @@ int NetworkedMultiplayerENet::get_packet_peer() const { return incoming_packets.front()->get().from; } +int NetworkedMultiplayerENet::get_packet_channel() const { + + ERR_FAIL_COND_V(!active, -1); + ERR_FAIL_COND_V(incoming_packets.size() == 0, -1); + + return incoming_packets.front()->get().channel; +} + +int NetworkedMultiplayerENet::get_last_packet_channel() const { + + ERR_FAIL_COND_V(!active, -1); + ERR_FAIL_COND_V(!current_packet.packet, -1); + + return current_packet.channel; +} + Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) { ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE); @@ -83,7 +99,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int host = enet_host_create(&address /* the address to bind the server host to */, p_max_clients /* allow up to 32 clients and/or outgoing connections */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + channel_count /* allow up to channel_count to be used */, p_in_bandwidth /* limit incoming bandwith if > 0 */, p_out_bandwidth /* limit outgoing bandwith if > 0 */); @@ -127,13 +143,13 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por host = enet_host_create(&c_client /* create a client host */, 1 /* only allow 1 outgoing connection */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + channel_count /* allow up to channel_count to be used */, p_in_bandwidth /* limit incoming bandwith if > 0 */, p_out_bandwidth /* limit outgoing bandwith if > 0 */); } else { host = enet_host_create(NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, - SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */, + channel_count /* allow up to channel_count to be used */, p_in_bandwidth /* limit incoming bandwith if > 0 */, p_out_bandwidth /* limit outgoing bandwith if > 0 */); } @@ -167,7 +183,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por unique_id = _gen_unique_id(); // Initiate connection, allocating enough channels - ENetPeer *peer = enet_host_connect(host, &address, SYSCH_MAX, unique_id); + ENetPeer *peer = enet_host_connect(host, &address, channel_count, unique_id); if (peer == NULL) { enet_host_destroy(host); @@ -316,7 +332,7 @@ void NetworkedMultiplayerENet::poll() { } enet_packet_destroy(event.packet); - } else if (event.channelID < SYSCH_MAX) { + } else if (event.channelID < channel_count) { Packet packet; packet.packet = event.packet; @@ -330,6 +346,7 @@ void NetworkedMultiplayerENet::poll() { uint32_t flags = decode_uint32(&event.packet->data[8]); packet.from = source; + packet.channel = event.channelID; if (server) { // Someone is cheating and trying to fake the source! @@ -496,7 +513,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer switch (transfer_mode) { case TRANSFER_MODE_UNRELIABLE: { - packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; + if (always_ordered) + packet_flags = 0; + else + packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; channel = SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_UNRELIABLE_ORDERED: { @@ -509,6 +529,9 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer } break; } + if (transfer_channel > SYSCH_CONFIG) + channel = transfer_channel; + Map::Element *E = NULL; if (target_peer != 0) { @@ -572,6 +595,7 @@ void NetworkedMultiplayerENet::_pop_current_packet() { enet_packet_destroy(current_packet.packet); current_packet.packet = NULL; current_packet.from = 0; + current_packet.channel = -1; } } @@ -759,6 +783,40 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const { #endif } +void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) { + + ERR_FAIL_COND(p_channel < -1 || p_channel >= channel_count); + + if (p_channel == SYSCH_CONFIG) { + ERR_EXPLAIN("Channel " + itos(SYSCH_CONFIG) + " is reserved"); + ERR_FAIL(); + } + transfer_channel = p_channel; +} + +int NetworkedMultiplayerENet::get_transfer_channel() const { + return transfer_channel; +} + +void NetworkedMultiplayerENet::set_channel_count(int p_channel) { + + ERR_FAIL_COND(active); + ERR_FAIL_COND(p_channel < SYSCH_MAX); + channel_count = p_channel; +} + +int NetworkedMultiplayerENet::get_channel_count() const { + return channel_count; +} + +void NetworkedMultiplayerENet::set_always_ordered(bool p_ordered) { + always_ordered = p_ordered; +} + +bool NetworkedMultiplayerENet::is_always_ordered() const { + return always_ordered; +} + void NetworkedMultiplayerENet::_bind_methods() { ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0)); @@ -771,7 +829,19 @@ void NetworkedMultiplayerENet::_bind_methods() { ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address); ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port); + ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel); + ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel); + ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &NetworkedMultiplayerENet::set_transfer_channel); + ClassDB::bind_method(D_METHOD("get_transfer_channel"), &NetworkedMultiplayerENet::get_transfer_channel); + ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &NetworkedMultiplayerENet::set_channel_count); + ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count); + ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered); + ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered); + ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "channel_count"), "set_channel_count", "get_channel_count"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "always_ordered"), "set_always_ordered", "is_always_ordered"); BIND_ENUM_CONSTANT(COMPRESS_NONE); BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER); @@ -789,6 +859,9 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() { target_peer = 0; current_packet.packet = NULL; transfer_mode = TRANSFER_MODE_RELIABLE; + channel_count = SYSCH_MAX; + transfer_channel = -1; + always_ordered = false; connection_status = CONNECTION_DISCONNECTED; compression_mode = COMPRESS_NONE; enet_compressor.context = this; diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index d481f5d4965..705807d429a 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -68,6 +68,9 @@ private: int target_peer; TransferMode transfer_mode; + int transfer_channel; + int channel_count; + bool always_ordered; ENetEvent event; ENetPeer *peer; @@ -83,6 +86,7 @@ private: ENetPacket *packet; int from; + int channel; }; CompressionMode compression_mode; @@ -145,6 +149,15 @@ public: void set_compression_mode(CompressionMode p_mode); CompressionMode get_compression_mode() const; + int get_packet_channel() const; + int get_last_packet_channel() const; + void set_transfer_channel(int p_channel); + int get_transfer_channel() const; + void set_channel_count(int p_channel); + int get_channel_count() const; + void set_always_ordered(bool p_ordered); + bool is_always_ordered() const; + NetworkedMultiplayerENet(); ~NetworkedMultiplayerENet();