2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*************************************************************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*  multiplayer_replicator.cpp                                           */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************************************************************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*                       This file is part of:                           */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*                           GODOT ENGINE                                */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*                      https://godotengine.org                          */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************************************************************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*                                                                       */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* 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.                */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************************************************************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "core/io/multiplayer_replicator.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "core/io/marshalls.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "scene/main/node.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "scene/resources/packed_scene.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define MAKE_ROOM(m_amount)             \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( packet_cache . size ( )  <  m_amount )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										packet_cache . resize ( m_amount ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _sync_all_default ( const  ResourceUID : : ID  & p_scene_id ,  int  p_peer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  full_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  same_size  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  last_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  all_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  EncodeInfo  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  raw  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										List < Variant >  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Map < ObjectID ,  struct  EncodeInfo >  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tracked_objects . has ( p_scene_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( const  ObjectID  & obj_id  :  tracked_objects [ p_scene_id ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Object  * obj  =  ObjectDB : : get_instance ( obj_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( obj )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  EncodeInfo  info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												Error  err  =  _get_state ( cfg . sync_properties ,  obj ,  info . state ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ERR_CONTINUE ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												err  =  _encode_state ( info . state ,  nullptr ,  info . size ,  & info . raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ERR_CONTINUE ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												state [ obj_id ]  =  info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												full_size  + =  info . size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( last_size  & &  info . size  ! =  last_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													same_size  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												all_raw  =  all_raw  & &  info . raw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												last_size  =  info . size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Default implementation do not send empty updates.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! full_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef DEBUG_ENABLED 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( full_size  >  4096  & &  cfg . sync_interval )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										WARN_PRINT_ONCE ( vformat ( " The timed state update for scene %d is big (%d bytes) consider optimizing it " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( same_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This is fast and small. Should we allow more than 256 objects per type?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This costs us 1 byte.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										MAKE_ROOM ( SYNC_CMD_OFFSET  +  1  +  2  +  2  +  full_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										MAKE_ROOM ( SYNC_CMD_OFFSET  +  1  +  2  +  state . size ( )  *  2  +  full_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ofs  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8_t  * ptr  =  packet_cache . ptrw ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptr [ 0 ]  =  MultiplayerAPI : : NETWORK_COMMAND_SYNC  +  ( ( same_size  ?  1  :  0 )  < <  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_uint64 ( p_scene_id ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptr [ ofs ]  =  cfg . sync_recv + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_uint16 ( state . size ( ) ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( same_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ofs  + =  encode_uint16 ( last_size  +  ( all_raw  ?  1  < <  15  :  0 ) ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  ObjectID  & obj_id  :  tracked_objects [ p_scene_id ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! state . has ( obj_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  EncodeInfo  & info  =  state [ obj_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object  * obj  =  ObjectDB : : get_instance ( obj_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( ! obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! same_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// We need to encode the size of every object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ofs  + =  encode_uint16 ( info . size  +  ( info . raw  ?  1  < <  15  :  0 ) ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Error  err  =  _encode_state ( info . state ,  & ptr [ ofs ] ,  size ,  & info . raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ofs  + =  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Ref < MultiplayerPeer >  network_peer  =  multiplayer - > get_network_peer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_target_peer ( p_peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_channel ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_mode ( MultiplayerPeer : : TRANSFER_MODE_UNRELIABLE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  network_peer - > put_packet ( ptr ,  ofs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : _process_default_sync ( const  ResourceUID : : ID  & p_id ,  const  uint8_t  * p_packet ,  int  p_packet_len )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( p_packet_len  <  SYNC_CMD_OFFSET  +  5 ,  " Invalid spawn packet received " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( ! replications . has ( p_id ) ,  " Invalid spawn ID received  "  +  itos ( p_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SceneConfig  & cfg  =  replications [ p_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( cfg . mode  ! =  REPLICATION_MODE_SERVER  | |  multiplayer - > is_network_server ( ) ,  " The defualt implementation only allows sync packets from the server " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  bool  same_size  =  ( ( p_packet [ 0 ]  &  64 )  > >  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT )  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ofs  =  SYNC_CMD_OFFSET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  time  =  p_packet [ ofs ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Skip old update.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( time  <  cfg . sync_recv  & &  cfg . sync_recv  -  time  <  127 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg . sync_recv  =  time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  count  =  decode_uint16 ( & p_packet [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef DEBUG_ENABLED 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! tracked_objects . has ( p_id )  | |  tracked_objects [ p_id ] . size ( )  ! =  count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tracked_objects . has ( p_id )  | |  tracked_objects [ p_id ] . size ( )  ! =  count )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  data_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  raw  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( same_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// This is fast and optimized.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data_size  =  decode_uint16 ( & p_packet [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										raw  =  ( data_size  &  ( 1  < <  15 ) )  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data_size  =  data_size  &  ~ ( 1  < <  15 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ofs  + =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND ( p_packet_len  -  ofs  <  data_size  *  count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  ObjectID  & obj_id  :  tracked_objects [ p_id ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object  * obj  =  ObjectDB : : get_instance ( obj_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( ! obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! same_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// This is slow and wasteful.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											data_size  =  decode_uint16 ( & p_packet [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											raw  =  ( data_size  &  ( 1  < <  15 ) )  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											data_size  =  data_size  &  ~ ( 1  < <  15 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ofs  + =  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND ( p_packet_len  -  ofs  <  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Error  err  =  _decode_state ( cfg . sync_properties ,  obj ,  & p_packet [ ofs ] ,  data_size ,  size ,  raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ofs  + =  data_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( size  ! =  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _send_default_spawn_despawn ( int  p_peer_id ,  const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj ,  const  NodePath  & p_path ,  bool  p_spawn )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( p_spawn  & &  ! p_obj ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Error  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Prepare state
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									List < Variant >  state_variants ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  state_len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_spawn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( err  =  _get_state ( cfg . properties ,  p_obj ,  state_variants ) )  ! =  OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									bool  is_raw  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( state_variants . size ( )  = =  1  & &  state_variants [ 0 ] . get_type ( )  = =  Variant : : PACKED_BYTE_ARRAY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										is_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( state_variants . size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  =  _encode_state ( state_variants ,  nullptr ,  state_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V ( err ,  err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										is_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ofs  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Prepare simplified path
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  Node  * root_node  =  multiplayer - > get_root_node ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! root_node ,  ERR_UNCONFIGURED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									NodePath  rel_path  =  ( root_node - > get_path ( ) ) . rel_path_to ( p_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  Vector < StringName >  names  =  rel_path . get_names ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( names . size ( )  <  2 ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									NodePath  parent  =  NodePath ( names . subarray ( 0 ,  names . size ( )  -  2 ) ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! root_node - > has_node ( parent ) ,  ERR_INVALID_PARAMETER ,  " Path not found:  "  +  parent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  path_id  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									multiplayer - > send_confirm_path ( root_node - > get_node ( parent ) ,  parent ,  p_peer_id ,  path_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Encode name and parent ID.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CharString  cname  =  String ( names [ names . size ( )  -  1 ] ) . utf8 ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  nlen  =  encode_cstring ( cname . get_data ( ) ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MAKE_ROOM ( SPAWN_CMD_OFFSET  +  4  +  4  +  nlen  +  state_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8_t  * ptr  =  packet_cache . ptrw ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptr [ 0 ]  =  ( p_spawn  ?  MultiplayerAPI : : NETWORK_COMMAND_SPAWN  :  MultiplayerAPI : : NETWORK_COMMAND_DESPAWN )  +  ( ( is_raw  ?  1  :  0 )  < <  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_uint64 ( p_scene_id ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_uint32 ( path_id ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_uint32 ( nlen ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  encode_cstring ( cname . get_data ( ) ,  & ptr [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Encode state.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! is_raw )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_encode_state ( state_variants ,  & ptr [ ofs ] ,  state_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( state_len )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PackedByteArray  pba  =  state_variants [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( & ptr [ ofs ] ,  pba . ptr ( ) ,  state_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Ref < MultiplayerPeer >  network_peer  =  multiplayer - > get_network_peer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_target_peer ( p_peer_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_channel ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_mode ( MultiplayerPeer : : TRANSFER_MODE_RELIABLE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  network_peer - > put_packet ( ptr ,  ofs  +  state_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : _process_default_spawn_despawn ( int  p_from ,  const  ResourceUID : : ID  & p_scene_id ,  const  uint8_t  * p_packet ,  int  p_packet_len ,  bool  p_spawn )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( p_packet_len  <  SPAWN_CMD_OFFSET  +  9 ,  " Invalid spawn packet received " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ofs  =  SPAWN_CMD_OFFSET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32_t  node_target  =  decode_uint32 ( & p_packet [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Node  * parent  =  multiplayer - > get_cached_node ( p_from ,  node_target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( parent  = =  nullptr ,  " Invalid packet received. Requested node was not found. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32_t  name_len  =  decode_uint32 ( & p_packet [ ofs ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( name_len  >  uint32_t ( p_packet_len  -  ofs ) ,  vformat ( " Invalid spawn packet size: %d, wants: %d " ,  p_packet_len ,  ofs  +  name_len ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( name_len  <  1 ,  " Zero spawn name size. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  String  name  =  String : : utf8 ( ( const  char  * ) & p_packet [ ofs ] ,  name_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// We need to make sure no trickery happens here (e.g. despawning a subpath), but we want to allow autogenerated ("@") node names.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( name . validate_node_name ( )  ! =  name . replace ( " @ " ,  " " ) ,  vformat ( " Invalid node name received: '%s' " ,  name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ofs  + =  name_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . mode  = =  REPLICATION_MODE_SERVER  & &  p_from  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										String  scene_path  =  ResourceUID : : get_singleton ( ) - > get_id_path ( p_scene_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( p_spawn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  bool  is_raw  =  ( ( p_packet [ 0 ]  &  64 )  > >  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT )  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND_MSG ( parent - > has_node ( name ) ,  vformat ( " Unable to spawn node. Node already exists: %s/%s " ,  parent - > get_path ( ) ,  name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											RES  res  =  ResourceLoader : : load ( scene_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND_MSG ( ! res . is_valid ( ) ,  " Unable to load scene to spawn at path:  "  +  scene_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PackedScene  * scene  =  Object : : cast_to < PackedScene > ( res . ptr ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND ( ! scene ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Node  * node  =  scene - > instantiate ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND ( ! node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											replicated_nodes [ node - > get_instance_id ( ) ]  =  p_scene_id ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											_track ( p_scene_id ,  node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											int  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											_decode_state ( cfg . properties ,  node ,  & p_packet [ ofs ] ,  p_packet_len  -  ofs ,  size ,  is_raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											parent - > _add_child_nocheck ( node ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emit_signal ( SNAME ( " spawned " ) ,  p_scene_id ,  node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND_MSG ( ! parent - > has_node ( name ) ,  vformat ( " Path not found: %s/%s " ,  parent - > get_path ( ) ,  name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Node  * node  =  parent - > get_node ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND_MSG ( ! replicated_nodes . has ( node - > get_instance_id ( ) ) ,  vformat ( " Trying to despawn a Node that was not replicated: %s/%s " ,  parent - > get_path ( ) ,  name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emit_signal ( SNAME ( " despawned " ) ,  p_scene_id ,  node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											_untrack ( p_scene_id ,  node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											replicated_nodes . erase ( node - > get_instance_id ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											node - > queue_delete ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PackedByteArray  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( p_packet_len  >  ofs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											data . resize ( p_packet_len  -  ofs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memcpy ( data . ptrw ( ) ,  & p_packet [ ofs ] ,  data . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( p_spawn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emit_signal ( SNAME ( " spawn_requested " ) ,  p_from ,  p_scene_id ,  parent ,  name ,  data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											emit_signal ( SNAME ( " despawn_requested " ) ,  p_from ,  p_scene_id ,  parent ,  name ,  data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : process_spawn_despawn ( int  p_from ,  const  uint8_t  * p_packet ,  int  p_packet_len ,  bool  p_spawn )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( p_packet_len  <  SPAWN_CMD_OFFSET ,  " Invalid spawn packet received " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ResourceUID : : ID  id  =  decode_uint64 ( & p_packet [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( ! replications . has ( id ) ,  " Invalid spawn ID received  "  +  itos ( id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_spawn_despawn_receive . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  ofs  =  SPAWN_CMD_OFFSET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  is_raw  =  ( ( p_packet [ 0 ]  &  64 )  > >  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT )  = =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  left  =  p_packet_len  -  ofs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( is_raw  & &  left )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PackedByteArray  pba ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pba . resize ( left ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memcpy ( pba . ptrw ( ) ,  & p_packet [ ofs ] ,  pba . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											data  =  pba ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  if  ( left )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ERR_FAIL_COND ( decode_variant ( data ,  & p_packet [ ofs ] ,  left )  ! =  OK ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  args [ 4 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 0 ]  =  p_from ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 1 ]  =  id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 2 ]  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 3 ]  =  p_spawn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  Variant  * argp [ ]  =  {  & args [ 0 ] ,  & args [ 1 ] ,  & args [ 2 ] ,  & args [ 3 ]  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Callable : : CallError  ce ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_spawn_despawn_receive . call ( argp ,  4 ,  ret ,  ce ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_MSG ( ce . error  ! =  Callable : : CallError : : CALL_OK ,  " Custom receive function failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_process_default_spawn_despawn ( p_from ,  id ,  p_packet ,  p_packet_len ,  p_spawn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : process_sync ( int  p_from ,  const  uint8_t  * p_packet ,  int  p_packet_len )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( p_packet_len  <  SPAWN_CMD_OFFSET ,  " Invalid spawn packet received " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ResourceUID : : ID  id  =  decode_uint64 ( & p_packet [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( ! replications . has ( id ) ,  " Invalid spawn ID received  "  +  itos ( id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_sync_receive . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Array  objs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tracked_objects . has ( id ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 13:35:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											objs . resize ( tracked_objects [ id ] . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  idx  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											for  ( const  ObjectID  & obj_id  :  tracked_objects [ id ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 13:35:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												objs [ idx + + ]  =  ObjectDB : : get_instance ( obj_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PackedByteArray  pba ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pba . resize ( p_packet_len  -  SPAWN_CMD_OFFSET ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( pba . size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											memcpy ( pba . ptrw ( ) ,  p_packet ,  p_packet_len  -  SPAWN_CMD_OFFSET ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  args [ 4 ]  =  {  p_from ,  id ,  objs ,  pba  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  * argp [ 4 ]  =  {  args ,  & args [ 1 ] ,  & args [ 2 ] ,  & args [ 3 ]  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Callable : : CallError  ce ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_sync_receive . call ( ( const  Variant  * * ) argp ,  4 ,  ret ,  ce ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_MSG ( ce . error  ! =  Callable : : CallError : : CALL_OK ,  " Custom sync function failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_MSG ( p_from  ! =  1 ,  " Default sync implementation only allow syncing from server to client " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_process_default_sync ( id ,  p_packet ,  p_packet_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _get_state ( const  List < StringName >  & p_properties ,  const  Object  * p_obj ,  List < Variant >  & r_variant )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! p_obj ,  ERR_INVALID_PARAMETER ,  " Cannot encode null object " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  StringName  & prop  :  p_properties )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bool  valid  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  Variant  v  =  p_obj - > get ( prop ,  & valid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( ! valid ,  ERR_INVALID_DATA ,  vformat ( " Property '%s' not found. " ,  prop ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r_variant . push_back ( v ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _encode_state ( const  List < Variant >  & p_variants ,  uint8_t  * p_buffer ,  int  & r_len ,  bool  * r_raw )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r_len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Try raw encoding optimization.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( r_raw  & &  p_variants . size ( )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* r_raw  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  Variant  v  =  p_variants [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( v . get_type ( )  = =  Variant : : PACKED_BYTE_ARRAY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* r_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  PackedByteArray  pba  =  v ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( p_buffer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												memcpy ( p_buffer ,  pba . ptr ( ) ,  pba . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											r_len  + =  pba . size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											multiplayer - > encode_and_compress_variant ( v ,  p_buffer ,  size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											r_len  + =  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Regular encoding.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  Variant  & v  :  p_variants )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										multiplayer - > encode_and_compress_variant ( v ,  p_buffer  ?  p_buffer  +  r_len  :  nullptr ,  size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r_len  + =  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _decode_state ( const  List < StringName >  & p_properties ,  Object  * p_obj ,  const  uint8_t  * p_buffer ,  int  p_len ,  int  & r_len ,  bool  p_raw )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r_len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  argc  =  p_properties . size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( argc  = =  0  & &  p_raw )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( p_len  ! =  0 ,  ERR_INVALID_DATA ,  " Buffer has trailing bytes. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( p_raw  & &  argc  ! =  1 ,  ERR_INVALID_DATA ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_raw )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r_len  =  p_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PackedByteArray  pba ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pba . resize ( p_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( pba . ptrw ( ) ,  p_buffer ,  p_len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p_obj - > set ( p_properties [ 0 ] ,  pba ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Vector < Variant >  args ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Vector < const  Variant  * >  argp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args . resize ( argc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( int  i  =  0 ;  i  <  argc ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( r_len  > =  p_len ,  ERR_INVALID_DATA ,  " Invalid packet received. Size too small. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  vlen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Error  err  =  multiplayer - > decode_and_decompress_variant ( args . write [ i ] ,  & p_buffer [ r_len ] ,  p_len  -  r_len ,  & vlen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( err  ! =  OK ,  err ,  " Invalid packet received. Unable to decode state variable. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										r_len  + =  vlen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( p_len  -  r_len  ! =  0 ,  ERR_INVALID_DATA ,  " Buffer has trailing bytes. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  StringName  & prop  :  p_properties )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p_obj - > set ( prop ,  args [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : spawn_config ( const  ResourceUID : : ID  & p_id ,  ReplicationMode  p_mode ,  const  TypedArray < StringName >  & p_props ,  const  Callable  & p_on_send ,  const  Callable  & p_on_recv )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( p_mode  <  REPLICATION_MODE_NONE  | |  p_mode  >  REPLICATION_MODE_CUSTOM ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! ResourceUID : : get_singleton ( ) - > has_id ( p_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( p_on_send . is_valid ( )  ! =  p_on_recv . is_valid ( ) ,  ERR_INVALID_PARAMETER ,  " Send and receive custom callables must be both valid or both empty " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef TOOLS_ENABLED 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! p_on_send . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// We allow non scene spawning with custom callables.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										String  path  =  ResourceUID : : get_singleton ( ) - > get_id_path ( p_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RES  res  =  ResourceLoader : : load ( path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V ( ! res - > is_class ( " PackedScene " ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_mode  = =  REPLICATION_MODE_NONE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( replications . has ( p_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											replications . erase ( p_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SceneConfig  cfg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . mode  =  p_mode ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  ( int  i  =  0 ;  i  <  p_props . size ( ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cfg . properties . push_back ( StringName ( p_props [ i ] ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_spawn_despawn_send  =  p_on_send ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_spawn_despawn_receive  =  p_on_recv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										replications [ p_id ]  =  cfg ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : sync_config ( const  ResourceUID : : ID  & p_id ,  uint64_t  p_interval ,  const  TypedArray < StringName >  & p_props ,  const  Callable  & p_on_send ,  const  Callable  & p_on_recv )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! ResourceUID : : get_singleton ( ) - > has_id ( p_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( p_on_send . is_valid ( )  ! =  p_on_recv . is_valid ( ) ,  ERR_INVALID_PARAMETER ,  " Send and receive custom callables must be both valid or both empty " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! replications . has ( p_id ) ,  ERR_UNCONFIGURED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SceneConfig  & cfg  =  replications [ p_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( p_interval  & &  cfg . mode  ! =  REPLICATION_MODE_SERVER  & &  ! p_on_send . is_valid ( ) ,  ERR_INVALID_PARAMETER ,  " Timed updates in custom mode are only allowed if custom callbacks are also specified " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( int  i  =  0 ;  i  <  p_props . size ( ) ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . sync_properties . push_back ( p_props [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg . on_sync_send  =  p_on_send ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg . on_sync_receive  =  p_on_recv ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cfg . sync_interval  =  p_interval  *  1000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _send_spawn_despawn ( int  p_peer_id ,  const  ResourceUID : : ID  & p_scene_id ,  const  Variant  & p_data ,  bool  p_spawn )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  data_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  is_raw  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_data . get_type ( )  = =  Variant : : PACKED_BYTE_ARRAY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  PackedByteArray  pba  =  p_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										is_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data_size  =  p_data . operator  PackedByteArray ( ) . size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( p_data . get_type ( )  = =  Variant : : NIL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										is_raw  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Error  err  =  encode_variant ( p_data ,  nullptr ,  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V ( err ,  err ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MAKE_ROOM ( SPAWN_CMD_OFFSET  +  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8_t  * ptr  =  packet_cache . ptrw ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptr [ 0 ]  =  ( p_spawn  ?  MultiplayerAPI : : NETWORK_COMMAND_SPAWN  :  MultiplayerAPI : : NETWORK_COMMAND_DESPAWN )  +  ( ( is_raw  ?  1  :  0 )  < <  MultiplayerAPI : : BYTE_ONLY_OR_NO_ARGS_SHIFT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									encode_uint64 ( p_scene_id ,  & ptr [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_data . get_type ( )  = =  Variant : : PACKED_BYTE_ARRAY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  PackedByteArray  pba  =  p_data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( & ptr [ SPAWN_CMD_OFFSET ] ,  pba . ptr ( ) ,  pba . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( data_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										encode_variant ( p_data ,  & ptr [ SPAWN_CMD_OFFSET ] ,  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Ref < MultiplayerPeer >  network_peer  =  multiplayer - > get_network_peer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_target_peer ( p_peer_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_channel ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_mode ( MultiplayerPeer : : TRANSFER_MODE_RELIABLE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  network_peer - > put_packet ( ptr ,  SPAWN_CMD_OFFSET  +  data_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : send_despawn ( int  p_peer_id ,  const  ResourceUID : : ID  & p_scene_id ,  const  Variant  & p_data ,  const  NodePath  & p_path )  {  
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! multiplayer - > has_network_peer ( ) ,  ERR_UNCONFIGURED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ,  vformat ( " Spawnable not found: %d " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_spawn_despawn_send . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _send_spawn_despawn ( p_peer_id ,  p_scene_id ,  p_data ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( cfg . mode  = =  REPLICATION_MODE_SERVER  & &  multiplayer - > is_network_server ( ) ,  ERR_UNAVAILABLE ,  " Manual despawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										NodePath  path  =  p_path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object  * obj  =  p_data . get_type ( )  = =  Variant : : OBJECT  ?  p_data . get_validated_object ( )  :  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( path . is_empty ( )  & &  obj )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Node  * node  =  Object : : cast_to < Node > ( obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( node  & &  node - > is_inside_tree ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												path  =  node - > get_path ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( path . is_empty ( ) ,  ERR_INVALID_PARAMETER ,  " Despawn default implementation requires a despawn path, or the data to be a node inside the SceneTree " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _send_default_spawn_despawn ( p_peer_id ,  p_scene_id ,  obj ,  path ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : send_spawn ( int  p_peer_id ,  const  ResourceUID : : ID  & p_scene_id ,  const  Variant  & p_data ,  const  NodePath  & p_path )  {  
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! multiplayer - > has_network_peer ( ) ,  ERR_UNCONFIGURED ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ,  vformat ( " Spawnable not found: %d " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_spawn_despawn_send . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _send_spawn_despawn ( p_peer_id ,  p_scene_id ,  p_data ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( cfg . mode  = =  REPLICATION_MODE_SERVER  & &  multiplayer - > is_network_server ( ) ,  ERR_UNAVAILABLE ,  " Manual spawn is restricted in default server mode implementation. Use custom mode if you desire control over server spawn requests. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										NodePath  path  =  p_path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object  * obj  =  p_data . get_type ( )  = =  Variant : : OBJECT  ?  p_data . get_validated_object ( )  :  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( ! obj ,  ERR_INVALID_PARAMETER ,  " Spawn default implementation requires the data to be an object. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( path . is_empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											Node  * node  =  Object : : cast_to < Node > ( obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( node  & &  node - > is_inside_tree ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												path  =  node - > get_path ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( path . is_empty ( ) ,  ERR_INVALID_PARAMETER ,  " Spawn default implementation requires a spawn path, or the data to be a node inside the SceneTree " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _send_default_spawn_despawn ( p_peer_id ,  p_scene_id ,  obj ,  path ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : _spawn_despawn ( ResourceUID : : ID  p_scene_id ,  Object  * p_obj ,  int  p_peer ,  bool  p_spawn )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ,  vformat ( " Spawnable not found: %d " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_spawn_despawn_send . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  args [ 4 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 0 ]  =  p_peer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 1 ]  =  p_scene_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 2 ]  =  p_obj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args [ 3 ]  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										const  Variant  * argp [ ]  =  {  & args [ 0 ] ,  & args [ 1 ] ,  & args [ 2 ] ,  & args [ 3 ]  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Callable : : CallError  ce ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_spawn_despawn_send . call ( argp ,  4 ,  ret ,  ce ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( ce . error  ! =  Callable : : CallError : : CALL_OK ,  FAILED ,  " Custom send function failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Node  * node  =  Object : : cast_to < Node > ( p_obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( ! p_obj ,  ERR_INVALID_PARAMETER ,  " Only nodes can be replicated by the default implementation " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _send_default_spawn_despawn ( p_peer ,  p_scene_id ,  node ,  node - > get_path ( ) ,  p_spawn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : spawn ( ResourceUID : : ID  p_scene_id ,  Object  * p_obj ,  int  p_peer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  _spawn_despawn ( p_scene_id ,  p_obj ,  p_peer ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : despawn ( ResourceUID : : ID  p_scene_id ,  Object  * p_obj ,  int  p_peer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  _spawn_despawn ( p_scene_id ,  p_obj ,  p_peer ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								PackedByteArray  MultiplayerReplicator : : encode_state ( const  ResourceUID : : ID  & p_scene_id ,  const  Object  * p_obj ,  bool  p_initial )  {  
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									PackedByteArray  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! replications . has ( p_scene_id ) ,  state ,  vformat ( " Spawnable not found: %d " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									List < Variant >  state_vars ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  List < StringName >  props  =  p_initial  ?  cfg . properties  :  cfg . sync_properties ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Error  err  =  _get_state ( props ,  p_obj ,  state_vars ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( err  ! =  OK ,  state ,  " Unable to retrieve object state. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  =  _encode_state ( state_vars ,  nullptr ,  len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( err  ! =  OK ,  state ,  " Unable to encode object state. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									state . resize ( len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_encode_state ( state_vars ,  state . ptrw ( ) ,  len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  state ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : decode_state ( const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj ,  const  PackedByteArray  p_data ,  bool  p_initial )  {  
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ,  vformat ( " Spawnable not found: %d " ,  p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  List < StringName >  props  =  p_initial  ?  cfg . properties  :  cfg . sync_properties ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									int  size ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  _decode_state ( props ,  p_obj ,  p_data . ptr ( ) ,  p_data . size ( ) ,  size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : scene_enter_exit_notify ( const  String  & p_scene ,  Node  * p_node ,  bool  p_enter )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! multiplayer - > has_network_peer ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Node  * root_node  =  multiplayer - > get_root_node ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! p_node  | |  ! p_node - > get_parent ( )  | |  ! root_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									NodePath  path  =  ( root_node - > get_path ( ) ) . rel_path_to ( p_node - > get_parent ( ) - > get_path ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( path . is_empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ResourceUID : : ID  id  =  ResourceLoader : : get_resource_uid ( p_scene ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! replications . has ( id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_enter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cfg . mode  = =  REPLICATION_MODE_SERVER  & &  multiplayer - > is_network_server ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											replicated_nodes [ p_node - > get_instance_id ( ) ]  =  id ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											_track ( id ,  p_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											spawn ( id ,  p_node ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emit_signal ( SNAME ( " replicated_instance_added " ) ,  id ,  p_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( cfg . mode  = =  REPLICATION_MODE_SERVER  & &  multiplayer - > is_network_server ( )  & &  replicated_nodes . has ( p_node - > get_instance_id ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											replicated_nodes . erase ( p_node - > get_instance_id ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											_untrack ( id ,  p_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											despawn ( id ,  p_node ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										emit_signal ( SNAME ( " replicated_instance_removed " ) ,  id ,  p_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : spawn_all ( int  p_peer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( const  KeyValue < ObjectID ,  ResourceUID : : ID >  & E  :  replicated_nodes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Only server mode adds to replicated_nodes, no need to check it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Object  * obj  =  ObjectDB : : get_instance ( E . key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( ! obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Node  * node  =  Object : : cast_to < Node > ( obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_CONTINUE ( ! node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spawn ( E . value ,  node ,  p_peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : poll ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( KeyValue < ResourceUID : : ID ,  SceneConfig >  & E  :  replications )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! E . value . sync_interval )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( E . value . mode  = =  REPLICATION_MODE_SERVER  & &  ! multiplayer - > is_network_server ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uint64_t  time  =  OS : : get_singleton ( ) - > get_ticks_usec ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( E . value . sync_last  +  E . value . sync_interval  < =  time )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sync_all ( E . key ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											E . value . sync_last  =  time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Handle wrapping.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( E . value . sync_last  >  time )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											E . value . sync_last  =  time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : track ( const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! replications . has ( p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( cfg . mode  = =  REPLICATION_MODE_SERVER ,  " Manual object tracking is not allowed in server mode. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_track ( p_scene_id ,  p_obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : _track ( const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! p_obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! replications . has ( p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tracked_objects . has ( p_scene_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tracked_objects [ p_scene_id ]  =  List < ObjectID > ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tracked_objects [ p_scene_id ] . push_back ( p_obj - > get_instance_id ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : untrack ( const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! replications . has ( p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_MSG ( cfg . mode  = =  REPLICATION_MODE_SERVER ,  " Manual object tracking is not allowed in server mode. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_untrack ( p_scene_id ,  p_obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : _untrack ( const  ResourceUID : : ID  & p_scene_id ,  Object  * p_obj )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! p_obj ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND ( ! replications . has ( p_scene_id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tracked_objects . has ( p_scene_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tracked_objects [ p_scene_id ] . erase ( p_obj - > get_instance_id ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : sync_all ( const  ResourceUID : : ID  & p_scene_id ,  int  p_peer )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tracked_objects . has ( p_scene_id ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cfg . on_sync_send . is_valid ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Array  objs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tracked_objects . has ( p_scene_id ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 13:35:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											objs . resize ( tracked_objects [ p_scene_id ] . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  idx  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											for  ( const  ObjectID  & obj_id  :  tracked_objects [ p_scene_id ] )  { 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-26 13:35:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												objs [ idx + + ]  =  ObjectDB : : get_instance ( obj_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  args [ 3 ]  =  {  p_scene_id ,  objs ,  p_peer  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  * argp [ 3 ]  =  {  args ,  & args [ 1 ] ,  & args [ 2 ]  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Callable : : CallError  ce ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Variant  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cfg . on_sync_send . call ( ( const  Variant  * * ) argp ,  3 ,  ret ,  ce ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ERR_FAIL_COND_V_MSG ( ce . error  ! =  Callable : : CallError : : CALL_OK ,  FAILED ,  " Custom sync function failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( cfg . sync_properties . size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  _sync_all_default ( p_scene_id ,  p_peer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Error  MultiplayerReplicator : : send_sync ( int  p_peer_id ,  const  ResourceUID : : ID  & p_scene_id ,  PackedByteArray  p_data ,  MultiplayerPeer : : TransferMode  p_transfer_mode ,  int  p_channel )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! multiplayer - > has_network_peer ( ) ,  ERR_UNCONFIGURED ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V ( ! replications . has ( p_scene_id ) ,  ERR_INVALID_PARAMETER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  SceneConfig  & cfg  =  replications [ p_scene_id ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ERR_FAIL_COND_V_MSG ( ! cfg . on_sync_send . is_valid ( ) ,  ERR_UNCONFIGURED ,  " Sending raw sync messages is only available with custom functions " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									MAKE_ROOM ( SYNC_CMD_OFFSET  +  p_data . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint8_t  * ptr  =  packet_cache . ptrw ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ptr [ 0 ]  =  MultiplayerAPI : : NETWORK_COMMAND_SYNC ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									encode_uint64 ( p_scene_id ,  & ptr [ 1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Ref < MultiplayerPeer >  network_peer  =  multiplayer - > get_network_peer ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_target_peer ( p_peer_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_channel ( p_channel ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									network_peer - > set_transfer_mode ( p_transfer_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  network_peer - > put_packet ( ptr ,  SYNC_CMD_OFFSET  +  p_data . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : clear ( )  {  
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tracked_objects . clear ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									replicated_nodes . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  MultiplayerReplicator : : _bind_methods ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " spawn_config " ,  " scene_id " ,  " spawn_mode " ,  " properties " ,  " custom_send " ,  " custom_receive " ) ,  & MultiplayerReplicator : : spawn_config ,  DEFVAL ( TypedArray < StringName > ( ) ) ,  DEFVAL ( Callable ( ) ) ,  DEFVAL ( Callable ( ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " sync_config " ,  " scene_id " ,  " interval " ,  " properties " ,  " custom_send " ,  " custom_receive " ) ,  & MultiplayerReplicator : : sync_config ,  DEFVAL ( TypedArray < StringName > ( ) ) ,  DEFVAL ( Callable ( ) ) ,  DEFVAL ( Callable ( ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " despawn " ,  " scene_id " ,  " object " ,  " peer_id " ) ,  & MultiplayerReplicator : : despawn ,  DEFVAL ( 0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " spawn " ,  " scene_id " ,  " object " ,  " peer_id " ) ,  & MultiplayerReplicator : : spawn ,  DEFVAL ( 0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " send_despawn " ,  " peer_id " ,  " scene_id " ,  " data " ,  " path " ) ,  & MultiplayerReplicator : : send_despawn ,  DEFVAL ( Variant ( ) ) ,  DEFVAL ( NodePath ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " send_spawn " ,  " peer_id " ,  " scene_id " ,  " data " ,  " path " ) ,  & MultiplayerReplicator : : send_spawn ,  DEFVAL ( Variant ( ) ) ,  DEFVAL ( NodePath ( ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-12 21:07:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " send_sync " ,  " peer_id " ,  " scene_id " ,  " data " ,  " transfer_mode " ,  " channel " ) ,  & MultiplayerReplicator : : send_sync ,  DEFVAL ( MultiplayerPeer : : TRANSFER_MODE_RELIABLE ) ,  DEFVAL ( 0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " sync_all " ,  " scene_id " ,  " peer_id " ) ,  & MultiplayerReplicator : : sync_all ,  DEFVAL ( 0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " track " ,  " scene_id " ,  " object " ) ,  & MultiplayerReplicator : : track ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " untrack " ,  " scene_id " ,  " object " ) ,  & MultiplayerReplicator : : untrack ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " encode_state " ,  " scene_id " ,  " object " ,  " initial " ) ,  & MultiplayerReplicator : : encode_state ,  DEFVAL ( true ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ClassDB : : bind_method ( D_METHOD ( " decode_state " ,  " scene_id " ,  " object " ,  " data " ,  " initial " ) ,  & MultiplayerReplicator : : decode_state ,  DEFVAL ( true ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-09 22:46:23 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " despawned " ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " node " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " spawned " ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " node " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " despawn_requested " ,  PropertyInfo ( Variant : : INT ,  " id " ) ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " parent " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ,  PropertyInfo ( Variant : : STRING ,  " name " ) ,  PropertyInfo ( Variant : : PACKED_BYTE_ARRAY ,  " data " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " spawn_requested " ,  PropertyInfo ( Variant : : INT ,  " id " ) ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " parent " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ,  PropertyInfo ( Variant : : STRING ,  " name " ) ,  PropertyInfo ( Variant : : PACKED_BYTE_ARRAY ,  " data " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " replicated_instance_added " ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " node " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ADD_SIGNAL ( MethodInfo ( " replicated_instance_removed " ,  PropertyInfo ( Variant : : INT ,  " scene_id " ) ,  PropertyInfo ( Variant : : OBJECT ,  " node " ,  PROPERTY_HINT_RESOURCE_TYPE ,  " Node " ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BIND_ENUM_CONSTANT ( REPLICATION_MODE_NONE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BIND_ENUM_CONSTANT ( REPLICATION_MODE_SERVER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BIND_ENUM_CONSTANT ( REPLICATION_MODE_CUSTOM ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}