reformat code

This commit is contained in:
JohnCorby 2022-02-05 20:17:08 -08:00
parent e7accbdf17
commit c9f9ba0801
10 changed files with 1562 additions and 1278 deletions

View File

@ -50,9 +50,10 @@ using System.Collections.Generic;
/// MIT License /// MIT License
/// </summary> /// </summary>
namespace EpicTransport { namespace EpicTransport
{
public class BidirectionalDictionary<T1, T2> : IEnumerable { public class BidirectionalDictionary<T1, T2> : IEnumerable
{
private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>(); private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>(); private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
@ -63,12 +64,14 @@ namespace EpicTransport {
public int Count => t1ToT2Dict.Count; public int Count => t1ToT2Dict.Count;
public void Add(T1 key, T2 value) { public void Add(T1 key, T2 value)
{
t1ToT2Dict[key] = value; t1ToT2Dict[key] = value;
t2ToT1Dict[value] = key; t2ToT1Dict[value] = key;
} }
public void Add(T2 key, T1 value) { public void Add(T2 key, T1 value)
{
t2ToT1Dict[key] = value; t2ToT1Dict[key] = value;
t1ToT2Dict[value] = key; t1ToT2Dict[value] = key;
} }
@ -85,36 +88,44 @@ namespace EpicTransport {
public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key); public bool Contains(T2 key) => t2ToT1Dict.ContainsKey(key);
public void Remove(T1 key) { public void Remove(T1 key)
if (Contains(key)) { {
if (Contains(key))
{
T2 val = t1ToT2Dict[key]; T2 val = t1ToT2Dict[key];
t1ToT2Dict.Remove(key); t1ToT2Dict.Remove(key);
t2ToT1Dict.Remove(val); t2ToT1Dict.Remove(val);
} }
} }
public void Remove(T2 key) {
if (Contains(key)) { public void Remove(T2 key)
{
if (Contains(key))
{
T1 val = t2ToT1Dict[key]; T1 val = t2ToT1Dict[key];
t1ToT2Dict.Remove(val); t1ToT2Dict.Remove(val);
t2ToT1Dict.Remove(key); t2ToT1Dict.Remove(key);
} }
} }
public T1 this[T2 key] { public T1 this[T2 key]
{
get => t2ToT1Dict[key]; get => t2ToT1Dict[key];
set { set
{
t2ToT1Dict[key] = value; t2ToT1Dict[key] = value;
t1ToT2Dict[value] = key; t1ToT2Dict[value] = key;
} }
} }
public T2 this[T1 key] { public T2 this[T1 key]
{
get => t1ToT2Dict[key]; get => t1ToT2Dict[key];
set { set
{
t1ToT2Dict[key] = value; t1ToT2Dict[key] = value;
t2ToT1Dict[value] = key; t2ToT1Dict[value] = key;
} }
} }
} }
} }

View File

@ -6,9 +6,10 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
namespace EpicTransport { namespace EpicTransport
public class Client : Common { {
public class Client : Common
{
public SocketId socketId; public SocketId socketId;
public ProductUserId serverId; public ProductUserId serverId;
@ -27,11 +28,13 @@ namespace EpicTransport {
private TaskCompletionSource<Task> connectedComplete; private TaskCompletionSource<Task> connectedComplete;
private CancellationTokenSource cancelToken; private CancellationTokenSource cancelToken;
private Client(EosTransport transport) : base(transport) { private Client(EosTransport transport) : base(transport)
{
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.timeout)); ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.timeout));
} }
public static Client CreateClient(EosTransport transport, string host) { public static Client CreateClient(EosTransport transport, string host)
{
Client c = new Client(transport); Client c = new Client(transport);
c.hostAddress = host; c.hostAddress = host;
@ -44,10 +47,12 @@ namespace EpicTransport {
return c; return c;
} }
public async void Connect(string host) { public async void Connect(string host)
{
cancelToken = new CancellationTokenSource(); cancelToken = new CancellationTokenSource();
try { try
{
hostProductId = ProductUserId.FromString(host); hostProductId = ProductUserId.FromString(host);
serverId = hostProductId; serverId = hostProductId;
connectedComplete = new TaskCompletionSource<Task>(); connectedComplete = new TaskCompletionSource<Task>();
@ -58,35 +63,46 @@ namespace EpicTransport {
Task connectedCompleteTask = connectedComplete.Task; Task connectedCompleteTask = connectedComplete.Task;
if (await Task.WhenAny(connectedCompleteTask, Task.Delay(ConnectionTimeout/*, cancelToken.Token*/)) != connectedCompleteTask) { if (await Task.WhenAny(connectedCompleteTask, Task.Delay(ConnectionTimeout /*, cancelToken.Token*/)) != connectedCompleteTask)
{
Debug.LogError($"Connection to {host} timed out."); Debug.LogError($"Connection to {host} timed out.");
OnConnected -= SetConnectedComplete; OnConnected -= SetConnectedComplete;
OnConnectionFailed(hostProductId); OnConnectionFailed(hostProductId);
} }
OnConnected -= SetConnectedComplete; OnConnected -= SetConnectedComplete;
} catch (FormatException) { }
catch (FormatException)
{
Debug.LogError($"Connection string was not in the right format. Did you enter a ProductId?"); Debug.LogError($"Connection string was not in the right format. Did you enter a ProductId?");
Error = true; Error = true;
OnConnectionFailed(hostProductId); OnConnectionFailed(hostProductId);
} catch (Exception ex) { }
catch (Exception ex)
{
Debug.LogError(ex.Message); Debug.LogError(ex.Message);
Error = true; Error = true;
OnConnectionFailed(hostProductId); OnConnectionFailed(hostProductId);
} finally { }
if (Error) { finally
{
if (Error)
{
OnConnectionFailed(null); OnConnectionFailed(null);
} }
} }
} }
public void Disconnect() { public void Disconnect()
if (serverId != null) { {
if (serverId != null)
{
CloseP2PSessionWithUser(serverId, socketId); CloseP2PSessionWithUser(serverId, socketId);
serverId = null; serverId = null;
} else { }
else
{
return; return;
} }
@ -100,12 +116,15 @@ namespace EpicTransport {
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task); private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel) { protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
if (clientUserId != hostProductId) { if (clientUserId != hostProductId)
{
Debug.LogError("Received a message from an unknown"); Debug.LogError("Received a message from an unknown");
return; return;
} }
@ -113,34 +132,44 @@ namespace EpicTransport {
OnReceivedData.Invoke(data, channel); OnReceivedData.Invoke(data, channel);
} }
protected override void OnNewConnection(OnIncomingConnectionRequestInfo result) { protected override void OnNewConnection(OnIncomingConnectionRequestInfo result)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
if (deadSockets.Contains(result.SocketId.SocketName)) { if (deadSockets.Contains(result.SocketId.SocketName))
{
Debug.LogError("Received incoming connection request from dead socket"); Debug.LogError("Received incoming connection request from dead socket");
return; return;
} }
if (hostProductId == result.RemoteUserId) { if (hostProductId == result.RemoteUserId)
{
EOSSDKComponent.GetP2PInterface().AcceptConnection( EOSSDKComponent.GetP2PInterface().AcceptConnection(
new AcceptConnectionOptions() { new AcceptConnectionOptions()
{
LocalUserId = EOSSDKComponent.LocalUserProductId, LocalUserId = EOSSDKComponent.LocalUserProductId,
RemoteUserId = result.RemoteUserId, RemoteUserId = result.RemoteUserId,
SocketId = result.SocketId SocketId = result.SocketId
}); });
} else { }
else
{
Debug.LogError("P2P Acceptance Request from unknown host ID."); Debug.LogError("P2P Acceptance Request from unknown host ID.");
} }
} }
protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId) { protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
switch (type) { switch (type)
{
case InternalMessages.ACCEPT_CONNECT: case InternalMessages.ACCEPT_CONNECT:
Connected = true; Connected = true;
OnConnected.Invoke(); OnConnected.Invoke();
@ -158,7 +187,7 @@ namespace EpicTransport {
} }
} }
public void Send(byte[] data, int channelId) => Send(hostProductId, socketId, data, (byte) channelId); public void Send(byte[] data, int channelId) => Send(hostProductId, socketId, data, (byte)channelId);
protected override void OnConnectionFailed(ProductUserId remoteId) => OnDisconnected.Invoke(); protected override void OnConnectionFailed(ProductUserId remoteId) => OnDisconnected.Invoke();
public void EosNotInitialized() => OnDisconnected.Invoke(); public void EosNotInitialized() => OnDisconnected.Invoke();

View File

@ -1,24 +1,26 @@
 using Epic.OnlineServices;
using Epic.OnlineServices;
using Epic.OnlineServices.P2P; using Epic.OnlineServices.P2P;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace EpicTransport { namespace EpicTransport
public abstract class Common { {
public abstract class Common
{
private PacketReliability[] channels; private PacketReliability[] channels;
private int internal_ch => channels.Length; private int internal_ch => channels.Length;
protected enum InternalMessages : byte { protected enum InternalMessages : byte
{
CONNECT, CONNECT,
ACCEPT_CONNECT, ACCEPT_CONNECT,
DISCONNECT DISCONNECT
} }
protected struct PacketKey { protected struct PacketKey
{
public ProductUserId productUserId; public ProductUserId productUserId;
public byte channel; public byte channel;
} }
@ -36,7 +38,8 @@ namespace EpicTransport {
// Mapping from PacketKey to a List of Packet Lists // Mapping from PacketKey to a List of Packet Lists
protected Dictionary<PacketKey, List<List<Packet>>> incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>(); protected Dictionary<PacketKey, List<List<Packet>>> incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>();
protected Common(EosTransport transport) { protected Common(EosTransport transport)
{
channels = transport.Channels; channels = transport.Channels;
deadSockets = new List<string>(); deadSockets = new List<string>();
@ -58,17 +61,18 @@ namespace EpicTransport {
outgoingNotificationId = EOSSDKComponent.GetP2PInterface().AddNotifyPeerConnectionClosed(addNotifyPeerConnectionClosedOptions, outgoingNotificationId = EOSSDKComponent.GetP2PInterface().AddNotifyPeerConnectionClosed(addNotifyPeerConnectionClosedOptions,
null, OnRemoteConnectionClosed); null, OnRemoteConnectionClosed);
if (outgoingNotificationId == 0 || incomingNotificationId == 0) { if (outgoingNotificationId == 0 || incomingNotificationId == 0)
{
Debug.LogError("Couldn't bind notifications with P2P interface"); Debug.LogError("Couldn't bind notifications with P2P interface");
} }
incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>(); incomingPackets = new Dictionary<PacketKey, List<List<Packet>>>();
this.transport = transport; this.transport = transport;
} }
protected void Dispose() { protected void Dispose()
{
EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionRequest(incomingNotificationId); EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionRequest(incomingNotificationId);
EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionClosed(outgoingNotificationId); EOSSDKComponent.GetP2PInterface().RemoveNotifyPeerConnectionClosed(outgoingNotificationId);
@ -77,14 +81,17 @@ namespace EpicTransport {
protected abstract void OnNewConnection(OnIncomingConnectionRequestInfo result); protected abstract void OnNewConnection(OnIncomingConnectionRequestInfo result);
private void OnConnectFail(OnRemoteConnectionClosedInfo result) { private void OnConnectFail(OnRemoteConnectionClosedInfo result)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
OnConnectionFailed(result.RemoteUserId); OnConnectionFailed(result.RemoteUserId);
switch (result.Reason) { switch (result.Reason)
{
case ConnectionClosedReason.ClosedByLocalUser: case ConnectionClosedReason.ClosedByLocalUser:
throw new Exception("Connection cLosed: The Connection was gracecfully closed by the local user."); throw new Exception("Connection cLosed: The Connection was gracecfully closed by the local user.");
case ConnectionClosedReason.ClosedByPeer: case ConnectionClosedReason.ClosedByPeer:
@ -111,11 +118,13 @@ namespace EpicTransport {
} }
} }
protected void SendInternal(ProductUserId target, SocketId socketId, InternalMessages type) { protected void SendInternal(ProductUserId target, SocketId socketId, InternalMessages type)
EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions() { {
EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions()
{
AllowDelayedDelivery = true, AllowDelayedDelivery = true,
Channel = (byte) internal_ch, Channel = (byte)internal_ch,
Data = new byte[] { (byte) type }, Data = new byte[] { (byte)type },
LocalUserId = EOSSDKComponent.LocalUserProductId, LocalUserId = EOSSDKComponent.LocalUserProductId,
Reliability = PacketReliability.ReliableOrdered, Reliability = PacketReliability.ReliableOrdered,
RemoteUserId = target, RemoteUserId = target,
@ -123,9 +132,10 @@ namespace EpicTransport {
}); });
} }
protected void Send(ProductUserId host, SocketId socketId, byte[] msgBuffer, byte channel)
protected void Send(ProductUserId host, SocketId socketId, byte[] msgBuffer, byte channel) { {
Result result = EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions() { Result result = EOSSDKComponent.GetP2PInterface().SendPacket(new SendPacketOptions()
{
AllowDelayedDelivery = true, AllowDelayedDelivery = true,
Channel = channel, Channel = channel,
Data = msgBuffer, Data = msgBuffer,
@ -135,19 +145,23 @@ namespace EpicTransport {
SocketId = socketId SocketId = socketId
}); });
if(result != Result.Success) { if (result != Result.Success)
{
Debug.LogError("Send failed " + result); Debug.LogError("Send failed " + result);
} }
} }
private bool Receive(out ProductUserId clientProductUserId, out SocketId socketId, out byte[] receiveBuffer, byte channel) { private bool Receive(out ProductUserId clientProductUserId, out SocketId socketId, out byte[] receiveBuffer, byte channel)
Result result = EOSSDKComponent.GetP2PInterface().ReceivePacket(new ReceivePacketOptions() { {
Result result = EOSSDKComponent.GetP2PInterface().ReceivePacket(new ReceivePacketOptions()
{
LocalUserId = EOSSDKComponent.LocalUserProductId, LocalUserId = EOSSDKComponent.LocalUserProductId,
MaxDataSizeBytes = P2PInterface.MaxPacketSize, MaxDataSizeBytes = P2PInterface.MaxPacketSize,
RequestedChannel = channel RequestedChannel = channel
}, out clientProductUserId, out socketId, out channel, out receiveBuffer); }, out clientProductUserId, out socketId, out channel, out receiveBuffer);
if (result == Result.Success) { if (result == Result.Success)
{
return true; return true;
} }
@ -156,47 +170,62 @@ namespace EpicTransport {
return false; return false;
} }
protected virtual void CloseP2PSessionWithUser(ProductUserId clientUserID, SocketId socketId) { protected virtual void CloseP2PSessionWithUser(ProductUserId clientUserID, SocketId socketId)
if (socketId == null) { {
if (socketId == null)
{
Debug.LogWarning("Socket ID == null | " + ignoreAllMessages); Debug.LogWarning("Socket ID == null | " + ignoreAllMessages);
return; return;
} }
if (deadSockets == null) { if (deadSockets == null)
{
Debug.LogWarning("DeadSockets == null"); Debug.LogWarning("DeadSockets == null");
return; return;
} }
if (deadSockets.Contains(socketId.SocketName)) { if (deadSockets.Contains(socketId.SocketName))
{
return; return;
} else { }
else
{
deadSockets.Add(socketId.SocketName); deadSockets.Add(socketId.SocketName);
} }
} }
protected void WaitForClose(ProductUserId clientUserID, SocketId socketId) => transport.StartCoroutine(DelayedClose(clientUserID, socketId)); protected void WaitForClose(ProductUserId clientUserID, SocketId socketId) => transport.StartCoroutine(DelayedClose(clientUserID, socketId));
private IEnumerator DelayedClose(ProductUserId clientUserID, SocketId socketId) {
private IEnumerator DelayedClose(ProductUserId clientUserID, SocketId socketId)
{
yield return null; yield return null;
CloseP2PSessionWithUser(clientUserID, socketId); CloseP2PSessionWithUser(clientUserID, socketId);
} }
public void ReceiveData() { public void ReceiveData()
try { {
try
{
// Internal Channel, no fragmentation here // Internal Channel, no fragmentation here
SocketId socketId = new SocketId(); SocketId socketId = new SocketId();
while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] internalMessage, (byte) internal_ch)) { while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] internalMessage, (byte)internal_ch))
if (internalMessage.Length == 1) { {
OnReceiveInternalData((InternalMessages) internalMessage[0], clientUserID, socketId); if (internalMessage.Length == 1)
{
OnReceiveInternalData((InternalMessages)internalMessage[0], clientUserID, socketId);
return; // Wait one frame return; // Wait one frame
} else { }
else
{
Debug.Log("Incorrect package length on internal channel."); Debug.Log("Incorrect package length on internal channel.");
} }
} }
// Insert new packet at the correct location in the incoming queue // Insert new packet at the correct location in the incoming queue
for (int chNum = 0; chNum < channels.Length; chNum++) { for (int chNum = 0; chNum < channels.Length; chNum++)
while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] receiveBuffer, (byte) chNum)) { {
while (transport.enabled && Receive(out ProductUserId clientUserID, out socketId, out byte[] receiveBuffer, (byte)chNum))
{
PacketKey incomingPacketKey = new PacketKey(); PacketKey incomingPacketKey = new PacketKey();
incomingPacketKey.productUserId = clientUserID; incomingPacketKey.productUserId = clientUserID;
incomingPacketKey.channel = (byte)chNum; incomingPacketKey.channel = (byte)chNum;
@ -204,34 +233,43 @@ namespace EpicTransport {
Packet packet = new Packet(); Packet packet = new Packet();
packet.FromBytes(receiveBuffer); packet.FromBytes(receiveBuffer);
if (!incomingPackets.ContainsKey(incomingPacketKey)) { if (!incomingPackets.ContainsKey(incomingPacketKey))
{
incomingPackets.Add(incomingPacketKey, new List<List<Packet>>()); incomingPackets.Add(incomingPacketKey, new List<List<Packet>>());
} }
int packetListIndex = incomingPackets[incomingPacketKey].Count; int packetListIndex = incomingPackets[incomingPacketKey].Count;
for(int i = 0; i < incomingPackets[incomingPacketKey].Count; i++) { for (int i = 0; i < incomingPackets[incomingPacketKey].Count; i++)
if(incomingPackets[incomingPacketKey][i][0].id == packet.id) { {
if (incomingPackets[incomingPacketKey][i][0].id == packet.id)
{
packetListIndex = i; packetListIndex = i;
break; break;
} }
} }
if (packetListIndex == incomingPackets[incomingPacketKey].Count) { if (packetListIndex == incomingPackets[incomingPacketKey].Count)
{
incomingPackets[incomingPacketKey].Add(new List<Packet>()); incomingPackets[incomingPacketKey].Add(new List<Packet>());
} }
int insertionIndex = -1; int insertionIndex = -1;
for (int i = 0; i < incomingPackets[incomingPacketKey][packetListIndex].Count; i++) { for (int i = 0; i < incomingPackets[incomingPacketKey][packetListIndex].Count; i++)
if (incomingPackets[incomingPacketKey][packetListIndex][i].fragment > packet.fragment) { {
if (incomingPackets[incomingPacketKey][packetListIndex][i].fragment > packet.fragment)
{
insertionIndex = i; insertionIndex = i;
break; break;
} }
} }
if (insertionIndex >= 0) { if (insertionIndex >= 0)
{
incomingPackets[incomingPacketKey][packetListIndex].Insert(insertionIndex, packet); incomingPackets[incomingPacketKey][packetListIndex].Insert(insertionIndex, packet);
} else { }
else
{
incomingPackets[incomingPacketKey][packetListIndex].Add(packet); incomingPackets[incomingPacketKey][packetListIndex].Add(packet);
} }
} }
@ -239,24 +277,32 @@ namespace EpicTransport {
// Find fully received packets // Find fully received packets
List<List<Packet>> emptyPacketLists = new List<List<Packet>>(); List<List<Packet>> emptyPacketLists = new List<List<Packet>>();
foreach(KeyValuePair<PacketKey, List<List<Packet>>> keyValuePair in incomingPackets) { foreach (KeyValuePair<PacketKey, List<List<Packet>>> keyValuePair in incomingPackets)
for(int packetList = 0; packetList < keyValuePair.Value.Count; packetList++) { {
for (int packetList = 0; packetList < keyValuePair.Value.Count; packetList++)
{
bool packetReady = true; bool packetReady = true;
int packetLength = 0; int packetLength = 0;
for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++) { for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++)
{
Packet tempPacket = keyValuePair.Value[packetList][packet]; Packet tempPacket = keyValuePair.Value[packetList][packet];
if (tempPacket.fragment != packet || (packet == keyValuePair.Value[packetList].Count - 1 && tempPacket.moreFragments)) { if (tempPacket.fragment != packet || (packet == keyValuePair.Value[packetList].Count - 1 && tempPacket.moreFragments))
{
packetReady = false; packetReady = false;
} else { }
else
{
packetLength += tempPacket.data.Length; packetLength += tempPacket.data.Length;
} }
} }
if (packetReady) { if (packetReady)
{
byte[] data = new byte[packetLength]; byte[] data = new byte[packetLength];
int dataIndex = 0; int dataIndex = 0;
for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++) { for (int packet = 0; packet < keyValuePair.Value[packetList].Count; packet++)
{
Array.Copy(keyValuePair.Value[packetList][packet].data, 0, data, dataIndex, keyValuePair.Value[packetList][packet].data.Length); Array.Copy(keyValuePair.Value[packetList][packet].data, 0, data, dataIndex, keyValuePair.Value[packetList][packet].data.Length);
dataIndex += keyValuePair.Value[packetList][packet].data.Length; dataIndex += keyValuePair.Value[packetList][packet].data.Length;
} }
@ -268,15 +314,16 @@ namespace EpicTransport {
} }
} }
for (int i = 0; i < emptyPacketLists.Count; i++) { for (int i = 0; i < emptyPacketLists.Count; i++)
{
keyValuePair.Value.Remove(emptyPacketLists[i]); keyValuePair.Value.Remove(emptyPacketLists[i]);
} }
emptyPacketLists.Clear(); emptyPacketLists.Clear();
} }
}
catch (Exception e)
{
} catch (Exception e) {
Debug.LogException(e); Debug.LogException(e);
} }
} }

View File

@ -1,10 +1,8 @@
using Epic.OnlineServices; using Epic.OnlineServices;
using Epic.OnlineServices.Logging; using Epic.OnlineServices.Logging;
using Epic.OnlineServices.Platform; using Epic.OnlineServices.Platform;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using UnityEngine; using UnityEngine;
/// <summary> /// <summary>
@ -14,10 +12,11 @@ using UnityEngine;
/// after releasing the SDK the game has to be restarted in order to initialize the SDK again. /// after releasing the SDK the game has to be restarted in order to initialize the SDK again.
/// In the unity editor the OnDestroy function will not run so that we dont have to restart the editor after play. /// In the unity editor the OnDestroy function will not run so that we dont have to restart the editor after play.
/// </summary> /// </summary>
namespace EpicTransport { namespace EpicTransport
{
[DefaultExecutionOrder(-32000)] [DefaultExecutionOrder(-32000)]
public class EOSSDKComponent : MonoBehaviour { public class EOSSDKComponent : MonoBehaviour
{
// Unity Inspector shown variables // Unity Inspector shown variables
[SerializeField] [SerializeField]
@ -31,11 +30,14 @@ namespace EpicTransport {
public Epic.OnlineServices.ExternalCredentialType connectInterfaceCredentialType = Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken; public Epic.OnlineServices.ExternalCredentialType connectInterfaceCredentialType = Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken;
public string deviceModel = "PC Windows 64bit"; public string deviceModel = "PC Windows 64bit";
[SerializeField] private string displayName = "User"; [SerializeField] private string displayName = "User";
public static string DisplayName { public static string DisplayName
get { {
get
{
return Instance.displayName; return Instance.displayName;
} }
set { set
{
Instance.displayName = value; Instance.displayName = value;
} }
} }
@ -45,8 +47,10 @@ namespace EpicTransport {
[SerializeField] [SerializeField]
public bool collectPlayerMetrics = true; public bool collectPlayerMetrics = true;
public static bool CollectPlayerMetrics { public static bool CollectPlayerMetrics
get { {
get
{
return Instance.collectPlayerMetrics; return Instance.collectPlayerMetrics;
} }
} }
@ -61,7 +65,6 @@ namespace EpicTransport {
private ulong authExpirationHandle; private ulong authExpirationHandle;
private string authInterfaceLoginCredentialId = null; private string authInterfaceLoginCredentialId = null;
public static void SetAuthInterfaceLoginCredentialId(string credentialId) => Instance.authInterfaceLoginCredentialId = credentialId; public static void SetAuthInterfaceLoginCredentialId(string credentialId) => Instance.authInterfaceLoginCredentialId = credentialId;
private string authInterfaceCredentialToken = null; private string authInterfaceCredentialToken = null;
@ -89,61 +92,78 @@ namespace EpicTransport {
public static Epic.OnlineServices.UI.UIInterface GetUIInterface() => Instance.EOS.GetUIInterface(); public static Epic.OnlineServices.UI.UIInterface GetUIInterface() => Instance.EOS.GetUIInterface();
public static Epic.OnlineServices.UserInfo.UserInfoInterface GetUserInfoInterface() => Instance.EOS.GetUserInfoInterface(); public static Epic.OnlineServices.UserInfo.UserInfoInterface GetUserInfoInterface() => Instance.EOS.GetUserInfoInterface();
protected EpicAccountId localUserAccountId; protected EpicAccountId localUserAccountId;
public static EpicAccountId LocalUserAccountId { public static EpicAccountId LocalUserAccountId
get { {
get
{
return Instance.localUserAccountId; return Instance.localUserAccountId;
} }
} }
protected string localUserAccountIdString; protected string localUserAccountIdString;
public static string LocalUserAccountIdString { public static string LocalUserAccountIdString
get { {
get
{
return Instance.localUserAccountIdString; return Instance.localUserAccountIdString;
} }
} }
protected ProductUserId localUserProductId; protected ProductUserId localUserProductId;
public static ProductUserId LocalUserProductId { public static ProductUserId LocalUserProductId
get { {
get
{
return Instance.localUserProductId; return Instance.localUserProductId;
} }
} }
protected string localUserProductIdString; protected string localUserProductIdString;
public static string LocalUserProductIdString { public static string LocalUserProductIdString
get { {
get
{
return Instance.localUserProductIdString; return Instance.localUserProductIdString;
} }
} }
protected bool initialized; protected bool initialized;
public static bool Initialized { public static bool Initialized
get { {
get
{
return Instance.initialized; return Instance.initialized;
} }
} }
protected bool isConnecting; protected bool isConnecting;
public static bool IsConnecting { public static bool IsConnecting
get { {
get
{
return Instance.isConnecting; return Instance.isConnecting;
} }
} }
protected static EOSSDKComponent instance; protected static EOSSDKComponent instance;
protected static EOSSDKComponent Instance { protected static EOSSDKComponent Instance
get { {
if (instance == null) { get
{
if (instance == null)
{
return new GameObject("EOSSDKComponent").AddComponent<EOSSDKComponent>(); return new GameObject("EOSSDKComponent").AddComponent<EOSSDKComponent>();
} else { }
else
{
return instance; return instance;
} }
} }
} }
public static void Tick() { public static void Tick()
{
instance.platformTickTimer -= Time.deltaTime; instance.platformTickTimer -= Time.deltaTime;
instance.EOS.Tick(); instance.EOS.Tick();
} }
@ -189,7 +209,8 @@ namespace EpicTransport {
private IntPtr libraryPointer; private IntPtr libraryPointer;
#endif #endif
private void Awake() { private void Awake()
{
// Initialize Java version of the SDK with a reference to the VM with JNI // Initialize Java version of the SDK with a reference to the VM with JNI
// See https://eoshelp.epicgames.com/s/question/0D54z00006ufJBNCA2/cant-get-createdeviceid-to-work-in-unity-android-c-sdk?language=en_US // See https://eoshelp.epicgames.com/s/question/0D54z00006ufJBNCA2/cant-get-createdeviceid-to-work-in-unity-android-c-sdk?language=en_US
if (Application.platform == RuntimePlatform.Android) if (Application.platform == RuntimePlatform.Android)
@ -202,10 +223,12 @@ namespace EpicTransport {
} }
// Prevent multiple instances // Prevent multiple instances
if (instance != null) { if (instance != null)
{
Destroy(gameObject); Destroy(gameObject);
return; return;
} }
instance = this; instance = this;
#if UNITY_EDITOR #if UNITY_EDITOR
@ -219,15 +242,18 @@ namespace EpicTransport {
Bindings.Hook(libraryPointer, GetProcAddress); Bindings.Hook(libraryPointer, GetProcAddress);
#endif #endif
if (!delayedInitialization) { if (!delayedInitialization)
{
Initialize(); Initialize();
} }
} }
protected void InitializeImplementation() { protected void InitializeImplementation()
{
isConnecting = true; isConnecting = true;
var initializeOptions = new InitializeOptions() { var initializeOptions = new InitializeOptions()
{
ProductName = apiKeys.epicProductName, ProductName = apiKeys.epicProductName,
ProductVersion = apiKeys.epicProductVersion ProductVersion = apiKeys.epicProductVersion
}; };
@ -236,7 +262,8 @@ namespace EpicTransport {
// This code is called each time the game is run in the editor, so we catch the case where the SDK has already been initialized in the editor. // This code is called each time the game is run in the editor, so we catch the case where the SDK has already been initialized in the editor.
var isAlreadyConfiguredInEditor = Application.isEditor && initializeResult == Result.AlreadyConfigured; var isAlreadyConfiguredInEditor = Application.isEditor && initializeResult == Result.AlreadyConfigured;
if (initializeResult != Result.Success && !isAlreadyConfiguredInEditor) { if (initializeResult != Result.Success && !isAlreadyConfiguredInEditor)
{
throw new System.Exception("Failed to initialize platform: " + initializeResult); throw new System.Exception("Failed to initialize platform: " + initializeResult);
} }
@ -245,11 +272,13 @@ namespace EpicTransport {
LoggingInterface.SetLogLevel(LogCategory.AllCategories, epicLoggerLevel); LoggingInterface.SetLogLevel(LogCategory.AllCategories, epicLoggerLevel);
LoggingInterface.SetCallback(message => Logger.EpicDebugLog(message)); LoggingInterface.SetCallback(message => Logger.EpicDebugLog(message));
var options = new Options() { var options = new Options()
{
ProductId = apiKeys.epicProductId, ProductId = apiKeys.epicProductId,
SandboxId = apiKeys.epicSandboxId, SandboxId = apiKeys.epicSandboxId,
DeploymentId = apiKeys.epicDeploymentId, DeploymentId = apiKeys.epicDeploymentId,
ClientCredentials = new ClientCredentials() { ClientCredentials = new ClientCredentials()
{
ClientId = apiKeys.epicClientId, ClientId = apiKeys.epicClientId,
ClientSecret = apiKeys.epicClientSecret ClientSecret = apiKeys.epicClientSecret
}, },
@ -257,18 +286,21 @@ namespace EpicTransport {
}; };
EOS = PlatformInterface.Create(options); EOS = PlatformInterface.Create(options);
if (EOS == null) { if (EOS == null)
{
throw new System.Exception("Failed to create platform"); throw new System.Exception("Failed to create platform");
} }
if (checkForEpicLauncherAndRestart) { if (checkForEpicLauncherAndRestart)
{
Result result = EOS.CheckForLauncherAndRestart(); Result result = EOS.CheckForLauncherAndRestart();
// If not started through epic launcher the app will be restarted and we can quit // If not started through epic launcher the app will be restarted and we can quit
if (result != Result.NoChange) { if (result != Result.NoChange)
{
// Log error if launcher check failed, but still quit to prevent hacking // Log error if launcher check failed, but still quit to prevent hacking
if (result == Result.UnexpectedError) { if (result == Result.UnexpectedError)
{
Debug.LogError("Unexpected Error while checking if app was started through epic launcher"); Debug.LogError("Unexpected Error while checking if app was started through epic launcher");
} }
@ -278,15 +310,19 @@ namespace EpicTransport {
// If we use the Auth interface then only login into the Connect interface after finishing the auth interface login // If we use the Auth interface then only login into the Connect interface after finishing the auth interface login
// If we don't use the Auth interface we can directly login to the Connect interface // If we don't use the Auth interface we can directly login to the Connect interface
if (authInterfaceLogin) { if (authInterfaceLogin)
if (authInterfaceCredentialType == Epic.OnlineServices.Auth.LoginCredentialType.Developer) { {
if (authInterfaceCredentialType == Epic.OnlineServices.Auth.LoginCredentialType.Developer)
{
authInterfaceLoginCredentialId = "localhost:" + devAuthToolPort; authInterfaceLoginCredentialId = "localhost:" + devAuthToolPort;
authInterfaceCredentialToken = devAuthToolCredentialName; authInterfaceCredentialToken = devAuthToolCredentialName;
} }
// Login to Auth Interface // Login to Auth Interface
Epic.OnlineServices.Auth.LoginOptions loginOptions = new Epic.OnlineServices.Auth.LoginOptions() { Epic.OnlineServices.Auth.LoginOptions loginOptions = new Epic.OnlineServices.Auth.LoginOptions()
Credentials = new Epic.OnlineServices.Auth.Credentials() { {
Credentials = new Epic.OnlineServices.Auth.Credentials()
{
Type = authInterfaceCredentialType, Type = authInterfaceCredentialType,
Id = authInterfaceLoginCredentialId, Id = authInterfaceLoginCredentialId,
Token = authInterfaceCredentialToken Token = authInterfaceCredentialToken
@ -295,33 +331,43 @@ namespace EpicTransport {
}; };
EOS.GetAuthInterface().Login(loginOptions, null, OnAuthInterfaceLogin); EOS.GetAuthInterface().Login(loginOptions, null, OnAuthInterfaceLogin);
} else { }
else
{
// Login to Connect Interface // Login to Connect Interface
if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken) { if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken)
{
Epic.OnlineServices.Connect.CreateDeviceIdOptions createDeviceIdOptions = new Epic.OnlineServices.Connect.CreateDeviceIdOptions(); Epic.OnlineServices.Connect.CreateDeviceIdOptions createDeviceIdOptions = new Epic.OnlineServices.Connect.CreateDeviceIdOptions();
createDeviceIdOptions.DeviceModel = deviceModel; createDeviceIdOptions.DeviceModel = deviceModel;
EOS.GetConnectInterface().CreateDeviceId(createDeviceIdOptions, null, OnCreateDeviceId); EOS.GetConnectInterface().CreateDeviceId(createDeviceIdOptions, null, OnCreateDeviceId);
} else { }
else
{
ConnectInterfaceLogin(); ConnectInterfaceLogin();
} }
} }
} }
public static void Initialize() {
if (Instance.initialized || Instance.isConnecting) { public static void Initialize()
{
if (Instance.initialized || Instance.isConnecting)
{
return; return;
} }
Instance.InitializeImplementation(); Instance.InitializeImplementation();
} }
private void OnAuthInterfaceLogin(Epic.OnlineServices.Auth.LoginCallbackInfo loginCallbackInfo) { private void OnAuthInterfaceLogin(Epic.OnlineServices.Auth.LoginCallbackInfo loginCallbackInfo)
if (loginCallbackInfo.ResultCode == Result.Success) { {
if (loginCallbackInfo.ResultCode == Result.Success)
{
Debug.Log("Auth Interface Login succeeded"); Debug.Log("Auth Interface Login succeeded");
string accountIdString; string accountIdString;
Result result = loginCallbackInfo.LocalUserId.ToString(out accountIdString); Result result = loginCallbackInfo.LocalUserId.ToString(out accountIdString);
if (Result.Success == result) { if (Result.Success == result)
{
Debug.Log("EOS User ID:" + accountIdString); Debug.Log("EOS User ID:" + accountIdString);
localUserAccountIdString = accountIdString; localUserAccountIdString = accountIdString;
@ -329,32 +375,45 @@ namespace EpicTransport {
} }
ConnectInterfaceLogin(); ConnectInterfaceLogin();
} else if(Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode)){ }
else if (Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode))
{
Debug.Log("Login returned " + loginCallbackInfo.ResultCode); Debug.Log("Login returned " + loginCallbackInfo.ResultCode);
} }
} }
private void OnCreateDeviceId(Epic.OnlineServices.Connect.CreateDeviceIdCallbackInfo createDeviceIdCallbackInfo) { private void OnCreateDeviceId(Epic.OnlineServices.Connect.CreateDeviceIdCallbackInfo createDeviceIdCallbackInfo)
if (createDeviceIdCallbackInfo.ResultCode == Result.Success || createDeviceIdCallbackInfo.ResultCode == Result.DuplicateNotAllowed) { {
if (createDeviceIdCallbackInfo.ResultCode == Result.Success || createDeviceIdCallbackInfo.ResultCode == Result.DuplicateNotAllowed)
{
ConnectInterfaceLogin(); ConnectInterfaceLogin();
} else if(Epic.OnlineServices.Common.IsOperationComplete(createDeviceIdCallbackInfo.ResultCode)) { }
else if (Epic.OnlineServices.Common.IsOperationComplete(createDeviceIdCallbackInfo.ResultCode))
{
Debug.Log("Device ID creation returned " + createDeviceIdCallbackInfo.ResultCode); Debug.Log("Device ID creation returned " + createDeviceIdCallbackInfo.ResultCode);
} }
} }
private void ConnectInterfaceLogin() { private void ConnectInterfaceLogin()
{
var loginOptions = new Epic.OnlineServices.Connect.LoginOptions(); var loginOptions = new Epic.OnlineServices.Connect.LoginOptions();
if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.Epic) { if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.Epic)
{
Epic.OnlineServices.Auth.Token token; Epic.OnlineServices.Auth.Token token;
Result result = EOS.GetAuthInterface().CopyUserAuthToken(new Epic.OnlineServices.Auth.CopyUserAuthTokenOptions(), localUserAccountId, out token); Result result = EOS.GetAuthInterface().CopyUserAuthToken(new Epic.OnlineServices.Auth.CopyUserAuthTokenOptions(), localUserAccountId, out token);
if (result == Result.Success) { if (result == Result.Success)
{
connectInterfaceCredentialToken = token.AccessToken; connectInterfaceCredentialToken = token.AccessToken;
} else { }
else
{
Debug.LogError("Failed to retrieve User Auth Token"); Debug.LogError("Failed to retrieve User Auth Token");
} }
} else if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken) { }
else if (connectInterfaceCredentialType == Epic.OnlineServices.ExternalCredentialType.DeviceidAccessToken)
{
loginOptions.UserLoginInfo = new Epic.OnlineServices.Connect.UserLoginInfo(); loginOptions.UserLoginInfo = new Epic.OnlineServices.Connect.UserLoginInfo();
loginOptions.UserLoginInfo.DisplayName = displayName; loginOptions.UserLoginInfo.DisplayName = displayName;
} }
@ -366,13 +425,16 @@ namespace EpicTransport {
EOS.GetConnectInterface().Login(loginOptions, null, OnConnectInterfaceLogin); EOS.GetConnectInterface().Login(loginOptions, null, OnConnectInterfaceLogin);
} }
private void OnConnectInterfaceLogin(Epic.OnlineServices.Connect.LoginCallbackInfo loginCallbackInfo) { private void OnConnectInterfaceLogin(Epic.OnlineServices.Connect.LoginCallbackInfo loginCallbackInfo)
if (loginCallbackInfo.ResultCode == Result.Success) { {
if (loginCallbackInfo.ResultCode == Result.Success)
{
Debug.Log("Connect Interface Login succeeded"); Debug.Log("Connect Interface Login succeeded");
string productIdString; string productIdString;
Result result = loginCallbackInfo.LocalUserId.ToString(out productIdString); Result result = loginCallbackInfo.LocalUserId.ToString(out productIdString);
if (Result.Success == result) { if (Result.Success == result)
{
Debug.Log("EOS User Product ID:" + productIdString); Debug.Log("EOS User Product ID:" + productIdString);
localUserProductIdString = productIdString; localUserProductIdString = productIdString;
@ -384,36 +446,50 @@ namespace EpicTransport {
var authExpirationOptions = new Epic.OnlineServices.Connect.AddNotifyAuthExpirationOptions(); var authExpirationOptions = new Epic.OnlineServices.Connect.AddNotifyAuthExpirationOptions();
authExpirationHandle = EOS.GetConnectInterface().AddNotifyAuthExpiration(authExpirationOptions, null, OnAuthExpiration); authExpirationHandle = EOS.GetConnectInterface().AddNotifyAuthExpiration(authExpirationOptions, null, OnAuthExpiration);
} else if (Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode)) { }
else if (Epic.OnlineServices.Common.IsOperationComplete(loginCallbackInfo.ResultCode))
{
Debug.Log("Login returned " + loginCallbackInfo.ResultCode + "\nRetrying..."); Debug.Log("Login returned " + loginCallbackInfo.ResultCode + "\nRetrying...");
EOS.GetConnectInterface().CreateUser(new Epic.OnlineServices.Connect.CreateUserOptions() { ContinuanceToken = loginCallbackInfo.ContinuanceToken }, null, (Epic.OnlineServices.Connect.CreateUserCallbackInfo cb) => { EOS.GetConnectInterface().CreateUser(new Epic.OnlineServices.Connect.CreateUserOptions() { ContinuanceToken = loginCallbackInfo.ContinuanceToken }, null, (Epic.OnlineServices.Connect.CreateUserCallbackInfo cb) =>
if (cb.ResultCode != Result.Success) { Debug.Log(cb.ResultCode); return; } {
if (cb.ResultCode != Result.Success)
{
Debug.Log(cb.ResultCode);
return;
}
localUserProductId = cb.LocalUserId; localUserProductId = cb.LocalUserId;
ConnectInterfaceLogin(); ConnectInterfaceLogin();
}); });
} }
} }
private void OnAuthExpiration(Epic.OnlineServices.Connect.AuthExpirationCallbackInfo authExpirationCallbackInfo) { private void OnAuthExpiration(Epic.OnlineServices.Connect.AuthExpirationCallbackInfo authExpirationCallbackInfo)
{
Debug.Log("AuthExpiration callback"); Debug.Log("AuthExpiration callback");
EOS.GetConnectInterface().RemoveNotifyAuthExpiration(authExpirationHandle); EOS.GetConnectInterface().RemoveNotifyAuthExpiration(authExpirationHandle);
ConnectInterfaceLogin(); ConnectInterfaceLogin();
} }
// Calling tick on a regular interval is required for callbacks to work. // Calling tick on a regular interval is required for callbacks to work.
private void LateUpdate() { private void LateUpdate()
if (EOS != null) { {
if (EOS != null)
{
platformTickTimer += Time.deltaTime; platformTickTimer += Time.deltaTime;
if (platformTickTimer >= platformTickIntervalInSeconds) { if (platformTickTimer >= platformTickIntervalInSeconds)
{
platformTickTimer = 0; platformTickTimer = 0;
EOS.Tick(); EOS.Tick();
} }
} }
} }
private void OnApplicationQuit() { private void OnApplicationQuit()
if (EOS != null) { {
if (EOS != null)
{
EOS.Release(); EOS.Release();
EOS = null; EOS = null;
PlatformInterface.Shutdown(); PlatformInterface.Shutdown();

View File

@ -10,9 +10,9 @@ using UnityEngine;
/// Create -> EOS -> API Key /// Create -> EOS -> API Key
/// in order to create an instance of this scriptable object /// in order to create an instance of this scriptable object
/// </summary> /// </summary>
[CreateAssetMenu(fileName = "EosApiKey", menuName = "EOS/API Key", order = 1)] [CreateAssetMenu(fileName = "EosApiKey", menuName = "EOS/API Key", order = 1)]
public class EosApiKey : ScriptableObject { public class EosApiKey : ScriptableObject
{
public string epicProductName = "MyApplication"; public string epicProductName = "MyApplication";
public string epicProductVersion = "1.0"; public string epicProductVersion = "1.0";
public string epicProductId = ""; public string epicProductId = "";

View File

@ -8,12 +8,13 @@ using Mirror;
using Epic.OnlineServices.Metrics; using Epic.OnlineServices.Metrics;
using System.Collections; using System.Collections;
namespace EpicTransport { namespace EpicTransport
{
/// <summary> /// <summary>
/// EOS Transport following the Mirror transport standard /// EOS Transport following the Mirror transport standard
/// </summary> /// </summary>
public class EosTransport : Transport { public class EosTransport : Transport
{
private const string EPIC_SCHEME = "epic"; private const string EPIC_SCHEME = "epic";
private Client client; private Client client;
@ -41,14 +42,18 @@ namespace EpicTransport {
private int packetId = 0; private int packetId = 0;
private void Awake() { private void Awake()
{
Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for EOS Transport."); Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for EOS Transport.");
Debug.Assert(Channels.Length < byte.MaxValue, "Too many channels configured for EOS Transport"); Debug.Assert(Channels.Length < byte.MaxValue, "Too many channels configured for EOS Transport");
if(Channels[0] != PacketReliability.ReliableOrdered) { if (Channels[0] != PacketReliability.ReliableOrdered)
{
Debug.LogWarning("EOS Transport Channel[0] is not ReliableOrdered, Mirror expects Channel 0 to be ReliableOrdered, only change this if you know what you are doing."); Debug.LogWarning("EOS Transport Channel[0] is not ReliableOrdered, Mirror expects Channel 0 to be ReliableOrdered, only change this if you know what you are doing.");
} }
if (Channels[1] != PacketReliability.UnreliableUnordered) {
if (Channels[1] != PacketReliability.UnreliableUnordered)
{
Debug.LogWarning("EOS Transport Channel[1] is not UnreliableUnordered, Mirror expects Channel 1 to be UnreliableUnordered, only change this if you know what you are doing."); Debug.LogWarning("EOS Transport Channel[1] is not UnreliableUnordered, Mirror expects Channel 1 to be UnreliableUnordered, only change this if you know what you are doing.");
} }
@ -56,59 +61,79 @@ namespace EpicTransport {
StartCoroutine("ChangeRelayStatus"); StartCoroutine("ChangeRelayStatus");
} }
public override void ClientEarlyUpdate() { public override void ClientEarlyUpdate()
{
EOSSDKComponent.Tick(); EOSSDKComponent.Tick();
if (activeNode != null) { if (activeNode != null)
{
ignoreCachedMessagesTimer += Time.deltaTime; ignoreCachedMessagesTimer += Time.deltaTime;
if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds) { if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds)
{
activeNode.ignoreAllMessages = true; activeNode.ignoreAllMessages = true;
} else { }
else
{
activeNode.ignoreAllMessages = false; activeNode.ignoreAllMessages = false;
if (client != null && !client.isConnecting) { if (client != null && !client.isConnecting)
if (EOSSDKComponent.Initialized) { {
if (EOSSDKComponent.Initialized)
{
client.Connect(client.hostAddress); client.Connect(client.hostAddress);
} else { }
else
{
Debug.LogError("EOS not initialized"); Debug.LogError("EOS not initialized");
client.EosNotInitialized(); client.EosNotInitialized();
} }
client.isConnecting = true; client.isConnecting = true;
} }
} }
} }
if (enabled) { if (enabled)
{
activeNode?.ReceiveData(); activeNode?.ReceiveData();
} }
} }
public override void ClientLateUpdate() {} public override void ClientLateUpdate() { }
public override void ServerEarlyUpdate() { public override void ServerEarlyUpdate()
{
EOSSDKComponent.Tick(); EOSSDKComponent.Tick();
if (activeNode != null) { if (activeNode != null)
{
ignoreCachedMessagesTimer += Time.deltaTime; ignoreCachedMessagesTimer += Time.deltaTime;
if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds) { if (ignoreCachedMessagesTimer <= ignoreCachedMessagesAtStartUpInSeconds)
{
activeNode.ignoreAllMessages = true; activeNode.ignoreAllMessages = true;
} else { }
else
{
activeNode.ignoreAllMessages = false; activeNode.ignoreAllMessages = false;
} }
} }
if (enabled) { if (enabled)
{
activeNode?.ReceiveData(); activeNode?.ReceiveData();
} }
} }
public override void ServerLateUpdate() {} public override void ServerLateUpdate() { }
public override bool ClientConnected() => ClientActive() && client.Connected; public override bool ClientConnected() => ClientActive() && client.Connected;
public override void ClientConnect(string address) {
if (!EOSSDKComponent.Initialized) { public override void ClientConnect(string address)
{
if (!EOSSDKComponent.Initialized)
{
Debug.LogError("EOS not initialized. Client could not be started."); Debug.LogError("EOS not initialized. Client could not be started.");
OnClientDisconnected.Invoke(); OnClientDisconnected.Invoke();
return; return;
@ -116,18 +141,21 @@ namespace EpicTransport {
StartCoroutine("FetchEpicAccountId"); StartCoroutine("FetchEpicAccountId");
if (ServerActive()) { if (ServerActive())
{
Debug.LogError("Transport already running as server!"); Debug.LogError("Transport already running as server!");
return; return;
} }
if (!ClientActive() || client.Error) { if (!ClientActive() || client.Error)
{
Debug.Log($"Starting client, target address {address}."); Debug.Log($"Starting client, target address {address}.");
client = Client.CreateClient(this, address); client = Client.CreateClient(this, address);
activeNode = client; activeNode = client;
if (EOSSDKComponent.CollectPlayerMetrics) { if (EOSSDKComponent.CollectPlayerMetrics)
{
// Start Metrics colletion session // Start Metrics colletion session
BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions(); BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions();
sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId; sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
@ -137,55 +165,68 @@ namespace EpicTransport {
sessionOptions.ServerIp = null; sessionOptions.ServerIp = null;
Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions); Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions);
if(result == Result.Success) { if (result == Result.Success)
{
Debug.Log("Started Metric Session"); Debug.Log("Started Metric Session");
} }
} }
} else { }
else
{
Debug.LogError("Client already running!"); Debug.LogError("Client already running!");
} }
} }
public override void ClientConnect(Uri uri) { public override void ClientConnect(Uri uri)
{
if (uri.Scheme != EPIC_SCHEME) if (uri.Scheme != EPIC_SCHEME)
throw new ArgumentException($"Invalid url {uri}, use {EPIC_SCHEME}://EpicAccountId instead", nameof(uri)); throw new ArgumentException($"Invalid url {uri}, use {EPIC_SCHEME}://EpicAccountId instead", nameof(uri));
ClientConnect(uri.Host); ClientConnect(uri.Host);
} }
public override void ClientSend(ArraySegment<byte> segment, int channelId) { public override void ClientSend(ArraySegment<byte> segment, int channelId)
{
Send(channelId, segment); Send(channelId, segment);
} }
public override void ClientDisconnect() { public override void ClientDisconnect()
if (ClientActive()) { {
if (ClientActive())
{
Shutdown(); Shutdown();
} }
} }
public bool ClientActive() => client != null; public bool ClientActive() => client != null;
public override bool ServerActive() => server != null; public override bool ServerActive() => server != null;
public override void ServerStart() {
if (!EOSSDKComponent.Initialized) { public override void ServerStart()
{
if (!EOSSDKComponent.Initialized)
{
Debug.LogError("EOS not initialized. Server could not be started."); Debug.LogError("EOS not initialized. Server could not be started.");
return; return;
} }
StartCoroutine("FetchEpicAccountId"); StartCoroutine("FetchEpicAccountId");
if (ClientActive()) { if (ClientActive())
{
Debug.LogError("Transport already running as client!"); Debug.LogError("Transport already running as client!");
return; return;
} }
if (!ServerActive()) { if (!ServerActive())
{
Debug.Log("Starting server."); Debug.Log("Starting server.");
server = Server.CreateServer(this, NetworkManager.singleton.maxConnections); server = Server.CreateServer(this, NetworkManager.singleton.maxConnections);
activeNode = server; activeNode = server;
if (EOSSDKComponent.CollectPlayerMetrics) { if (EOSSDKComponent.CollectPlayerMetrics)
{
// Start Metrics colletion session // Start Metrics colletion session
BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions(); BeginPlayerSessionOptions sessionOptions = new BeginPlayerSessionOptions();
sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId; sessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
@ -195,17 +236,22 @@ namespace EpicTransport {
sessionOptions.ServerIp = null; sessionOptions.ServerIp = null;
Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions); Result result = EOSSDKComponent.GetMetricsInterface().BeginPlayerSession(sessionOptions);
if (result == Result.Success) { if (result == Result.Success)
{
Debug.Log("Started Metric Session"); Debug.Log("Started Metric Session");
} }
} }
} else { }
else
{
Debug.LogError("Server already started!"); Debug.LogError("Server already started!");
} }
} }
public override Uri ServerUri() { public override Uri ServerUri()
UriBuilder epicBuilder = new UriBuilder { {
UriBuilder epicBuilder = new UriBuilder
{
Scheme = EPIC_SCHEME, Scheme = EPIC_SCHEME,
Host = EOSSDKComponent.LocalUserProductIdString Host = EOSSDKComponent.LocalUserProductIdString
}; };
@ -213,26 +259,37 @@ namespace EpicTransport {
return epicBuilder.Uri; return epicBuilder.Uri;
} }
public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId) { public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId)
if (ServerActive()) { {
Send( channelId, segment, connectionId); if (ServerActive())
{
Send(channelId, segment, connectionId);
} }
} }
public override void ServerDisconnect(int connectionId) => server.Disconnect(connectionId); public override void ServerDisconnect(int connectionId) => server.Disconnect(connectionId);
public override string ServerGetClientAddress(int connectionId) => ServerActive() ? server.ServerGetClientAddress(connectionId) : string.Empty; public override string ServerGetClientAddress(int connectionId) => ServerActive() ? server.ServerGetClientAddress(connectionId) : string.Empty;
public override void ServerStop() {
if (ServerActive()) { public override void ServerStop()
{
if (ServerActive())
{
Shutdown(); Shutdown();
} }
} }
private void Send(int channelId, ArraySegment<byte> segment, int connectionId = int.MinValue) { private void Send(int channelId, ArraySegment<byte> segment, int connectionId = int.MinValue)
{
Packet[] packets = GetPacketArray(channelId, segment); Packet[] packets = GetPacketArray(channelId, segment);
for(int i = 0; i < packets.Length; i++) { for (int i = 0; i < packets.Length; i++)
if (connectionId == int.MinValue) { {
if (connectionId == int.MinValue)
{
client.Send(packets[i].ToBytes(), channelId); client.Send(packets[i].ToBytes(), channelId);
} else { }
else
{
server.SendAll(connectionId, packets[i].ToBytes(), channelId); server.SendAll(connectionId, packets[i].ToBytes(), channelId);
} }
} }
@ -240,11 +297,13 @@ namespace EpicTransport {
packetId++; packetId++;
} }
private Packet[] GetPacketArray(int channelId, ArraySegment<byte> segment) { private Packet[] GetPacketArray(int channelId, ArraySegment<byte> segment)
int packetCount = Mathf.CeilToInt((float) segment.Count / (float)GetMaxSinglePacketSize(channelId)); {
int packetCount = Mathf.CeilToInt((float)segment.Count / (float)GetMaxSinglePacketSize(channelId));
Packet[] packets = new Packet[packetCount]; Packet[] packets = new Packet[packetCount];
for (int i = 0; i < segment.Count; i += GetMaxSinglePacketSize(channelId)) { for (int i = 0; i < segment.Count; i += GetMaxSinglePacketSize(channelId))
{
int fragment = i / GetMaxSinglePacketSize(channelId); int fragment = i / GetMaxSinglePacketSize(channelId);
packets[fragment] = new Packet(); packets[fragment] = new Packet();
@ -258,14 +317,17 @@ namespace EpicTransport {
return packets; return packets;
} }
public override void Shutdown() { public override void Shutdown()
if (EOSSDKComponent.CollectPlayerMetrics) { {
if (EOSSDKComponent.CollectPlayerMetrics)
{
// Stop Metrics collection session // Stop Metrics collection session
EndPlayerSessionOptions endSessionOptions = new EndPlayerSessionOptions(); EndPlayerSessionOptions endSessionOptions = new EndPlayerSessionOptions();
endSessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId; endSessionOptions.AccountId = EOSSDKComponent.LocalUserAccountId;
Result result = EOSSDKComponent.GetMetricsInterface().EndPlayerSession(endSessionOptions); Result result = EOSSDKComponent.GetMetricsInterface().EndPlayerSession(endSessionOptions);
if (result == Result.Success) { if (result == Result.Success)
{
Debug.LogError("Stopped Metric Session"); Debug.LogError("Stopped Metric Session");
} }
} }
@ -285,24 +347,32 @@ namespace EpicTransport {
public override int GetBatchThreshold(int channelId) => P2PInterface.MaxPacketSize; // Use P2PInterface.MaxPacketSize as everything above will get fragmentated and will be counter effective to batching public override int GetBatchThreshold(int channelId) => P2PInterface.MaxPacketSize; // Use P2PInterface.MaxPacketSize as everything above will get fragmentated and will be counter effective to batching
public override bool Available() { public override bool Available()
try { {
try
{
return EOSSDKComponent.Initialized; return EOSSDKComponent.Initialized;
} catch { }
catch
{
return false; return false;
} }
} }
private IEnumerator FetchEpicAccountId() { private IEnumerator FetchEpicAccountId()
while (!EOSSDKComponent.Initialized) { {
while (!EOSSDKComponent.Initialized)
{
yield return null; yield return null;
} }
productUserId = EOSSDKComponent.LocalUserProductId; productUserId = EOSSDKComponent.LocalUserProductId;
} }
private IEnumerator ChangeRelayStatus() { private IEnumerator ChangeRelayStatus()
while (!EOSSDKComponent.Initialized) { {
while (!EOSSDKComponent.Initialized)
{
yield return null; yield return null;
} }
@ -312,12 +382,15 @@ namespace EpicTransport {
EOSSDKComponent.GetP2PInterface().SetRelayControl(setRelayControlOptions); EOSSDKComponent.GetP2PInterface().SetRelayControl(setRelayControlOptions);
} }
public void ResetIgnoreMessagesAtStartUpTimer() { public void ResetIgnoreMessagesAtStartUpTimer()
{
ignoreCachedMessagesTimer = 0; ignoreCachedMessagesTimer = 0;
} }
private void OnDestroy() { private void OnDestroy()
if (activeNode != null) { {
if (activeNode != null)
{
Shutdown(); Shutdown();
} }
} }

View File

@ -4,11 +4,14 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace EpicTransport { namespace EpicTransport
public static class Logger { {
public static class Logger
public static void EpicDebugLog(LogMessage message) { {
switch (message.Level) { public static void EpicDebugLog(LogMessage message)
{
switch (message.Level)
{
case LogLevel.Info: case LogLevel.Info:
Debug.Log($"Epic Manager: Category - {message.Category} Message - {message.Message}"); Debug.Log($"Epic Manager: Category - {message.Category} Message - {message.Message}");
break; break;

View File

@ -1,7 +1,9 @@
using System; using System;
namespace EpicTransport { namespace EpicTransport
public struct Packet { {
public struct Packet
{
public const int headerSize = sizeof(uint) + sizeof(uint) + 1; public const int headerSize = sizeof(uint) + sizeof(uint) + 1;
public int size => headerSize + data.Length; public int size => headerSize + data.Length;
@ -13,20 +15,21 @@ namespace EpicTransport {
// body // body
public byte[] data; public byte[] data;
public byte[] ToBytes() { public byte[] ToBytes()
{
byte[] array = new byte[size]; byte[] array = new byte[size];
// Copy id // Copy id
array[0] = (byte) id; array[0] = (byte)id;
array[1] = (byte) (id >> 8); array[1] = (byte)(id >> 8);
array[2] = (byte) (id >> 0x10); array[2] = (byte)(id >> 0x10);
array[3] = (byte) (id >> 0x18); array[3] = (byte)(id >> 0x18);
// Copy fragment // Copy fragment
array[4] = (byte) fragment; array[4] = (byte)fragment;
array[5] = (byte) (fragment >> 8); array[5] = (byte)(fragment >> 8);
array[6] = (byte) (fragment >> 0x10); array[6] = (byte)(fragment >> 0x10);
array[7] = (byte) (fragment >> 0x18); array[7] = (byte)(fragment >> 0x18);
array[8] = moreFragments ? (byte)1 : (byte)0; array[8] = moreFragments ? (byte)1 : (byte)0;
@ -35,7 +38,8 @@ namespace EpicTransport {
return array; return array;
} }
public void FromBytes(byte[] array) { public void FromBytes(byte[] array)
{
id = BitConverter.ToInt32(array, 0); id = BitConverter.ToInt32(array, 0);
fragment = BitConverter.ToInt32(array, 4); fragment = BitConverter.ToInt32(array, 4);
moreFragments = array[8] == 1; moreFragments = array[8] == 1;

View File

@ -1,10 +1,11 @@
using System; using System;
using System.Text; using System.Text;
public class RandomString { public class RandomString
{
// Generates a random string with a given size. // Generates a random string with a given size.
public static string Generate(int size) { public static string Generate(int size)
{
var builder = new StringBuilder(size); var builder = new StringBuilder(size);
Random random = new Random(); Random random = new Random();
@ -19,15 +20,19 @@ public class RandomString {
char offsetUpperCase = 'A'; char offsetUpperCase = 'A';
const int lettersOffset = 26; // A...Z or a..z: length=26 const int lettersOffset = 26; // A...Z or a..z: length=26
for (var i = 0; i < size; i++) { for (var i = 0; i < size; i++)
{
char offset; char offset;
if(random.Next(0,2) == 0) { if (random.Next(0, 2) == 0)
{
offset = offsetLowerCase; offset = offsetLowerCase;
} else { }
else
{
offset = offsetUpperCase; offset = offsetUpperCase;
} }
var @char = (char) random.Next(offset, offset + lettersOffset); var @char = (char)random.Next(offset, offset + lettersOffset);
builder.Append(@char); builder.Append(@char);
} }

View File

@ -4,8 +4,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace EpicTransport { namespace EpicTransport
public class Server : Common { {
public class Server : Common
{
private event Action<int> OnConnected; private event Action<int> OnConnected;
private event Action<int, byte[], int> OnReceivedData; private event Action<int, byte[], int> OnReceivedData;
private event Action<int> OnDisconnected; private event Action<int> OnDisconnected;
@ -16,7 +18,8 @@ namespace EpicTransport {
private int maxConnections; private int maxConnections;
private int nextConnectionID; private int nextConnectionID;
public static Server CreateServer(EosTransport transport, int maxConnections) { public static Server CreateServer(EosTransport transport, int maxConnections)
{
Server s = new Server(transport, maxConnections); Server s = new Server(transport, maxConnections);
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id); s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
@ -24,46 +27,56 @@ namespace EpicTransport {
s.OnReceivedData += (id, data, channel) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), channel); s.OnReceivedData += (id, data, channel) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), channel);
s.OnReceivedError += (id, exception) => transport.OnServerError.Invoke(id, exception); s.OnReceivedError += (id, exception) => transport.OnServerError.Invoke(id, exception);
if (!EOSSDKComponent.Initialized) { if (!EOSSDKComponent.Initialized)
{
Debug.LogError("EOS not initialized."); Debug.LogError("EOS not initialized.");
} }
return s; return s;
} }
private Server(EosTransport transport, int maxConnections) : base(transport) { private Server(EosTransport transport, int maxConnections) : base(transport)
{
this.maxConnections = maxConnections; this.maxConnections = maxConnections;
epicToMirrorIds = new BidirectionalDictionary<ProductUserId, int>(); epicToMirrorIds = new BidirectionalDictionary<ProductUserId, int>();
epicToSocketIds = new Dictionary<ProductUserId, SocketId>(); epicToSocketIds = new Dictionary<ProductUserId, SocketId>();
nextConnectionID = 1; nextConnectionID = 1;
} }
protected override void OnNewConnection(OnIncomingConnectionRequestInfo result) { protected override void OnNewConnection(OnIncomingConnectionRequestInfo result)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
if (deadSockets.Contains(result.SocketId.SocketName)) { if (deadSockets.Contains(result.SocketId.SocketName))
{
Debug.LogError("Received incoming connection request from dead socket"); Debug.LogError("Received incoming connection request from dead socket");
return; return;
} }
EOSSDKComponent.GetP2PInterface().AcceptConnection( EOSSDKComponent.GetP2PInterface().AcceptConnection(
new AcceptConnectionOptions() { new AcceptConnectionOptions()
{
LocalUserId = EOSSDKComponent.LocalUserProductId, LocalUserId = EOSSDKComponent.LocalUserProductId,
RemoteUserId = result.RemoteUserId, RemoteUserId = result.RemoteUserId,
SocketId = result.SocketId SocketId = result.SocketId
}); });
} }
protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId) { protected override void OnReceiveInternalData(InternalMessages type, ProductUserId clientUserId, SocketId socketId)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
switch (type) { switch (type)
{
case InternalMessages.CONNECT: case InternalMessages.CONNECT:
if (epicToMirrorIds.Count >= maxConnections) { if (epicToMirrorIds.Count >= maxConnections)
{
Debug.LogError("Reached max connections"); Debug.LogError("Reached max connections");
//CloseP2PSessionWithUser(clientUserId, socketId); //CloseP2PSessionWithUser(clientUserId, socketId);
SendInternal(clientUserId, socketId, InternalMessages.DISCONNECT); SendInternal(clientUserId, socketId, InternalMessages.DISCONNECT);
@ -82,13 +95,16 @@ namespace EpicTransport {
Debug.Log($"Client with Product User ID {clientUserIdString} connected. Assigning connection id {connectionId}"); Debug.Log($"Client with Product User ID {clientUserIdString} connected. Assigning connection id {connectionId}");
break; break;
case InternalMessages.DISCONNECT: case InternalMessages.DISCONNECT:
if (epicToMirrorIds.TryGetValue(clientUserId, out int connId)) { if (epicToMirrorIds.TryGetValue(clientUserId, out int connId))
{
OnDisconnected.Invoke(connId); OnDisconnected.Invoke(connId);
//CloseP2PSessionWithUser(clientUserId, socketId); //CloseP2PSessionWithUser(clientUserId, socketId);
epicToMirrorIds.Remove(clientUserId); epicToMirrorIds.Remove(clientUserId);
epicToSocketIds.Remove(clientUserId); epicToSocketIds.Remove(clientUserId);
Debug.Log($"Client with Product User ID {clientUserId} disconnected."); Debug.Log($"Client with Product User ID {clientUserId} disconnected.");
} else { }
else
{
OnReceivedError.Invoke(-1, new Exception("ERROR Unknown Product User ID")); OnReceivedError.Invoke(-1, new Exception("ERROR Unknown Product User ID"));
} }
@ -99,14 +115,19 @@ namespace EpicTransport {
} }
} }
protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel) { protected override void OnReceiveData(byte[] data, ProductUserId clientUserId, int channel)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }
if (epicToMirrorIds.TryGetValue(clientUserId, out int connectionId)) { if (epicToMirrorIds.TryGetValue(clientUserId, out int connectionId))
{
OnReceivedData.Invoke(connectionId, data, channel); OnReceivedData.Invoke(connectionId, data, channel);
} else { }
else
{
SocketId socketId; SocketId socketId;
epicToSocketIds.TryGetValue(clientUserId, out socketId); epicToSocketIds.TryGetValue(clientUserId, out socketId);
CloseP2PSessionWithUser(clientUserId, socketId); CloseP2PSessionWithUser(clientUserId, socketId);
@ -119,20 +140,26 @@ namespace EpicTransport {
} }
} }
public void Disconnect(int connectionId) { public void Disconnect(int connectionId)
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) { {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId))
{
SocketId socketId; SocketId socketId;
epicToSocketIds.TryGetValue(userId, out socketId); epicToSocketIds.TryGetValue(userId, out socketId);
SendInternal(userId, socketId, InternalMessages.DISCONNECT); SendInternal(userId, socketId, InternalMessages.DISCONNECT);
epicToMirrorIds.Remove(userId); epicToMirrorIds.Remove(userId);
epicToSocketIds.Remove(userId); epicToSocketIds.Remove(userId);
} else { }
else
{
Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId); Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId);
} }
} }
public void Shutdown() { public void Shutdown()
foreach (KeyValuePair<ProductUserId, int> client in epicToMirrorIds) { {
foreach (KeyValuePair<ProductUserId, int> client in epicToMirrorIds)
{
Disconnect(client.Value); Disconnect(client.Value);
SocketId socketId; SocketId socketId;
epicToSocketIds.TryGetValue(client.Key, out socketId); epicToSocketIds.TryGetValue(client.Key, out socketId);
@ -145,32 +172,41 @@ namespace EpicTransport {
Dispose(); Dispose();
} }
public void SendAll(int connectionId, byte[] data, int channelId) { public void SendAll(int connectionId, byte[] data, int channelId)
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) { {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId))
{
SocketId socketId; SocketId socketId;
epicToSocketIds.TryGetValue(userId, out socketId); epicToSocketIds.TryGetValue(userId, out socketId);
Send(userId, socketId, data, (byte)channelId); Send(userId, socketId, data, (byte)channelId);
} else { }
else
{
Debug.LogError("Trying to send on unknown connection: " + connectionId); Debug.LogError("Trying to send on unknown connection: " + connectionId);
OnReceivedError.Invoke(connectionId, new Exception("ERROR Unknown Connection")); OnReceivedError.Invoke(connectionId, new Exception("ERROR Unknown Connection"));
} }
} }
public string ServerGetClientAddress(int connectionId) { public string ServerGetClientAddress(int connectionId)
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId)) { {
if (epicToMirrorIds.TryGetValue(connectionId, out ProductUserId userId))
{
string userIdString; string userIdString;
userId.ToString(out userIdString); userId.ToString(out userIdString);
return userIdString; return userIdString;
} else { }
else
{
Debug.LogError("Trying to get info on unknown connection: " + connectionId); Debug.LogError("Trying to get info on unknown connection: " + connectionId);
OnReceivedError.Invoke(connectionId, new Exception("ERROR Unknown Connection")); OnReceivedError.Invoke(connectionId, new Exception("ERROR Unknown Connection"));
return string.Empty; return string.Empty;
} }
} }
protected override void OnConnectionFailed(ProductUserId remoteId) { protected override void OnConnectionFailed(ProductUserId remoteId)
if (ignoreAllMessages) { {
if (ignoreAllMessages)
{
return; return;
} }