2023-01-05 12:25:55 +00:00
/**************************************************************************/
/* enet_multiplayer_peer.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-04 23:50:27 +00:00
2021-07-12 14:18:43 +00:00
# include "enet_multiplayer_peer.h"
2023-06-13 14:56:21 +00:00
2018-09-11 16:13:45 +00:00
# include "core/io/ip.h"
# include "core/io/marshalls.h"
# include "core/os/os.h"
2016-08-14 16:29:25 +00:00
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_target_peer ( int p_peer ) {
2017-03-05 15:44:50 +00:00
target_peer = p_peer ;
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_packet_peer ( ) const {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , 1 , " The multiplayer instance isn't currently active. " ) ;
2024-01-19 12:21:39 +00:00
ERR_FAIL_COND_V ( incoming_packets . is_empty ( ) , 1 ) ;
2016-08-14 16:29:25 +00:00
return incoming_packets . front ( ) - > get ( ) . from ;
}
2022-10-08 18:50:19 +00:00
MultiplayerPeer : : TransferMode ENetMultiplayerPeer : : get_packet_mode ( ) const {
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , TRANSFER_MODE_RELIABLE , " The multiplayer instance isn't currently active. " ) ;
2024-01-19 12:21:39 +00:00
ERR_FAIL_COND_V ( incoming_packets . is_empty ( ) , TRANSFER_MODE_RELIABLE ) ;
2022-10-08 18:50:19 +00:00
return incoming_packets . front ( ) - > get ( ) . transfer_mode ;
}
int ENetMultiplayerPeer : : get_packet_channel ( ) const {
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , 1 , " The multiplayer instance isn't currently active. " ) ;
2024-01-19 12:21:39 +00:00
ERR_FAIL_COND_V ( incoming_packets . is_empty ( ) , 1 ) ;
2022-10-08 18:50:19 +00:00
int ch = incoming_packets . front ( ) - > get ( ) . channel ;
if ( ch > = SYSCH_MAX ) { // First 2 channels are reserved.
return ch - SYSCH_MAX + 1 ;
}
return 0 ;
}
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_server ( int p_port , int p_max_clients , int p_max_channels , int p_in_bandwidth , int p_out_bandwidth ) {
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
2021-09-07 21:04:52 +00:00
set_refuse_new_connections ( false ) ;
2021-07-15 23:48:44 +00:00
Ref < ENetConnection > host ;
host . instantiate ( ) ;
Error err = host - > create_host_bound ( bind_ip , p_port , p_max_clients , 0 , p_max_channels > 0 ? p_max_channels + SYSCH_MAX : 0 , p_out_bandwidth ) ;
if ( err ! = OK ) {
return err ;
2020-01-13 15:51:17 +00:00
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
active_mode = MODE_SERVER ;
2017-03-05 15:44:50 +00:00
unique_id = 1 ;
connection_status = CONNECTION_CONNECTED ;
2021-07-15 23:48:44 +00:00
hosts [ 0 ] = host ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2018-05-06 22:28:59 +00:00
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_client ( const String & p_address , int p_port , int p_channel_count , int p_in_bandwidth , int p_out_bandwidth , int p_local_port ) {
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
2021-09-07 21:04:52 +00:00
set_refuse_new_connections ( false ) ;
2021-07-15 23:48:44 +00:00
Ref < ENetConnection > host ;
host . instantiate ( ) ;
Error err ;
if ( p_local_port ) {
err = host - > create_host_bound ( bind_ip , p_local_port , 1 , 0 , p_in_bandwidth , p_out_bandwidth ) ;
2021-03-29 16:14:50 +00:00
} else {
2021-07-15 23:48:44 +00:00
err = host - > create_host ( 1 , 0 , p_in_bandwidth , p_out_bandwidth ) ;
2021-03-29 16:14:50 +00:00
}
2021-07-15 23:48:44 +00:00
if ( err ! = OK ) {
return err ;
2021-03-29 16:14:50 +00:00
}
2016-08-14 17:06:51 +00:00
2021-07-15 22:43:49 +00:00
unique_id = generate_unique_id ( ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
Ref < ENetPacketPeer > peer = host - > connect_to_host ( p_address , p_port , p_channel_count > 0 ? p_channel_count + SYSCH_MAX : 0 , unique_id ) ;
if ( peer . is_null ( ) ) {
host - > destroy ( ) ;
ERR_FAIL_V_MSG ( ERR_CANT_CREATE , " Couldn't connect to the ENet multiplayer server. " ) ;
2016-08-14 17:06:51 +00:00
}
2021-07-15 23:48:44 +00:00
// Need to wait for CONNECT event.
2017-03-05 15:44:50 +00:00
connection_status = CONNECTION_CONNECTING ;
2021-07-15 23:48:44 +00:00
active_mode = MODE_CLIENT ;
peers [ 1 ] = peer ;
hosts [ 0 ] = host ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : create_mesh ( int p_id ) {
ERR_FAIL_COND_V_MSG ( p_id < = 0 , ERR_INVALID_PARAMETER , " The unique ID must be greater then 0 " ) ;
ERR_FAIL_COND_V_MSG ( _is_active ( ) , ERR_ALREADY_IN_USE , " The multiplayer instance is already active. " ) ;
active_mode = MODE_MESH ;
unique_id = p_id ;
connection_status = CONNECTION_CONNECTED ;
return OK ;
}
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
Error ENetMultiplayerPeer : : add_mesh_peer ( int p_id , Ref < ENetConnection > p_host ) {
ERR_FAIL_COND_V ( p_host . is_null ( ) , ERR_INVALID_PARAMETER ) ;
ERR_FAIL_COND_V_MSG ( active_mode ! = MODE_MESH , ERR_UNCONFIGURED , " The multiplayer instance is not configured as a mesh. Call 'create_mesh' first. " ) ;
List < Ref < ENetPacketPeer > > host_peers ;
p_host - > get_peers ( host_peers ) ;
Fix various typos
Found via ` codespell -q 3 -S ./thirdparty,*.po,./DONORS.md -L ackward,ang,ans,ba,beng,cas,childs,childrens,dof,doubleclick,expct,fave,findn,gird,hist,inout,leapyear,lod,nd,numer,ois,ony,paket,seeked,sinc,switchs,te,uint,varn`
Update editor/import/resource_importer_layered_texture.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update doc/classes/TileSetScenesCollectionSource.xml
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/gui/graph_edit.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/resources/animation.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Update scene/gui/rich_text_label.cpp
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Revert previously committed change
2022-01-02 06:03:58 +00:00
ERR_FAIL_COND_V_MSG ( host_peers . size ( ) ! = 1 | | host_peers [ 0 ] - > get_state ( ) ! = ENetPacketPeer : : STATE_CONNECTED , ERR_INVALID_PARAMETER , " The provided host must have exactly one peer in the connected state. " ) ;
2021-07-15 23:48:44 +00:00
hosts [ p_id ] = p_host ;
peers [ p_id ] = host_peers [ 0 ] ;
emit_signal ( SNAME ( " peer_connected " ) , p_id ) ;
return OK ;
}
2016-08-14 16:29:25 +00:00
2022-10-08 18:50:19 +00:00
void ENetMultiplayerPeer : : _store_packet ( int32_t p_source , ENetConnection : : Event & p_event ) {
Packet packet ;
packet . packet = p_event . packet ;
packet . channel = p_event . channel_id ;
packet . from = p_source ;
if ( p_event . packet - > flags & ENET_PACKET_FLAG_RELIABLE ) {
packet . transfer_mode = TRANSFER_MODE_RELIABLE ;
} else if ( p_event . packet - > flags & ENET_PACKET_FLAG_UNSEQUENCED ) {
packet . transfer_mode = TRANSFER_MODE_UNRELIABLE ;
} else {
packet . transfer_mode = TRANSFER_MODE_UNRELIABLE_ORDERED ;
}
packet . packet - > referenceCount + + ;
incoming_packets . push_back ( packet ) ;
}
2022-10-22 15:49:40 +00:00
void ENetMultiplayerPeer : : _disconnect_inactive_peers ( ) {
HashSet < int > to_drop ;
for ( const KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . value - > is_active ( ) ) {
continue ;
2021-07-15 23:48:44 +00:00
}
2022-10-22 15:49:40 +00:00
to_drop . insert ( E . key ) ;
2021-07-15 23:48:44 +00:00
}
2022-10-22 15:49:40 +00:00
for ( const int & P : to_drop ) {
peers . erase ( P ) ;
if ( hosts . has ( P ) ) {
hosts . erase ( P ) ;
2021-07-15 23:48:44 +00:00
}
2022-10-31 13:18:22 +00:00
ERR_CONTINUE ( active_mode = = MODE_CLIENT & & P ! = TARGET_PEER_SERVER ) ;
2022-10-22 15:49:40 +00:00
emit_signal ( SNAME ( " peer_disconnected " ) , P ) ;
2016-08-14 16:29:25 +00:00
}
}
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : poll ( ) {
ERR_FAIL_COND_MSG ( ! _is_active ( ) , " The multiplayer instance isn't currently active. " ) ;
2016-08-14 21:49:50 +00:00
2021-07-15 23:48:44 +00:00
_pop_current_packet ( ) ;
2022-10-22 15:49:40 +00:00
_disconnect_inactive_peers ( ) ;
2021-09-27 09:07:00 +00:00
switch ( active_mode ) {
case MODE_CLIENT : {
2022-10-22 15:49:40 +00:00
if ( ! peers . has ( 1 ) ) {
close ( ) ;
2021-09-27 09:07:00 +00:00
return ;
}
ENetConnection : : Event event ;
ENetConnection : : EventType ret = hosts [ 0 ] - > service ( 0 , event ) ;
do {
2022-10-22 15:49:40 +00:00
if ( ret = = ENetConnection : : EVENT_CONNECT ) {
connection_status = CONNECTION_CONNECTED ;
emit_signal ( SNAME ( " peer_connected " ) , 1 ) ;
} else if ( ret = = ENetConnection : : EVENT_DISCONNECT ) {
if ( connection_status = = CONNECTION_CONNECTED ) {
// Client just disconnected from server.
emit_signal ( SNAME ( " peer_disconnected " ) , 1 ) ;
}
close ( ) ;
} else if ( ret = = ENetConnection : : EVENT_RECEIVE ) {
_store_packet ( 1 , event ) ;
} else if ( ret ! = ENetConnection : : EVENT_NONE ) {
close ( ) ; // Error.
2021-07-15 23:48:44 +00:00
}
2022-10-22 15:49:40 +00:00
} while ( hosts . has ( 0 ) & & hosts [ 0 ] - > check_events ( ret , event ) > 0 ) ;
2021-09-27 09:07:00 +00:00
} break ;
case MODE_SERVER : {
ENetConnection : : Event event ;
ENetConnection : : EventType ret = hosts [ 0 ] - > service ( 0 , event ) ;
do {
2022-10-22 15:49:40 +00:00
if ( ret = = ENetConnection : : EVENT_CONNECT ) {
if ( is_refusing_new_connections ( ) ) {
event . peer - > reset ( ) ;
continue ;
}
// Client joined with invalid ID, probably trying to exploit us.
if ( event . data < 2 | | peers . has ( ( int ) event . data ) ) {
event . peer - > reset ( ) ;
continue ;
}
int id = event . data ;
event . peer - > set_meta ( SNAME ( " _net_id " ) , id ) ;
peers [ id ] = event . peer ;
emit_signal ( SNAME ( " peer_connected " ) , id ) ;
} else if ( ret = = ENetConnection : : EVENT_DISCONNECT ) {
int id = event . peer - > get_meta ( SNAME ( " _net_id " ) ) ;
if ( ! peers . has ( id ) ) {
// Never fully connected.
continue ;
}
emit_signal ( SNAME ( " peer_disconnected " ) , id ) ;
peers . erase ( id ) ;
} else if ( ret = = ENetConnection : : EVENT_RECEIVE ) {
int32_t source = event . peer - > get_meta ( SNAME ( " _net_id " ) ) ;
_store_packet ( source , event ) ;
} else if ( ret ! = ENetConnection : : EVENT_NONE ) {
close ( ) ; // Error
2021-09-27 09:07:00 +00:00
}
2022-10-22 15:49:40 +00:00
} while ( hosts . has ( 0 ) & & hosts [ 0 ] - > check_events ( ret , event ) > 0 ) ;
2021-09-27 09:07:00 +00:00
} break ;
case MODE_MESH : {
2022-10-22 15:49:40 +00:00
HashSet < int > to_drop ;
2021-09-27 09:07:00 +00:00
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
ENetConnection : : Event event ;
ENetConnection : : EventType ret = E . value - > service ( 0 , event ) ;
do {
2022-10-22 15:49:40 +00:00
if ( ret = = ENetConnection : : EVENT_CONNECT ) {
event . peer - > reset ( ) ;
} else if ( ret = = ENetConnection : : EVENT_RECEIVE ) {
_store_packet ( E . key , event ) ;
} else if ( ret = = ENetConnection : : EVENT_NONE ) {
break ; // Keep polling the others.
} else {
to_drop . insert ( E . key ) ; // Error or disconnect.
2021-09-27 09:07:00 +00:00
break ; // Keep polling the others.
}
} while ( E . value - > check_events ( ret , event ) > 0 ) ;
}
2022-10-22 15:49:40 +00:00
for ( const int & P : to_drop ) {
if ( peers . has ( P ) ) {
emit_signal ( SNAME ( " peer_disconnected " ) , P ) ;
peers . erase ( P ) ;
}
hosts . erase ( P ) ;
}
2021-09-27 09:07:00 +00:00
} break ;
default :
return ;
2021-07-15 23:48:44 +00:00
}
}
bool ENetMultiplayerPeer : : is_server ( ) const {
return active_mode = = MODE_SERVER ;
2016-08-14 21:49:50 +00:00
}
2022-10-08 18:50:19 +00:00
bool ENetMultiplayerPeer : : is_server_relay_supported ( ) const {
return active_mode = = MODE_SERVER | | active_mode = = MODE_CLIENT ;
}
2022-10-22 15:49:40 +00:00
void ENetMultiplayerPeer : : disconnect_peer ( int p_peer , bool p_force ) {
ERR_FAIL_COND ( ! _is_active ( ) | | ! peers . has ( p_peer ) ) ;
peers [ p_peer ] - > peer_disconnect ( 0 ) ; // Will be removed during next poll.
if ( active_mode = = MODE_CLIENT | | active_mode = = MODE_SERVER ) {
hosts [ 0 ] - > flush ( ) ;
} else {
ERR_FAIL_COND ( ! hosts . has ( p_peer ) ) ;
hosts [ p_peer ] - > flush ( ) ;
}
if ( p_force ) {
peers . erase ( p_peer ) ;
if ( hosts . has ( p_peer ) ) {
hosts . erase ( p_peer ) ;
}
if ( active_mode = = MODE_CLIENT ) {
hosts . clear ( ) ; // Avoid flushing again.
close ( ) ;
}
}
}
void ENetMultiplayerPeer : : close ( ) {
2021-09-02 13:21:09 +00:00
if ( ! _is_active ( ) ) {
return ;
}
2016-08-14 16:29:25 +00:00
_pop_current_packet ( ) ;
2021-07-15 23:48:44 +00:00
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . value . is_valid ( ) & & E . value - > get_state ( ) = = ENetPacketPeer : : STATE_CONNECTED ) {
2022-10-22 15:49:40 +00:00
E . value - > peer_disconnect_now ( 0 ) ;
2016-08-19 19:48:08 +00:00
}
}
2022-10-22 15:49:40 +00:00
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
E . value - > flush ( ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
active_mode = MODE_NONE ;
2016-08-14 16:29:25 +00:00
incoming_packets . clear ( ) ;
2021-07-15 23:48:44 +00:00
peers . clear ( ) ;
hosts . clear ( ) ;
unique_id = 0 ;
2017-03-05 15:44:50 +00:00
connection_status = CONNECTION_DISCONNECTED ;
2021-09-07 21:04:52 +00:00
set_refuse_new_connections ( false ) ;
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_available_packet_count ( ) const {
2016-08-14 16:29:25 +00:00
return incoming_packets . size ( ) ;
}
2018-05-06 22:28:59 +00:00
2021-07-12 14:18:43 +00:00
Error ENetMultiplayerPeer : : get_packet ( const uint8_t * * r_buffer , int & r_buffer_size ) {
2024-01-19 12:21:39 +00:00
ERR_FAIL_COND_V_MSG ( incoming_packets . is_empty ( ) , ERR_UNAVAILABLE , " No incoming packets available. " ) ;
2016-08-14 16:29:25 +00:00
_pop_current_packet ( ) ;
current_packet = incoming_packets . front ( ) - > get ( ) ;
incoming_packets . pop_front ( ) ;
2022-10-08 18:50:19 +00:00
* r_buffer = ( const uint8_t * ) ( current_packet . packet - > data ) ;
r_buffer_size = current_packet . packet - > dataLength ;
2016-08-14 16:29:25 +00:00
return OK ;
}
2018-05-06 22:28:59 +00:00
2021-07-12 14:18:43 +00:00
Error ENetMultiplayerPeer : : put_packet ( const uint8_t * p_buffer , int p_buffer_size ) {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , ERR_UNCONFIGURED , " The multiplayer instance isn't currently active. " ) ;
2020-02-02 22:34:47 +00:00
ERR_FAIL_COND_V_MSG ( connection_status ! = CONNECTION_CONNECTED , ERR_UNCONFIGURED , " The multiplayer instance isn't currently connected to any server or client. " ) ;
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( target_peer ! = 0 & & ! peers . has ( ABS ( target_peer ) ) , ERR_INVALID_PARAMETER , vformat ( " Invalid target peer: %d " , target_peer ) ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_CLIENT & & ! peers . has ( 1 ) , ERR_BUG ) ;
2016-08-14 16:29:25 +00:00
2017-03-05 15:44:50 +00:00
int packet_flags = 0 ;
int channel = SYSCH_RELIABLE ;
2022-09-29 09:53:28 +00:00
int tr_channel = get_transfer_channel ( ) ;
2023-08-05 10:27:02 +00:00
switch ( get_transfer_mode ( ) ) {
case TRANSFER_MODE_UNRELIABLE : {
packet_flags = ENET_PACKET_FLAG_UNSEQUENCED | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT ;
channel = SYSCH_UNRELIABLE ;
} break ;
case TRANSFER_MODE_UNRELIABLE_ORDERED : {
packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT ;
channel = SYSCH_UNRELIABLE ;
} break ;
case TRANSFER_MODE_RELIABLE : {
packet_flags = ENET_PACKET_FLAG_RELIABLE ;
channel = SYSCH_RELIABLE ;
} break ;
}
2022-09-29 09:53:28 +00:00
if ( tr_channel > 0 ) {
channel = SYSCH_MAX + tr_channel - 1 ;
2016-08-14 16:29:25 +00:00
}
2021-09-27 08:09:32 +00:00
# ifdef DEBUG_ENABLED
2022-10-08 18:50:19 +00:00
if ( ( packet_flags & ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT ) & & p_buffer_size > ENET_HOST_DEFAULT_MTU ) {
2023-01-30 13:22:47 +00:00
WARN_PRINT_ONCE ( vformat ( " Sending %d bytes unreliably which is above the MTU (%d), this will result in higher packet loss " , p_buffer_size , ENET_HOST_DEFAULT_MTU ) ) ;
2021-09-27 08:09:32 +00:00
}
# endif
2022-10-08 18:50:19 +00:00
ENetPacket * packet = enet_packet_create ( nullptr , p_buffer_size , packet_flags ) ;
memcpy ( & packet - > data [ 0 ] , p_buffer , p_buffer_size ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
if ( is_server ( ) ) {
2017-03-05 15:44:50 +00:00
if ( target_peer = = 0 ) {
2021-07-15 23:48:44 +00:00
hosts [ 0 ] - > broadcast ( channel , packet ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
} else if ( target_peer < 0 ) {
// Send to all but one and make copies for sending.
2017-03-05 15:44:50 +00:00
int exclude = - target_peer ;
2021-07-15 23:48:44 +00:00
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = exclude ) {
2016-08-19 19:48:08 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2021-07-15 23:48:44 +00:00
E . value - > send ( channel , packet ) ;
}
_destroy_unused ( packet ) ;
} else {
peers [ target_peer ] - > send ( channel , packet ) ;
}
ERR_FAIL_COND_V ( ! hosts . has ( 0 ) , ERR_BUG ) ;
hosts [ 0 ] - > flush ( ) ;
2016-08-14 16:29:25 +00:00
2021-07-15 23:48:44 +00:00
} else if ( active_mode = = MODE_CLIENT ) {
peers [ 1 ] - > send ( channel , packet ) ; // Send to server for broadcast.
ERR_FAIL_COND_V ( ! hosts . has ( 0 ) , ERR_BUG ) ;
hosts [ 0 ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
2021-07-15 23:48:44 +00:00
} else {
if ( target_peer < = 0 ) {
int exclude = ABS ( target_peer ) ;
for ( KeyValue < int , Ref < ENetPacketPeer > > & E : peers ) {
if ( E . key = = exclude ) {
continue ;
}
E . value - > send ( channel , packet ) ;
ERR_CONTINUE ( ! hosts . has ( E . key ) ) ;
hosts [ E . key ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
_destroy_unused ( packet ) ;
2016-08-19 19:48:08 +00:00
} else {
2021-07-15 23:48:44 +00:00
peers [ target_peer ] - > send ( channel , packet ) ;
ERR_FAIL_COND_V ( ! hosts . has ( target_peer ) , ERR_BUG ) ;
hosts [ target_peer ] - > flush ( ) ;
2016-08-19 19:48:08 +00:00
}
2016-08-14 16:29:25 +00:00
}
return OK ;
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_max_packet_size ( ) const {
2018-04-08 20:45:14 +00:00
return 1 < < 24 ; // Anything is good
2016-08-14 16:29:25 +00:00
}
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : _pop_current_packet ( ) {
2016-08-14 16:29:25 +00:00
if ( current_packet . packet ) {
2021-07-15 23:48:44 +00:00
current_packet . packet - > referenceCount - - ;
_destroy_unused ( current_packet . packet ) ;
2020-04-01 23:20:12 +00:00
current_packet . packet = nullptr ;
2017-03-05 15:44:50 +00:00
current_packet . from = 0 ;
2018-05-12 17:42:00 +00:00
current_packet . channel = - 1 ;
2016-08-14 16:29:25 +00:00
}
}
2021-07-12 14:18:43 +00:00
MultiplayerPeer : : ConnectionStatus ENetMultiplayerPeer : : get_connection_status ( ) const {
2016-08-14 17:06:51 +00:00
return connection_status ;
}
2021-07-12 14:18:43 +00:00
int ENetMultiplayerPeer : : get_unique_id ( ) const {
2021-07-15 23:48:44 +00:00
ERR_FAIL_COND_V_MSG ( ! _is_active ( ) , 0 , " The multiplayer instance isn't currently active. " ) ;
2016-08-19 19:48:08 +00:00
return unique_id ;
}
2021-09-07 21:04:52 +00:00
void ENetMultiplayerPeer : : set_refuse_new_connections ( bool p_enabled ) {
2020-07-13 17:14:27 +00:00
# ifdef GODOT_ENET
2021-07-15 23:48:44 +00:00
if ( _is_active ( ) ) {
for ( KeyValue < int , Ref < ENetConnection > > & E : hosts ) {
2021-09-07 21:04:52 +00:00
E . value - > refuse_new_connections ( p_enabled ) ;
2021-07-15 23:48:44 +00:00
}
2020-07-23 08:38:48 +00:00
}
2020-07-13 17:14:27 +00:00
# endif
2021-09-07 21:04:52 +00:00
MultiplayerPeer : : set_refuse_new_connections ( p_enabled ) ;
2016-08-19 19:48:08 +00:00
}
2021-07-15 23:48:44 +00:00
Ref < ENetConnection > ENetMultiplayerPeer : : get_host ( ) const {
ERR_FAIL_COND_V ( ! _is_active ( ) , nullptr ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_MESH , nullptr ) ;
return hosts [ 0 ] ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
Ref < ENetPacketPeer > ENetMultiplayerPeer : : get_peer ( int p_id ) const {
ERR_FAIL_COND_V ( ! _is_active ( ) , nullptr ) ;
ERR_FAIL_COND_V ( ! peers . has ( p_id ) , nullptr ) ;
ERR_FAIL_COND_V ( active_mode = = MODE_CLIENT & & p_id ! = 1 , nullptr ) ;
return peers [ p_id ] ;
}
2016-08-22 04:14:08 +00:00
2021-07-15 23:48:44 +00:00
void ENetMultiplayerPeer : : _destroy_unused ( ENetPacket * p_packet ) {
if ( p_packet - > referenceCount = = 0 ) {
enet_packet_destroy ( p_packet ) ;
2016-08-22 04:14:08 +00:00
}
2021-07-15 23:48:44 +00:00
}
2016-08-22 04:14:08 +00:00
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : _bind_methods ( ) {
2021-07-15 23:48:44 +00:00
ClassDB : : bind_method ( D_METHOD ( " create_server " , " port " , " max_clients " , " max_channels " , " in_bandwidth " , " out_bandwidth " ) , & ENetMultiplayerPeer : : create_server , DEFVAL ( 32 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " create_client " , " address " , " port " , " channel_count " , " in_bandwidth " , " out_bandwidth " , " local_port " ) , & ENetMultiplayerPeer : : create_client , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) , DEFVAL ( 0 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " create_mesh " , " unique_id " ) , & ENetMultiplayerPeer : : create_mesh ) ;
ClassDB : : bind_method ( D_METHOD ( " add_mesh_peer " , " peer_id " , " host " ) , & ENetMultiplayerPeer : : add_mesh_peer ) ;
2021-07-12 14:18:43 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_bind_ip " , " ip " ) , & ENetMultiplayerPeer : : set_bind_ip ) ;
2021-07-15 23:48:44 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_host " ) , & ENetMultiplayerPeer : : get_host ) ;
ClassDB : : bind_method ( D_METHOD ( " get_peer " , " id " ) , & ENetMultiplayerPeer : : get_peer ) ;
2018-05-12 17:42:00 +00:00
2021-07-15 23:48:44 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " host " , PROPERTY_HINT_RESOURCE_TYPE , " ENetConnection " , PROPERTY_USAGE_NONE ) , " " , " get_host " ) ;
2016-08-14 17:06:51 +00:00
}
2021-07-12 14:18:43 +00:00
ENetMultiplayerPeer : : ENetMultiplayerPeer ( ) {
2021-05-06 00:48:18 +00:00
bind_ip = IPAddress ( " * " ) ;
2016-08-14 16:29:25 +00:00
}
2016-08-14 17:06:51 +00:00
2021-07-12 14:18:43 +00:00
ENetMultiplayerPeer : : ~ ENetMultiplayerPeer ( ) {
2021-07-15 23:48:44 +00:00
if ( _is_active ( ) ) {
2022-10-22 15:49:40 +00:00
close ( ) ;
2019-06-01 13:42:22 +00:00
}
2016-08-14 16:29:25 +00:00
}
2016-08-27 11:41:34 +00:00
2018-05-06 22:28:59 +00:00
// Sets IP for ENet to bind when using create_server or create_client
2016-08-27 11:41:34 +00:00
// if no IP is set, then ENet bind to ENET_HOST_ANY
2021-07-12 14:18:43 +00:00
void ENetMultiplayerPeer : : set_bind_ip ( const IPAddress & p_ip ) {
2020-02-02 22:34:47 +00:00
ERR_FAIL_COND_MSG ( ! p_ip . is_valid ( ) & & ! p_ip . is_wildcard ( ) , vformat ( " Invalid bind IP address: %s " , String ( p_ip ) ) ) ;
2017-01-22 05:00:59 +00:00
bind_ip = p_ip ;
2016-08-27 11:41:34 +00:00
}