using LobbyRelaySample ;
using System ;
using System.Collections ;
using System.Collections.Generic ;
using Unity.Services.Relay ;
using Unity.Services.Relay.Allocations ;
using Unity.Services.Relay.Models ;
using UnityEngine ;
protected NativeList < NetworkConnection > m_connections ;
protected NetworkEndPoint m_endpointForServer ;
protected JobHandle m_currentUpdateHandle ;
protected LocalLobby m_localLobby ;
protected Action < bool , string > m_onJoinComplete ;
protected enum MsgType { NewPlayer = 0 , PingPong = 1 , ReadyState = 2 , PlayerName = 3 , Emote = 4 } // We only use 3 bits for this.
public void BeginRelayJoin ( LocalLobby localLobby ) //, Action<bool, string> onJoinComplete)
{
m_localLobby = localLobby ;
// m_onJoinComplete = onJoinComplete;
JoinRelay ( ) ;
}
protected abstract void JoinRelay ( ) ;
protected void BindToAllocation ( string ip , int port , byte [ ] allocationIdBytes , byte [ ] connectionDataBytes , byte [ ] hostConnectionDataBytes , byte [ ] hmacKeyBytes , int connectionCapacity )
{
public class RelayUtpSetup_Host : RelayUTPSetup
{
private LocalLobby m_localLobby ;
public void DoRelaySetup ( LocalLobby localLobby )
protected override void JoinRelay ( )
m_localLobby = localLobby ;
public void OnAllocation ( Allocation allocation )
private void OnAllocation ( Allocation allocation )
BindToAllocation ( allocation ) ;
BindToAllocation ( allocation . RelayServer . IpV4 , allocation . RelayServer . Port , allocation . AllocationIdBytes , allocation . ConnectionData , allocation . ConnectionData , allocation . Key , 1 6 ) ;
public void OnRelayCode ( string relayCode )
private void OnRelayCode ( string relayCode )
{
m_localLobby . RelayCode = relayCode ;
RelayInterface . JoinAsync ( m_localLobby . RelayCode , OnJoin ) ;
{
m_localLobby . RelayServer = new ServerAddress ( joinAllocation . RelayServer . IpV4 , joinAllocation . RelayServer . Port ) ;
}
private void BindToAllocation ( Allocation allocation )
{
BindToAllocation ( allocation . RelayServer . IpV4 , allocation . RelayServer . Port , allocation . AllocationIdBytes , allocation . ConnectionData , allocation . ConnectionData , allocation . Key , 1 6 ) ;
}
protected override void OnBindingComplete ( )
}
}
private struct PongJob : Unity . Jobs . IJobParallelForDefer
private struct PongJob : IJobParallelForDefer
{
public NetworkDriver . Concurrent driver ;
public NativeArray < NetworkConnection > connections ;
// Pop all events for the connection
while ( ( cmd = driver . PopEventForConnection ( connections [ i ] , out strm ) ) ! = NetworkEvent . Type . Empty )
{
if ( cmd = = NetworkEvent . Type . Data )
if ( cmd = = NetworkEvent . Type . Connect )
// For ping requests we reply with a pong message
int id = strm . ReadInt ( ) ;
// TODO: Assuming that i is the index in connections, which will be the order in which they are received and also will not shift downward if disconnects happen? Need to test with multiple clients.
SendPong ( driver , connections ) ;
}
else if ( cmd = = NetworkEvent . Type . Data )
{
byte header = strm . ReadByte ( ) ;
int contents = header % 3 2 ;
header = ( byte ) ( header > > 5 ) ;
MsgType msgType = ( MsgType ) header ;
Debug . LogWarning ( "Received int: " + id ) ;
if ( msgType = = MsgType . PingPong )
{
SendPong ( driver , connections ) ;
}
else if ( msgType = = MsgType . PlayerName )
{
byte [ ] nameBytes = new byte [ contents ] ;
unsafe
{
fixed ( byte * namePtr = nameBytes )
{
strm . ReadBytes ( namePtr , contents ) ;
}
}
string name = System . Text . Encoding . UTF8 . GetString ( nameBytes ) ;
Debug . LogWarning ( "Received name for connection " + i + ": " + name ) ;
// Create a temporary DataStreamWriter to keep our serialized pong message
if ( driver . BeginSend ( connections [ i ] , out var pongData ) = = 0 )
{
pongData . WriteInt ( id ) ;
// Send the pong message with the same id as the ping
driver . EndSend ( pongData ) ;
SendPong ( driver , connections ) ;
}
}
else if ( cmd = = NetworkEvent . Type . Disconnect )
connections [ i ] = default ( NetworkConnection ) ;
}
}
void SendPong ( NetworkDriver . Concurrent driver , NativeArray < NetworkConnection > connections )
{
byte reply = ( byte ) ( ( ( int ) MsgType . PingPong ) < < 5 ) ;
if ( driver . BeginSend ( connections [ i ] , out var writeData ) = = 0 )
{
writeData . WriteByte ( reply ) ;
driver . EndSend ( writeData ) ;
Debug . LogWarning ( "Sent pong for connection " + i ) ;
}
}
}
}
public class RelayUtpSetup_Client : RelayUTPSetup
{
private LocalLobby m_localLobby ;
private JobHandle m_activeUpdateJobHandle ;
// TEMP
public string myName { private get ; set ; }
public void JoinRelay ( LocalLobby localLobby )
protected override void JoinRelay ( )
m_localLobby = localLobby ;
localLobby . onChanged + = OnLobbyChange ;
m_ localLobby. onChanged + = OnLobbyChange ;
}
private void OnLobbyChange ( LocalLobby lobby )
{
if ( allocation = = null )
return ; // TODO: Error messaging.
BindToAllocation ( allocation . RelayServer . IpV4 , allocation . RelayServer . Port , allocation . AllocationIdBytes , allocation . ConnectionData , allocation . HostConnectionData , allocation . Key , 1 ) ;
}
public NetworkDriver driver ;
public NativeArray < NetworkConnection > connection ; // TODO: I think we were using NativeArray to merely contain one entry, since we'd be unable to pass just that via jobs?
public float fixedTime ;
public NativeArray < byte > myName ;
public void Execute ( )
{
{
if ( cmd = = NetworkEvent . Type . Connect )
{
// Create a 4 byte data stream which we can store our ping sequence number in
// Same as name sending.
if ( myName = = null | | myName . Length = = 0 )
return ;
List < byte > message = new List < byte > ( myName . Length + 1 ) ;
message . AddRange ( myName ) ;
byte header = ( byte ) ( ( ( ( int ) MsgType . PlayerName ) < < 5 ) + myName . Length ) ; // TODO: Truncate length;
message . Insert ( 0 , header ) ;
if ( driver . BeginSend ( connection [ 0 ] , out var pingData ) = = 0 )
if ( driver . BeginSend ( connection [ 0 ] , out var connectData ) = = 0 ) // Oh, should check this first?
pingData . WriteInt ( 1 2 3 ) ;
driver . EndSend ( pingData ) ;
byte [ ] bytes = message . ToArray ( ) ;
unsafe
{
fixed ( byte * bytesPtr = bytes )
{
connectData . WriteBytes ( bytesPtr , message . Count ) ;
driver . EndSend ( connectData ) ;
}
}
}
}
else if ( cmd = = NetworkEvent . Type . Data )
{
driver = m_networkDriver ,
connection = m_connections . AsArray ( ) ,
fixedTime = Time . fixedTime
fixedTime = Time . fixedTime ,
myName = new NativeArray < byte > ( System . Text . Encoding . UTF8 . GetBytes ( myName ) , Allocator . TempJob )
} ;
pingJob . Schedule ( ) . Complete ( ) ;
// Wait for the previous frames ping to complete before starting a new one, the Complete in LateUpdate is not
// enough since we can get multiple FixedUpdate per frame on slow clients
m_activeUpdateJobHandle . Complete ( ) ;
m_currentUpdateHandle . Complete ( ) ;
fixedTime = Time . fixedTime
fixedTime = Time . fixedTime ,
myName = new NativeArray < byte > ( System . Text . Encoding . UTF8 . GetBytes ( myName ) , Allocator . TempJob )
m_activeUpdateJobHandle = m_networkDriver . ScheduleUpdate ( ) ;
m_activeUpdateJobHandle = pingJob . Schedule ( m_activeUpdateJobHandle ) ;
m_currentUpdateHandle = m_networkDriver . ScheduleUpdate ( ) ;
m_currentUpdateHandle = pingJob . Schedule ( m_currentUpdateHandle ) ;
}
}
}