2018-05-16 17:19:33 +00:00
/*************************************************************************/
/* multiplayer_api.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2018-05-16 17:19:33 +00:00
/* */
/* 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-09-11 16:13:45 +00:00
# include "multiplayer_api.h"
2020-02-27 02:30:20 +00:00
# include "core/debugger/engine_debugger.h"
2018-03-03 17:28:49 +00:00
# include "core/io/marshalls.h"
2021-09-03 17:40:47 +00:00
# include "core/multiplayer/multiplayer_replicator.h"
# include "core/multiplayer/rpc_manager.h"
2018-03-03 17:28:49 +00:00
# include "scene/main/node.h"
2020-05-12 15:01:17 +00:00
2020-02-12 10:51:50 +00:00
# include <stdint.h>
2018-03-03 17:28:49 +00:00
2019-09-01 16:38:58 +00:00
# ifdef DEBUG_ENABLED
# include "core/os/os.h"
# endif
2021-09-03 17:40:47 +00:00
# ifdef DEBUG_ENABLED
void MultiplayerAPI : : profile_bandwidth ( const String & p_inout , int p_size ) {
if ( EngineDebugger : : is_profiling ( " multiplayer " ) ) {
Array values ;
values . push_back ( " bandwidth " ) ;
values . push_back ( p_inout ) ;
values . push_back ( OS : : get_singleton ( ) - > get_ticks_msec ( ) ) ;
values . push_back ( p_size ) ;
EngineDebugger : : profiler_add_frame_data ( " multiplayer " , values ) ;
2018-05-13 05:07:56 +00:00
}
}
2021-09-03 17:40:47 +00:00
# endif
2018-05-13 05:07:56 +00:00
2018-03-03 17:28:49 +00:00
void MultiplayerAPI : : poll ( ) {
2021-09-07 21:35:19 +00:00
if ( ! multiplayer_peer . is_valid ( ) | | multiplayer_peer - > get_connection_status ( ) = = MultiplayerPeer : : CONNECTION_DISCONNECTED ) {
2018-03-03 17:28:49 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
multiplayer_peer - > poll ( ) ;
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
if ( ! multiplayer_peer . is_valid ( ) ) { // It's possible that polling might have resulted in a disconnection, so check here.
2018-03-03 17:28:49 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
while ( multiplayer_peer - > get_available_packet_count ( ) ) {
int sender = multiplayer_peer - > get_packet_peer ( ) ;
2018-03-03 17:28:49 +00:00
const uint8_t * packet ;
int len ;
2021-09-07 21:35:19 +00:00
Error err = multiplayer_peer - > get_packet ( & packet , len ) ;
2018-03-03 17:28:49 +00:00
if ( err ! = OK ) {
ERR_PRINT ( " Error getting packet! " ) ;
2020-01-21 19:46:32 +00:00
break ; // Something is wrong!
2018-03-03 17:28:49 +00:00
}
2021-09-03 17:40:47 +00:00
remote_sender_id = sender ;
2018-03-03 17:28:49 +00:00
_process_packet ( sender , packet , len ) ;
2021-09-03 17:40:47 +00:00
remote_sender_id = 0 ;
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
if ( ! multiplayer_peer . is_valid ( ) ) {
2018-09-25 15:44:26 +00:00
break ; // It's also possible that a packet or RPC caused a disconnection, so also check here.
2018-03-03 17:28:49 +00:00
}
}
2021-09-07 21:35:19 +00:00
if ( multiplayer_peer . is_valid ( ) & & multiplayer_peer - > get_connection_status ( ) = = MultiplayerPeer : : CONNECTION_CONNECTED ) {
2021-08-12 19:07:44 +00:00
replicator - > poll ( ) ;
}
2018-03-03 17:28:49 +00:00
}
void MultiplayerAPI : : clear ( ) {
2021-08-09 20:46:23 +00:00
replicator - > clear ( ) ;
2018-03-03 17:28:49 +00:00
connected_peers . clear ( ) ;
path_get_cache . clear ( ) ;
path_send_cache . clear ( ) ;
2019-01-15 09:35:26 +00:00
packet_cache . clear ( ) ;
2018-03-03 17:28:49 +00:00
last_send_cache_id = 1 ;
}
void MultiplayerAPI : : set_root_node ( Node * p_node ) {
root_node = p_node ;
}
2020-06-01 08:34:15 +00:00
Node * MultiplayerAPI : : get_root_node ( ) {
return root_node ;
}
2021-09-07 21:35:19 +00:00
void MultiplayerAPI : : set_multiplayer_peer ( const Ref < MultiplayerPeer > & p_peer ) {
if ( p_peer = = multiplayer_peer ) {
2020-05-10 10:56:01 +00:00
return ; // Nothing to do
2020-05-14 14:41:43 +00:00
}
2019-01-15 10:14:51 +00:00
2021-07-12 14:11:05 +00:00
ERR_FAIL_COND_MSG ( p_peer . is_valid ( ) & & p_peer - > get_connection_status ( ) = = MultiplayerPeer : : CONNECTION_DISCONNECTED ,
" Supplied MultiplayerPeer must be connecting or connected. " ) ;
2020-01-03 12:34:51 +00:00
2021-09-07 21:35:19 +00:00
if ( multiplayer_peer . is_valid ( ) ) {
multiplayer_peer - > disconnect ( " peer_connected " , callable_mp ( this , & MultiplayerAPI : : _add_peer ) ) ;
multiplayer_peer - > disconnect ( " peer_disconnected " , callable_mp ( this , & MultiplayerAPI : : _del_peer ) ) ;
multiplayer_peer - > disconnect ( " connection_succeeded " , callable_mp ( this , & MultiplayerAPI : : _connected_to_server ) ) ;
multiplayer_peer - > disconnect ( " connection_failed " , callable_mp ( this , & MultiplayerAPI : : _connection_failed ) ) ;
multiplayer_peer - > disconnect ( " server_disconnected " , callable_mp ( this , & MultiplayerAPI : : _server_disconnected ) ) ;
2018-03-03 17:28:49 +00:00
clear ( ) ;
}
2021-09-07 21:35:19 +00:00
multiplayer_peer = p_peer ;
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
if ( multiplayer_peer . is_valid ( ) ) {
multiplayer_peer - > connect ( " peer_connected " , callable_mp ( this , & MultiplayerAPI : : _add_peer ) ) ;
multiplayer_peer - > connect ( " peer_disconnected " , callable_mp ( this , & MultiplayerAPI : : _del_peer ) ) ;
multiplayer_peer - > connect ( " connection_succeeded " , callable_mp ( this , & MultiplayerAPI : : _connected_to_server ) ) ;
multiplayer_peer - > connect ( " connection_failed " , callable_mp ( this , & MultiplayerAPI : : _connection_failed ) ) ;
multiplayer_peer - > connect ( " server_disconnected " , callable_mp ( this , & MultiplayerAPI : : _server_disconnected ) ) ;
2018-03-03 17:28:49 +00:00
}
}
2021-09-07 21:35:19 +00:00
Ref < MultiplayerPeer > MultiplayerAPI : : get_multiplayer_peer ( ) const {
return multiplayer_peer ;
2018-03-03 17:28:49 +00:00
}
void MultiplayerAPI : : _process_packet ( int p_from , const uint8_t * p_packet , int p_packet_len ) {
2020-04-01 23:20:12 +00:00
ERR_FAIL_COND_MSG ( root_node = = nullptr , " Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it. " ) ;
2019-08-15 02:57:49 +00:00
ERR_FAIL_COND_MSG ( p_packet_len < 1 , " Invalid packet received. Size too small. " ) ;
2018-03-03 17:28:49 +00:00
2019-09-01 16:38:58 +00:00
# ifdef DEBUG_ENABLED
2021-09-03 17:40:47 +00:00
profile_bandwidth ( " in " , p_packet_len ) ;
2019-09-01 16:38:58 +00:00
# endif
2020-02-12 10:51:50 +00:00
// Extract the `packet_type` from the LSB three bits:
2021-09-03 17:40:47 +00:00
uint8_t packet_type = p_packet [ 0 ] & CMD_MASK ;
2018-03-03 17:28:49 +00:00
switch ( packet_type ) {
case NETWORK_COMMAND_SIMPLIFY_PATH : {
_process_simplify_path ( p_from , p_packet , p_packet_len ) ;
} break ;
case NETWORK_COMMAND_CONFIRM_PATH : {
_process_confirm_path ( p_from , p_packet , p_packet_len ) ;
} break ;
2021-05-26 12:07:57 +00:00
case NETWORK_COMMAND_REMOTE_CALL : {
2021-09-03 17:40:47 +00:00
rpc_manager - > process_rpc ( p_from , p_packet , p_packet_len ) ;
2018-03-03 17:28:49 +00:00
} break ;
2018-05-11 19:34:45 +00:00
case NETWORK_COMMAND_RAW : {
_process_raw ( p_from , p_packet , p_packet_len ) ;
} break ;
2021-07-30 00:14:37 +00:00
case NETWORK_COMMAND_SPAWN : {
2021-08-09 20:46:23 +00:00
replicator - > process_spawn_despawn ( p_from , p_packet , p_packet_len , true ) ;
2021-07-30 00:14:37 +00:00
} break ;
case NETWORK_COMMAND_DESPAWN : {
2021-08-09 20:46:23 +00:00
replicator - > process_spawn_despawn ( p_from , p_packet , p_packet_len , false ) ;
2021-07-30 00:14:37 +00:00
} break ;
2021-08-12 19:07:44 +00:00
case NETWORK_COMMAND_SYNC : {
replicator - > process_sync ( p_from , p_packet , p_packet_len ) ;
} break ;
2018-03-03 17:28:49 +00:00
}
}
void MultiplayerAPI : : _process_simplify_path ( int p_from , const uint8_t * p_packet , int p_packet_len ) {
2020-02-12 10:51:50 +00:00
ERR_FAIL_COND_MSG ( p_packet_len < 38 , " Invalid packet received. Size too small. " ) ;
int ofs = 1 ;
String methods_md5 ;
methods_md5 . parse_utf8 ( ( const char * ) ( p_packet + ofs ) , 32 ) ;
ofs + = 33 ;
int id = decode_uint32 ( & p_packet [ ofs ] ) ;
ofs + = 4 ;
2018-03-03 17:28:49 +00:00
String paths ;
2020-02-12 10:51:50 +00:00
paths . parse_utf8 ( ( const char * ) ( p_packet + ofs ) , p_packet_len - ofs ) ;
2018-03-03 17:28:49 +00:00
NodePath path = paths ;
if ( ! path_get_cache . has ( p_from ) ) {
path_get_cache [ p_from ] = PathGetCache ( ) ;
}
2020-02-12 10:51:50 +00:00
Node * node = root_node - > get_node ( path ) ;
2020-04-01 23:20:12 +00:00
ERR_FAIL_COND ( node = = nullptr ) ;
2021-09-03 17:40:47 +00:00
const bool valid_rpc_checksum = rpc_manager - > get_rpc_md5 ( node ) = = methods_md5 ;
2020-02-12 10:51:50 +00:00
if ( valid_rpc_checksum = = false ) {
ERR_PRINT ( " The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path ) ;
}
2018-03-03 17:28:49 +00:00
PathGetCache : : NodeInfo ni ;
ni . path = path ;
path_get_cache [ p_from ] . nodes [ id ] = ni ;
2018-09-25 15:44:26 +00:00
// Encode path to send ack.
2018-03-03 17:28:49 +00:00
CharString pname = String ( path ) . utf8 ( ) ;
2020-04-01 23:20:12 +00:00
int len = encode_cstring ( pname . get_data ( ) , nullptr ) ;
2018-03-03 17:28:49 +00:00
Vector < uint8_t > packet ;
2020-02-12 10:51:50 +00:00
packet . resize ( 1 + 1 + len ) ;
2018-07-25 01:11:03 +00:00
packet . write [ 0 ] = NETWORK_COMMAND_CONFIRM_PATH ;
2020-02-12 10:51:50 +00:00
packet . write [ 1 ] = valid_rpc_checksum ;
encode_cstring ( pname . get_data ( ) , & packet . write [ 2 ] ) ;
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
multiplayer_peer - > set_transfer_channel ( 0 ) ;
multiplayer_peer - > set_transfer_mode ( Multiplayer : : TRANSFER_MODE_RELIABLE ) ;
multiplayer_peer - > set_target_peer ( p_from ) ;
multiplayer_peer - > put_packet ( packet . ptr ( ) , packet . size ( ) ) ;
2018-03-03 17:28:49 +00:00
}
void MultiplayerAPI : : _process_confirm_path ( int p_from , const uint8_t * p_packet , int p_packet_len ) {
2020-02-12 10:51:50 +00:00
ERR_FAIL_COND_MSG ( p_packet_len < 3 , " Invalid packet received. Size too small. " ) ;
const bool valid_rpc_checksum = p_packet [ 1 ] ;
2018-05-11 19:34:45 +00:00
2018-03-03 17:28:49 +00:00
String paths ;
2020-02-12 10:51:50 +00:00
paths . parse_utf8 ( ( const char * ) & p_packet [ 2 ] , p_packet_len - 2 ) ;
2018-03-03 17:28:49 +00:00
NodePath path = paths ;
2020-02-12 10:51:50 +00:00
if ( valid_rpc_checksum = = false ) {
ERR_PRINT ( " The rpc node checksum failed. Make sure to have the same methods on both nodes. Node path: " + path ) ;
}
2018-03-03 17:28:49 +00:00
PathSentCache * psc = path_send_cache . getptr ( path ) ;
2019-08-15 02:57:49 +00:00
ERR_FAIL_COND_MSG ( ! psc , " Invalid packet received. Tries to confirm a path which was not found in cache. " ) ;
2018-03-03 17:28:49 +00:00
Map < int , bool > : : Element * E = psc - > confirmed_peers . find ( p_from ) ;
2019-08-15 02:57:49 +00:00
ERR_FAIL_COND_MSG ( ! E , " Invalid packet received. Source peer was not found in cache for the given path. " ) ;
2018-03-03 17:28:49 +00:00
E - > get ( ) = true ;
}
2020-02-12 10:51:50 +00:00
bool MultiplayerAPI : : _send_confirm_path ( Node * p_node , NodePath p_path , PathSentCache * psc , int p_target ) {
2018-03-03 17:28:49 +00:00
bool has_all_peers = true ;
2018-09-25 15:44:26 +00:00
List < int > peers_to_add ; // If one is missing, take note to add it.
2018-03-03 17:28:49 +00:00
for ( Set < int > : : Element * E = connected_peers . front ( ) ; E ; E = E - > next ( ) ) {
2020-05-14 14:41:43 +00:00
if ( p_target < 0 & & E - > get ( ) = = - p_target ) {
2018-09-25 15:44:26 +00:00
continue ; // Continue, excluded.
2020-05-14 14:41:43 +00:00
}
2018-03-03 17:28:49 +00:00
2020-05-14 14:41:43 +00:00
if ( p_target > 0 & & E - > get ( ) ! = p_target ) {
2018-09-25 15:44:26 +00:00
continue ; // Continue, not for this peer.
2020-05-14 14:41:43 +00:00
}
2018-03-03 17:28:49 +00:00
Map < int , bool > : : Element * F = psc - > confirmed_peers . find ( E - > get ( ) ) ;
2018-10-06 20:20:41 +00:00
if ( ! F | | ! F - > get ( ) ) {
2018-09-25 15:44:26 +00:00
// Path was not cached, or was cached but is unconfirmed.
2018-03-03 17:28:49 +00:00
if ( ! F ) {
2018-09-25 15:44:26 +00:00
// Not cached at all, take note.
2018-03-03 17:28:49 +00:00
peers_to_add . push_back ( E - > get ( ) ) ;
}
has_all_peers = false ;
}
}
2020-02-12 10:51:50 +00:00
if ( peers_to_add . size ( ) > 0 ) {
// Those that need to be added, send a message for this.
2018-03-03 17:28:49 +00:00
2018-09-25 15:44:26 +00:00
// Encode function name.
2020-02-12 10:51:50 +00:00
const CharString path = String ( p_path ) . utf8 ( ) ;
2020-04-01 23:20:12 +00:00
const int path_len = encode_cstring ( path . get_data ( ) , nullptr ) ;
2020-02-12 10:51:50 +00:00
// Extract MD5 from rpc methods list.
2021-09-03 17:40:47 +00:00
const String methods_md5 = rpc_manager - > get_rpc_md5 ( p_node ) ;
2020-02-12 10:51:50 +00:00
const int methods_md5_len = 33 ; // 32 + 1 for the `0` that is added by the encoder.
2018-03-03 17:28:49 +00:00
Vector < uint8_t > packet ;
2020-02-12 10:51:50 +00:00
packet . resize ( 1 + 4 + path_len + methods_md5_len ) ;
int ofs = 0 ;
packet . write [ ofs ] = NETWORK_COMMAND_SIMPLIFY_PATH ;
ofs + = 1 ;
ofs + = encode_cstring ( methods_md5 . utf8 ( ) . get_data ( ) , & packet . write [ ofs ] ) ;
ofs + = encode_uint32 ( psc - > id , & packet . write [ ofs ] ) ;
ofs + = encode_cstring ( path . get_data ( ) , & packet . write [ ofs ] ) ;
2018-03-03 17:28:49 +00:00
2021-07-16 03:45:57 +00:00
for ( int & E : peers_to_add ) {
2021-09-07 21:35:19 +00:00
multiplayer_peer - > set_target_peer ( E ) ; // To all of you.
multiplayer_peer - > set_transfer_channel ( 0 ) ;
multiplayer_peer - > set_transfer_mode ( Multiplayer : : TRANSFER_MODE_RELIABLE ) ;
multiplayer_peer - > put_packet ( packet . ptr ( ) , packet . size ( ) ) ;
2018-03-03 17:28:49 +00:00
2021-07-16 03:45:57 +00:00
psc - > confirmed_peers . insert ( E , false ) ; // Insert into confirmed, but as false since it was not confirmed.
2020-02-12 10:51:50 +00:00
}
2018-03-03 17:28:49 +00:00
}
return has_all_peers ;
}
2020-02-12 10:51:50 +00:00
// The variant is compressed and encoded; The first byte contains all the meta
// information and the format is:
// - The first LSB 5 bits are used for the variant type.
// - The next two bits are used to store the encoding mode.
// - The most significant is used to store the boolean value.
# define VARIANT_META_TYPE_MASK 0x1F
# define VARIANT_META_EMODE_MASK 0x60
# define VARIANT_META_BOOL_MASK 0x80
# define ENCODE_8 0 << 5
# define ENCODE_16 1 << 5
# define ENCODE_32 2 << 5
# define ENCODE_64 3 << 5
2021-08-09 20:46:23 +00:00
Error MultiplayerAPI : : encode_and_compress_variant ( const Variant & p_variant , uint8_t * r_buffer , int & r_len ) {
2020-02-12 10:51:50 +00:00
// Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
CRASH_COND ( p_variant . get_type ( ) > VARIANT_META_TYPE_MASK ) ;
uint8_t * buf = r_buffer ;
r_len = 0 ;
uint8_t encode_mode = 0 ;
switch ( p_variant . get_type ( ) ) {
case Variant : : BOOL : {
if ( buf ) {
// We still have 1 free bit in the meta, so let's use it.
buf [ 0 ] = ( p_variant . operator bool ( ) ) ? ( 1 < < 7 ) : 0 ;
buf [ 0 ] | = encode_mode | p_variant . get_type ( ) ;
}
r_len + = 1 ;
} break ;
case Variant : : INT : {
if ( buf ) {
// Reserve the first byte for the meta.
buf + = 1 ;
}
r_len + = 1 ;
int64_t val = p_variant ;
if ( val < = ( int64_t ) INT8_MAX & & val > = ( int64_t ) INT8_MIN ) {
// Use 8 bit
encode_mode = ENCODE_8 ;
if ( buf ) {
buf [ 0 ] = val ;
}
r_len + = 1 ;
} else if ( val < = ( int64_t ) INT16_MAX & & val > = ( int64_t ) INT16_MIN ) {
// Use 16 bit
encode_mode = ENCODE_16 ;
if ( buf ) {
encode_uint16 ( val , buf ) ;
}
r_len + = 2 ;
} else if ( val < = ( int64_t ) INT32_MAX & & val > = ( int64_t ) INT32_MIN ) {
// Use 32 bit
encode_mode = ENCODE_32 ;
if ( buf ) {
encode_uint32 ( val , buf ) ;
}
r_len + = 4 ;
} else {
// Use 64 bit
encode_mode = ENCODE_64 ;
if ( buf ) {
encode_uint64 ( val , buf ) ;
}
r_len + = 8 ;
}
// Store the meta
if ( buf ) {
buf - = 1 ;
buf [ 0 ] = encode_mode | p_variant . get_type ( ) ;
}
} break ;
default :
// Any other case is not yet compressed.
2020-02-12 11:14:18 +00:00
Error err = encode_variant ( p_variant , r_buffer , r_len , allow_object_decoding ) ;
2020-05-14 14:41:43 +00:00
if ( err ! = OK ) {
2020-02-12 10:51:50 +00:00
return err ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
if ( r_buffer ) {
2021-03-12 13:35:16 +00:00
// The first byte is not used by the marshalling, so store the type
2020-02-12 10:51:50 +00:00
// so we know how to decompress and decode this variant.
r_buffer [ 0 ] = p_variant . get_type ( ) ;
}
}
return OK ;
}
2020-05-14 12:29:06 +00:00
2021-08-09 20:46:23 +00:00
Error MultiplayerAPI : : decode_and_decompress_variant ( Variant & r_variant , const uint8_t * p_buffer , int p_len , int * r_len ) {
2020-02-12 10:51:50 +00:00
const uint8_t * buf = p_buffer ;
int len = p_len ;
ERR_FAIL_COND_V ( len < 1 , ERR_INVALID_DATA ) ;
uint8_t type = buf [ 0 ] & VARIANT_META_TYPE_MASK ;
uint8_t encode_mode = buf [ 0 ] & VARIANT_META_EMODE_MASK ;
ERR_FAIL_COND_V ( type > = Variant : : VARIANT_MAX , ERR_INVALID_DATA ) ;
switch ( type ) {
case Variant : : BOOL : {
bool val = ( buf [ 0 ] & VARIANT_META_BOOL_MASK ) > 0 ;
r_variant = val ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
* r_len = 1 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
} break ;
case Variant : : INT : {
buf + = 1 ;
len - = 1 ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
* r_len = 1 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
if ( encode_mode = = ENCODE_8 ) {
// 8 bits.
ERR_FAIL_COND_V ( len < 1 , ERR_INVALID_DATA ) ;
int8_t val = buf [ 0 ] ;
r_variant = val ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
( * r_len ) + = 1 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
} else if ( encode_mode = = ENCODE_16 ) {
// 16 bits.
ERR_FAIL_COND_V ( len < 2 , ERR_INVALID_DATA ) ;
int16_t val = decode_uint16 ( buf ) ;
r_variant = val ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
( * r_len ) + = 2 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
} else if ( encode_mode = = ENCODE_32 ) {
// 32 bits.
ERR_FAIL_COND_V ( len < 4 , ERR_INVALID_DATA ) ;
int32_t val = decode_uint32 ( buf ) ;
r_variant = val ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
( * r_len ) + = 4 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
} else {
// 64 bits.
ERR_FAIL_COND_V ( len < 8 , ERR_INVALID_DATA ) ;
int64_t val = decode_uint64 ( buf ) ;
r_variant = val ;
2020-05-14 14:41:43 +00:00
if ( r_len ) {
2020-02-12 10:51:50 +00:00
( * r_len ) + = 8 ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
}
} break ;
default :
2020-02-12 11:14:18 +00:00
Error err = decode_variant ( r_variant , p_buffer , p_len , r_len , allow_object_decoding ) ;
2020-05-14 14:41:43 +00:00
if ( err ! = OK ) {
2020-02-12 10:51:50 +00:00
return err ;
2020-05-14 14:41:43 +00:00
}
2020-02-12 10:51:50 +00:00
}
return OK ;
}
2018-05-08 09:49:57 +00:00
void MultiplayerAPI : : _add_peer ( int p_id ) {
2018-03-03 17:28:49 +00:00
connected_peers . insert ( p_id ) ;
path_get_cache . insert ( p_id , PathGetCache ( ) ) ;
2021-09-07 21:35:19 +00:00
if ( is_server ( ) ) {
2021-08-09 20:46:23 +00:00
replicator - > spawn_all ( p_id ) ;
2021-07-30 00:14:37 +00:00
}
2021-09-07 21:35:19 +00:00
emit_signal ( SNAME ( " peer_connected " ) , p_id ) ;
2018-03-03 17:28:49 +00:00
}
2018-05-08 09:49:57 +00:00
void MultiplayerAPI : : _del_peer ( int p_id ) {
2018-03-03 17:28:49 +00:00
connected_peers . erase ( p_id ) ;
2019-10-25 16:00:49 +00:00
// Cleanup get cache.
path_get_cache . erase ( p_id ) ;
// Cleanup sent cache.
// Some refactoring is needed to make this faster and do paths GC.
List < NodePath > keys ;
path_send_cache . get_key_list ( & keys ) ;
2021-07-24 13:46:25 +00:00
for ( const NodePath & E : keys ) {
2021-07-16 03:45:57 +00:00
PathSentCache * psc = path_send_cache . getptr ( E ) ;
2019-10-25 16:00:49 +00:00
psc - > confirmed_peers . erase ( p_id ) ;
}
2021-09-07 21:35:19 +00:00
emit_signal ( SNAME ( " peer_disconnected " ) , p_id ) ;
2018-03-03 17:28:49 +00:00
}
2018-05-08 09:49:57 +00:00
void MultiplayerAPI : : _connected_to_server ( ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " connected_to_server " ) ) ;
2018-03-03 17:28:49 +00:00
}
2018-05-08 09:49:57 +00:00
void MultiplayerAPI : : _connection_failed ( ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " connection_failed " ) ) ;
2018-03-03 17:28:49 +00:00
}
2018-05-08 09:49:57 +00:00
void MultiplayerAPI : : _server_disconnected ( ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " server_disconnected " ) ) ;
2018-03-03 17:28:49 +00:00
}
2021-09-03 17:40:47 +00:00
Error MultiplayerAPI : : send_bytes ( Vector < uint8_t > p_data , int p_to , Multiplayer : : TransferMode p_mode , int p_channel ) {
2019-08-15 02:57:49 +00:00
ERR_FAIL_COND_V_MSG ( p_data . size ( ) < 1 , ERR_INVALID_DATA , " Trying to send an empty raw packet. " ) ;
2021-09-07 21:35:19 +00:00
ERR_FAIL_COND_V_MSG ( ! multiplayer_peer . is_valid ( ) , ERR_UNCONFIGURED , " Trying to send a raw packet while no multiplayer peer is active. " ) ;
ERR_FAIL_COND_V_MSG ( multiplayer_peer - > get_connection_status ( ) ! = MultiplayerPeer : : CONNECTION_CONNECTED , ERR_UNCONFIGURED , " Trying to send a raw packet via a multiplayer peer which is not connected. " ) ;
2018-05-11 19:34:45 +00:00
2021-09-03 17:40:47 +00:00
if ( packet_cache . size ( ) < p_data . size ( ) + 1 ) {
packet_cache . resize ( p_data . size ( ) + 1 ) ;
}
2020-02-17 21:06:54 +00:00
const uint8_t * r = p_data . ptr ( ) ;
2018-07-25 01:11:03 +00:00
packet_cache . write [ 0 ] = NETWORK_COMMAND_RAW ;
memcpy ( & packet_cache . write [ 1 ] , & r [ 0 ] , p_data . size ( ) ) ;
2018-07-08 07:47:22 +00:00
2021-09-07 21:35:19 +00:00
multiplayer_peer - > set_target_peer ( p_to ) ;
multiplayer_peer - > set_transfer_channel ( p_channel ) ;
multiplayer_peer - > set_transfer_mode ( p_mode ) ;
2018-07-08 07:47:22 +00:00
2021-09-07 21:35:19 +00:00
return multiplayer_peer - > put_packet ( packet_cache . ptr ( ) , p_data . size ( ) + 1 ) ;
2018-05-11 19:34:45 +00:00
}
void MultiplayerAPI : : _process_raw ( int p_from , const uint8_t * p_packet , int p_packet_len ) {
2019-08-15 02:57:49 +00:00
ERR_FAIL_COND_MSG ( p_packet_len < 2 , " Invalid packet received. Size too small. " ) ;
2018-05-11 19:34:45 +00:00
2020-02-17 21:06:54 +00:00
Vector < uint8_t > out ;
2018-05-11 19:34:45 +00:00
int len = p_packet_len - 1 ;
out . resize ( len ) ;
{
2020-02-17 21:06:54 +00:00
uint8_t * w = out . ptrw ( ) ;
2018-05-11 19:34:45 +00:00
memcpy ( & w [ 0 ] , & p_packet [ 1 ] , len ) ;
}
2021-09-07 21:35:19 +00:00
emit_signal ( SNAME ( " peer_packet " ) , p_from , out ) ;
2018-05-11 19:34:45 +00:00
}
2021-09-03 17:40:47 +00:00
bool MultiplayerAPI : : is_cache_confirmed ( NodePath p_path , int p_peer ) {
const PathSentCache * psc = path_send_cache . getptr ( p_path ) ;
ERR_FAIL_COND_V ( ! psc , false ) ;
const Map < int , bool > : : Element * F = psc - > confirmed_peers . find ( p_peer ) ;
ERR_FAIL_COND_V ( ! F , false ) ; // Should never happen.
return F - > get ( ) ;
}
2021-08-09 20:46:23 +00:00
bool MultiplayerAPI : : send_confirm_path ( Node * p_node , NodePath p_path , int p_peer_id , int & r_id ) {
// See if the path is cached.
PathSentCache * psc = path_send_cache . getptr ( p_path ) ;
if ( ! psc ) {
// Path is not cached, create.
path_send_cache [ p_path ] = PathSentCache ( ) ;
psc = path_send_cache . getptr ( p_path ) ;
psc - > id = last_send_cache_id + + ;
}
r_id = psc - > id ;
// See if all peers have cached path (if so, call can be fast).
return _send_confirm_path ( p_node , p_path , psc , p_peer_id ) ;
}
Node * MultiplayerAPI : : get_cached_node ( int p_from , uint32_t p_node_id ) {
Map < int , PathGetCache > : : Element * E = path_get_cache . find ( p_from ) ;
ERR_FAIL_COND_V_MSG ( ! E , nullptr , vformat ( " No cache found for peer %d. " , p_from ) ) ;
Map < int , PathGetCache : : NodeInfo > : : Element * F = E - > get ( ) . nodes . find ( p_node_id ) ;
ERR_FAIL_COND_V_MSG ( ! F , nullptr , vformat ( " ID %d not found in cache of peer %d. " , p_node_id , p_from ) ) ;
PathGetCache : : NodeInfo * ni = & F - > get ( ) ;
Node * node = root_node - > get_node ( ni - > path ) ;
if ( ! node ) {
ERR_PRINT ( " Failed to get cached path: " + String ( ni - > path ) + " . " ) ;
}
return node ;
}
2021-09-07 21:35:19 +00:00
int MultiplayerAPI : : get_unique_id ( ) const {
ERR_FAIL_COND_V_MSG ( ! multiplayer_peer . is_valid ( ) , 0 , " No multiplayer peer is assigned. Unable to get unique ID. " ) ;
return multiplayer_peer - > get_unique_id ( ) ;
2018-03-03 17:28:49 +00:00
}
2021-09-07 21:35:19 +00:00
bool MultiplayerAPI : : is_server ( ) const {
return multiplayer_peer . is_valid ( ) & & multiplayer_peer - > is_server ( ) ;
2018-03-03 17:28:49 +00:00
}
2021-09-07 21:35:19 +00:00
void MultiplayerAPI : : set_refuse_new_connections ( bool p_refuse ) {
ERR_FAIL_COND_MSG ( ! multiplayer_peer . is_valid ( ) , " No multiplayer peer is assigned. Unable to set 'refuse_new_connections'. " ) ;
multiplayer_peer - > set_refuse_new_connections ( p_refuse ) ;
2018-03-03 17:28:49 +00:00
}
2021-09-07 21:35:19 +00:00
bool MultiplayerAPI : : is_refusing_new_connections ( ) const {
ERR_FAIL_COND_V_MSG ( ! multiplayer_peer . is_valid ( ) , false , " No multiplayer peer is assigned. Unable to get 'refuse_new_connections'. " ) ;
return multiplayer_peer - > is_refusing_new_connections ( ) ;
2018-03-03 17:28:49 +00:00
}
2021-09-07 21:35:19 +00:00
Vector < int > MultiplayerAPI : : get_peer_ids ( ) const {
ERR_FAIL_COND_V_MSG ( ! multiplayer_peer . is_valid ( ) , Vector < int > ( ) , " No multiplayer peer is assigned. Assume no peers are connected. " ) ;
2018-03-03 17:28:49 +00:00
Vector < int > ret ;
for ( Set < int > : : Element * E = connected_peers . front ( ) ; E ; E = E - > next ( ) ) {
ret . push_back ( E - > get ( ) ) ;
}
return ret ;
}
2019-03-26 15:52:42 +00:00
void MultiplayerAPI : : set_allow_object_decoding ( bool p_enable ) {
allow_object_decoding = p_enable ;
}
bool MultiplayerAPI : : is_object_decoding_allowed ( ) const {
return allow_object_decoding ;
}
2021-08-09 20:46:23 +00:00
void MultiplayerAPI : : scene_enter_exit_notify ( const String & p_scene , Node * p_node , bool p_enter ) {
replicator - > scene_enter_exit_notify ( p_scene , p_node , p_enter ) ;
2021-07-30 00:14:37 +00:00
}
2021-09-03 17:40:47 +00:00
void MultiplayerAPI : : rpcp ( Node * p_node , int p_peer_id , const StringName & p_method , const Variant * * p_arg , int p_argcount ) {
rpc_manager - > rpcp ( p_node , p_peer_id , p_method , p_arg , p_argcount ) ;
}
2018-03-03 17:28:49 +00:00
void MultiplayerAPI : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " set_root_node " , " node " ) , & MultiplayerAPI : : set_root_node ) ;
2020-06-01 08:34:15 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_root_node " ) , & MultiplayerAPI : : get_root_node ) ;
2021-09-03 17:40:47 +00:00
ClassDB : : bind_method ( D_METHOD ( " send_bytes " , " bytes " , " id " , " mode " , " channel " ) , & MultiplayerAPI : : send_bytes , DEFVAL ( MultiplayerPeer : : TARGET_PEER_BROADCAST ) , DEFVAL ( Multiplayer : : TRANSFER_MODE_RELIABLE ) , DEFVAL ( 0 ) ) ;
2021-09-07 21:35:19 +00:00
ClassDB : : bind_method ( D_METHOD ( " has_multiplayer_peer " ) , & MultiplayerAPI : : has_multiplayer_peer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_multiplayer_peer " ) , & MultiplayerAPI : : get_multiplayer_peer ) ;
ClassDB : : bind_method ( D_METHOD ( " set_multiplayer_peer " , " peer " ) , & MultiplayerAPI : : set_multiplayer_peer ) ;
ClassDB : : bind_method ( D_METHOD ( " get_unique_id " ) , & MultiplayerAPI : : get_unique_id ) ;
ClassDB : : bind_method ( D_METHOD ( " is_server " ) , & MultiplayerAPI : : is_server ) ;
2021-09-03 17:40:47 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_remote_sender_id " ) , & MultiplayerAPI : : get_remote_sender_id ) ;
2018-03-03 17:28:49 +00:00
ClassDB : : bind_method ( D_METHOD ( " poll " ) , & MultiplayerAPI : : poll ) ;
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & MultiplayerAPI : : clear ) ;
2021-09-07 21:35:19 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_peers " ) , & MultiplayerAPI : : get_peer_ids ) ;
ClassDB : : bind_method ( D_METHOD ( " set_refuse_new_connections " , " refuse " ) , & MultiplayerAPI : : set_refuse_new_connections ) ;
ClassDB : : bind_method ( D_METHOD ( " is_refusing_new_connections " ) , & MultiplayerAPI : : is_refusing_new_connections ) ;
2019-03-26 15:52:42 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_object_decoding " , " enable " ) , & MultiplayerAPI : : set_allow_object_decoding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_object_decoding_allowed " ) , & MultiplayerAPI : : is_object_decoding_allowed ) ;
2021-08-09 20:46:23 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_replicator " ) , & MultiplayerAPI : : get_replicator ) ;
2019-03-26 15:52:42 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_object_decoding " ) , " set_allow_object_decoding " , " is_object_decoding_allowed " ) ;
2021-09-07 21:35:19 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " refuse_new_connections " ) , " set_refuse_new_connections " , " is_refusing_new_connections " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " multiplayer_peer " , PROPERTY_HINT_RESOURCE_TYPE , " MultiplayerPeer " , PROPERTY_USAGE_NONE ) , " set_multiplayer_peer " , " get_multiplayer_peer " ) ;
2021-06-17 23:10:18 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " root_node " , PROPERTY_HINT_RESOURCE_TYPE , " Node " , PROPERTY_USAGE_NONE ) , " set_root_node " , " get_root_node " ) ;
2021-09-07 21:35:19 +00:00
ADD_PROPERTY_DEFAULT ( " refuse_new_connections " , false ) ;
2021-08-09 20:46:23 +00:00
ADD_PROPERTY ( PropertyInfo ( Variant : : OBJECT , " replicator " , PROPERTY_HINT_RESOURCE_TYPE , " MultiplayerReplicator " , PROPERTY_USAGE_NONE ) , " " , " get_replicator " ) ;
2018-03-03 17:28:49 +00:00
2021-09-07 21:35:19 +00:00
ADD_SIGNAL ( MethodInfo ( " peer_connected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " peer_disconnected " , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " peer_packet " , PropertyInfo ( Variant : : INT , " id " ) , PropertyInfo ( Variant : : PACKED_BYTE_ARRAY , " packet " ) ) ) ;
2018-03-03 17:28:49 +00:00
ADD_SIGNAL ( MethodInfo ( " connected_to_server " ) ) ;
ADD_SIGNAL ( MethodInfo ( " connection_failed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " server_disconnected " ) ) ;
}
2020-05-12 15:01:17 +00:00
MultiplayerAPI : : MultiplayerAPI ( ) {
2021-08-09 20:46:23 +00:00
replicator = memnew ( MultiplayerReplicator ( this ) ) ;
2021-09-03 17:40:47 +00:00
rpc_manager = memnew ( RPCManager ( this ) ) ;
2018-03-03 17:28:49 +00:00
clear ( ) ;
}
MultiplayerAPI : : ~ MultiplayerAPI ( ) {
clear ( ) ;
2021-08-09 20:46:23 +00:00
memdelete ( replicator ) ;
2021-09-03 17:40:47 +00:00
memdelete ( rpc_manager ) ;
2018-03-03 17:28:49 +00:00
}