mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-02-21 09:39:56 +00:00
Revert "Revert "cleanup fizzyfacepunch""
This reverts commit c049b94527a16c3ae0f04c644362cf5b3f3f114b.
This commit is contained in:
parent
c049b94527
commit
f7ed57a787
@ -3,79 +3,79 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public class BidirectionalDictionary<T1, T2> : IEnumerable
|
public class BidirectionalDictionary<T1, T2> : IEnumerable
|
||||||
{
|
{
|
||||||
private Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
|
private readonly Dictionary<T1, T2> t1ToT2Dict = new Dictionary<T1, T2>();
|
||||||
private Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
|
private readonly Dictionary<T2, T1> t2ToT1Dict = new Dictionary<T2, T1>();
|
||||||
|
|
||||||
public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
|
public IEnumerable<T1> FirstTypes => t1ToT2Dict.Keys;
|
||||||
public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
|
public IEnumerable<T2> SecondTypes => t2ToT1Dict.Keys;
|
||||||
|
|
||||||
public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
|
public IEnumerator GetEnumerator() => t1ToT2Dict.GetEnumerator();
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T2 Get(T1 key) => t1ToT2Dict[key];
|
public T2 Get(T1 key) => t1ToT2Dict[key];
|
||||||
|
|
||||||
public T1 Get(T2 key) => t2ToT1Dict[key];
|
public T1 Get(T2 key) => t2ToT1Dict[key];
|
||||||
|
|
||||||
public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
|
public bool TryGetValue(T1 key, out T2 value) => t1ToT2Dict.TryGetValue(key, out value);
|
||||||
|
|
||||||
public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
|
public bool TryGetValue(T2 key, out T1 value) => t2ToT1Dict.TryGetValue(key, out value);
|
||||||
|
|
||||||
public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
|
public bool Contains(T1 key) => t1ToT2Dict.ContainsKey(key);
|
||||||
|
|
||||||
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];
|
var val = t1ToT2Dict[key];
|
||||||
t1ToT2Dict.Remove(key);
|
t1ToT2Dict.Remove(key);
|
||||||
t2ToT1Dict.Remove(val);
|
t2ToT1Dict.Remove(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void Remove(T2 key)
|
public void Remove(T2 key)
|
||||||
{
|
{
|
||||||
if (Contains(key))
|
if (Contains(key))
|
||||||
{
|
{
|
||||||
T1 val = t2ToT1Dict[key];
|
var 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,10 +3,7 @@ using System;
|
|||||||
|
|
||||||
public class FizzyConnectionManager : ConnectionManager
|
public class FizzyConnectionManager : ConnectionManager
|
||||||
{
|
{
|
||||||
public Action<IntPtr, int> ForwardMessage;
|
public Action<IntPtr, int> ForwardMessage;
|
||||||
|
|
||||||
public override void OnMessage(IntPtr data, int size, long messageNum, long recvTime, int channel)
|
public override void OnMessage(IntPtr data, int size, long messageNum, long recvTime, int channel) => ForwardMessage(data, size);
|
||||||
{
|
|
||||||
ForwardMessage(data, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,303 +1,301 @@
|
|||||||
using Steamworks;
|
using Steamworks;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
[HelpURL("https://github.com/Chykary/FizzyFacepunch")]
|
[HelpURL("https://github.com/Chykary/FizzyFacepunch")]
|
||||||
public class FizzyFacepunch : Transport
|
public class FizzyFacepunch : Transport
|
||||||
{
|
{
|
||||||
private const string STEAM_SCHEME = "steam";
|
private const string STEAM_SCHEME = "steam";
|
||||||
|
|
||||||
private static IClient client;
|
private static IClient client;
|
||||||
private static IServer server;
|
private static IServer server;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
public P2PSend[] Channels = new P2PSend[2] { P2PSend.Reliable, P2PSend.UnreliableNoDelay };
|
public P2PSend[] Channels = new P2PSend[2] { P2PSend.Reliable, P2PSend.UnreliableNoDelay };
|
||||||
|
|
||||||
[Tooltip("Timeout for connecting in seconds.")]
|
[Tooltip("Timeout for connecting in seconds.")]
|
||||||
public int Timeout = 25;
|
public int Timeout = 25;
|
||||||
[Tooltip("The Steam ID for your application.")]
|
[Tooltip("The Steam ID for your application.")]
|
||||||
public string SteamAppID = "480";
|
public string SteamAppID = "480";
|
||||||
[Tooltip("Allow or disallow P2P connections to fall back to being relayed through the Steam servers if a direct connection or NAT-traversal cannot be established.")]
|
[Tooltip("Allow or disallow P2P connections to fall back to being relayed through the Steam servers if a direct connection or NAT-traversal cannot be established.")]
|
||||||
public bool AllowSteamRelay = true;
|
public bool AllowSteamRelay = true;
|
||||||
|
|
||||||
[Tooltip("Use SteamSockets instead of the (deprecated) SteamNetworking. This will always use Relay.")]
|
[Tooltip("Use SteamSockets instead of the (deprecated) SteamNetworking. This will always use Relay.")]
|
||||||
public bool UseNextGenSteamNetworking = true;
|
public bool UseNextGenSteamNetworking = true;
|
||||||
|
|
||||||
[Tooltip("Check this if you want the transport to initialise Facepunch.")]
|
[Tooltip("Check this if you want the transport to initialise Facepunch.")]
|
||||||
public bool InitFacepunch = true;
|
public bool InitFacepunch = true;
|
||||||
|
|
||||||
[Header("Info")]
|
[Header("Info")]
|
||||||
[Tooltip("This will display your Steam User ID when you start or connect to a server.")]
|
[Tooltip("This will display your Steam User ID when you start or connect to a server.")]
|
||||||
public ulong SteamUserID;
|
public ulong SteamUserID;
|
||||||
|
|
||||||
public Action<string> SetTransportError;
|
public Action<string> SetTransportError;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
const string fileName = "steam_appid.txt";
|
const string fileName = "steam_appid.txt";
|
||||||
if (File.Exists(fileName))
|
if (File.Exists(fileName))
|
||||||
{
|
{
|
||||||
string content = File.ReadAllText(fileName);
|
var content = File.ReadAllText(fileName);
|
||||||
if (content != SteamAppID)
|
if (content != SteamAppID)
|
||||||
{
|
{
|
||||||
File.WriteAllText(fileName, SteamAppID.ToString());
|
File.WriteAllText(fileName, SteamAppID.ToString());
|
||||||
Debug.Log($"Updating {fileName}. Previous: {content}, new SteamAppID {SteamAppID}");
|
Debug.Log($"Updating {fileName}. Previous: {content}, new SteamAppID {SteamAppID}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
File.WriteAllText(fileName, SteamAppID.ToString());
|
File.WriteAllText(fileName, SteamAppID.ToString());
|
||||||
Debug.Log($"New {fileName} written with SteamAppID {SteamAppID}");
|
Debug.Log($"New {fileName} written with SteamAppID {SteamAppID}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for FizzySteamworks.");
|
Debug.Assert(Channels != null && Channels.Length > 0, "No channel configured for FizzySteamworks.");
|
||||||
|
|
||||||
if (InitFacepunch)
|
if (InitFacepunch)
|
||||||
{
|
{
|
||||||
SteamClient.Init(uint.Parse(SteamAppID), true);
|
SteamClient.Init(uint.Parse(SteamAppID), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoke(nameof(FetchSteamID), 1f);
|
Invoke(nameof(FetchSteamID), 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientEarlyUpdate()
|
public override void ClientEarlyUpdate()
|
||||||
{
|
{
|
||||||
if (enabled && client != null && !client.Error)
|
if (enabled && client != null && !client.Error)
|
||||||
{
|
{
|
||||||
client?.ReceiveData();
|
client?.ReceiveData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ServerEarlyUpdate()
|
public override void ServerEarlyUpdate()
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
server?.ReceiveData();
|
server?.ReceiveData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientLateUpdate()
|
public override void ClientLateUpdate()
|
||||||
{
|
{
|
||||||
if (enabled && client != null && !client.Error)
|
if (enabled && client != null && !client.Error)
|
||||||
{
|
{
|
||||||
client?.FlushData();
|
client?.FlushData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ServerLateUpdate()
|
public override void ServerLateUpdate()
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
server?.FlushData();
|
server?.FlushData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool ClientConnected() => ClientActive() && client.Connected;
|
public override bool ClientConnected() => ClientActive() && client.Connected;
|
||||||
public override void ClientConnect(string address)
|
public override void ClientConnect(string address)
|
||||||
{
|
{
|
||||||
if (!SteamClient.IsValid)
|
if (!SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
Debug.LogError("SteamWorks not initialized. Client could not be started.");
|
Debug.LogError("SteamWorks not initialized. Client could not be started.");
|
||||||
OnClientDisconnected.Invoke();
|
OnClientDisconnected.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchSteamID();
|
FetchSteamID();
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (UseNextGenSteamNetworking)
|
if (UseNextGenSteamNetworking)
|
||||||
{
|
{
|
||||||
Debug.Log($"Starting client [SteamSockets], target address {address}.");
|
Debug.Log($"Starting client [SteamSockets], target address {address}.");
|
||||||
client = NextClient.CreateClient(this, address);
|
client = NextClient.CreateClient(this, address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"Starting client [DEPRECATED SteamNetworking], target address {address}. Relay enabled: {AllowSteamRelay}");
|
Debug.Log($"Starting client [DEPRECATED SteamNetworking], target address {address}. Relay enabled: {AllowSteamRelay}");
|
||||||
SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay);
|
SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay);
|
||||||
client = LegacyClient.CreateClient(this, address);
|
client = LegacyClient.CreateClient(this, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 != STEAM_SCHEME)
|
if (uri.Scheme != STEAM_SCHEME)
|
||||||
throw new ArgumentException($"Invalid url {uri}, use {STEAM_SCHEME}://SteamID instead", nameof(uri));
|
{
|
||||||
|
throw new ArgumentException($"Invalid url {uri}, use {STEAM_SCHEME}://SteamID 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)
|
||||||
{
|
{
|
||||||
byte[] data = new byte[segment.Count];
|
var data = new byte[segment.Count];
|
||||||
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
|
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
|
||||||
client.Send(data, channelId);
|
client.Send(data, channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
public override void ServerStart()
|
||||||
{
|
{
|
||||||
if (!SteamClient.IsValid)
|
if (!SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
Debug.LogError("SteamWorks not initialized. Server could not be started.");
|
Debug.LogError("SteamWorks not initialized. Server could not be started.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchSteamID();
|
FetchSteamID();
|
||||||
|
|
||||||
if (ClientActive())
|
if (ClientActive())
|
||||||
{
|
{
|
||||||
Debug.LogError("Transport already running as client!");
|
Debug.LogError("Transport already running as client!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ServerActive())
|
if (!ServerActive())
|
||||||
{
|
{
|
||||||
if (UseNextGenSteamNetworking)
|
if (UseNextGenSteamNetworking)
|
||||||
{
|
{
|
||||||
Debug.Log($"Starting server [SteamSockets].");
|
Debug.Log($"Starting server [SteamSockets].");
|
||||||
server = NextServer.CreateServer(this, NetworkManager.singleton.maxConnections);
|
server = NextServer.CreateServer(this, NetworkManager.singleton.maxConnections);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.Log($"Starting server [DEPRECATED SteamNetworking]. Relay enabled: {AllowSteamRelay}");
|
Debug.Log($"Starting server [DEPRECATED SteamNetworking]. Relay enabled: {AllowSteamRelay}");
|
||||||
SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay);
|
SteamNetworking.AllowP2PPacketRelay(AllowSteamRelay);
|
||||||
server = LegacyServer.CreateServer(this, NetworkManager.singleton.maxConnections);
|
server = LegacyServer.CreateServer(this, NetworkManager.singleton.maxConnections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError("Server already started!");
|
Debug.LogError("Server already started!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Uri ServerUri()
|
public override Uri ServerUri()
|
||||||
{
|
{
|
||||||
var steamBuilder = new UriBuilder
|
var steamBuilder = new UriBuilder
|
||||||
{
|
{
|
||||||
Scheme = STEAM_SCHEME,
|
Scheme = STEAM_SCHEME,
|
||||||
Host = SteamClient.SteamId.Value.ToString()
|
Host = SteamClient.SteamId.Value.ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
return steamBuilder.Uri;
|
return steamBuilder.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())
|
if (ServerActive())
|
||||||
{
|
{
|
||||||
byte[] data = new byte[segment.Count];
|
var data = new byte[segment.Count];
|
||||||
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
|
Array.Copy(segment.Array, segment.Offset, data, 0, segment.Count);
|
||||||
server.Send(connectionId, data, channelId);
|
server.Send(connectionId, data, channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override void ServerDisconnect(int connectionId)
|
public override void ServerDisconnect(int connectionId)
|
||||||
{
|
{
|
||||||
if (ServerActive())
|
if (ServerActive())
|
||||||
{
|
{
|
||||||
server.Disconnect(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()
|
public override void ServerStop()
|
||||||
{
|
{
|
||||||
if (ServerActive())
|
if (ServerActive())
|
||||||
{
|
{
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
if (server != null)
|
if (server != null)
|
||||||
{
|
{
|
||||||
server.Shutdown();
|
server.Shutdown();
|
||||||
server = null;
|
server = null;
|
||||||
Debug.Log("Transport shut down - was server.");
|
Debug.Log("Transport shut down - was server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
client.Disconnect();
|
client.Disconnect();
|
||||||
client = null;
|
client = null;
|
||||||
Debug.Log("Transport shut down - was client.");
|
Debug.Log("Transport shut down - was client.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetMaxPacketSize(int channelId)
|
public override int GetMaxPacketSize(int channelId)
|
||||||
{
|
{
|
||||||
if (channelId >= Channels.Length)
|
if (channelId >= Channels.Length)
|
||||||
{
|
{
|
||||||
Debug.LogError("Channel Id exceeded configured channels! Please configure more channels.");
|
Debug.LogError("Channel Id exceeded configured channels! Please configure more channels.");
|
||||||
return 1200;
|
return 1200;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Channels[channelId])
|
switch (Channels[channelId])
|
||||||
{
|
{
|
||||||
case P2PSend.Unreliable:
|
case P2PSend.Unreliable:
|
||||||
case P2PSend.UnreliableNoDelay:
|
case P2PSend.UnreliableNoDelay:
|
||||||
return 1200;
|
return 1200;
|
||||||
case P2PSend.Reliable:
|
case P2PSend.Reliable:
|
||||||
case P2PSend.ReliableWithBuffering:
|
case P2PSend.ReliableWithBuffering:
|
||||||
return 1048576;
|
return 1048576;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Available()
|
public override bool Available()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return SteamClient.IsValid;
|
return SteamClient.IsValid;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FetchSteamID()
|
private void FetchSteamID()
|
||||||
{
|
{
|
||||||
if (SteamClient.IsValid)
|
if (SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
if (UseNextGenSteamNetworking)
|
if (UseNextGenSteamNetworking)
|
||||||
{
|
{
|
||||||
SteamNetworkingUtils.InitRelayNetworkAccess();
|
SteamNetworkingUtils.InitRelayNetworkAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamUserID = SteamClient.SteamId;
|
SteamUserID = SteamClient.SteamId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy() => Shutdown();
|
||||||
{
|
}
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,10 +4,7 @@ using System;
|
|||||||
|
|
||||||
public class FizzySocketManager : SocketManager
|
public class FizzySocketManager : SocketManager
|
||||||
{
|
{
|
||||||
public Action<Connection, IntPtr, int> ForwardMessage;
|
public Action<Connection, IntPtr, int> ForwardMessage;
|
||||||
|
|
||||||
public override void OnMessage(Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel)
|
public override void OnMessage(Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel) => ForwardMessage(connection, data, size);
|
||||||
{
|
|
||||||
ForwardMessage(connection, data, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public interface IClient
|
public interface IClient
|
||||||
{
|
{
|
||||||
bool Connected { get; }
|
bool Connected { get; }
|
||||||
bool Error { get; }
|
bool Error { get; }
|
||||||
void ReceiveData();
|
void ReceiveData();
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
void FlushData();
|
void FlushData();
|
||||||
void Send(byte[] data, int channelId);
|
void Send(byte[] data, int channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,12 @@
|
|||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public interface IServer
|
public interface IServer
|
||||||
{
|
{
|
||||||
void ReceiveData();
|
void ReceiveData();
|
||||||
void Send(int connectionId, byte[] data, int channelId);
|
void Send(int connectionId, byte[] data, int channelId);
|
||||||
void Disconnect(int connectionId);
|
void Disconnect(int connectionId);
|
||||||
void FlushData();
|
void FlushData();
|
||||||
string ServerGetClientAddress(int connectionId);
|
string ServerGetClientAddress(int connectionId);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,159 +6,156 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public class LegacyClient : LegacyCommon, IClient
|
public class LegacyClient : LegacyCommon, IClient
|
||||||
{
|
{
|
||||||
public bool Error { get; private set; }
|
public bool Error { get; private set; }
|
||||||
public bool Connected { get; private set; }
|
public bool Connected { get; private set; }
|
||||||
|
|
||||||
private event Action<byte[], int> OnReceivedData;
|
private event Action<byte[], int> OnReceivedData;
|
||||||
private event Action OnConnected;
|
private event Action OnConnected;
|
||||||
private event Action OnDisconnected;
|
private event Action OnDisconnected;
|
||||||
|
|
||||||
private TimeSpan ConnectionTimeout;
|
private TimeSpan ConnectionTimeout;
|
||||||
|
|
||||||
private SteamId hostSteamID = 0;
|
private SteamId hostSteamID = 0;
|
||||||
private TaskCompletionSource<Task> connectedComplete;
|
private TaskCompletionSource<Task> connectedComplete;
|
||||||
private CancellationTokenSource cancelToken;
|
private CancellationTokenSource cancelToken;
|
||||||
|
|
||||||
private LegacyClient(FizzyFacepunch transport) : base(transport)
|
private LegacyClient(FizzyFacepunch transport) : base(transport) => ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout));
|
||||||
{
|
|
||||||
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LegacyClient CreateClient(FizzyFacepunch transport, string host)
|
public static LegacyClient CreateClient(FizzyFacepunch transport, string host)
|
||||||
{
|
{
|
||||||
LegacyClient c = new LegacyClient(transport);
|
var c = new LegacyClient(transport);
|
||||||
|
|
||||||
c.OnConnected += () => transport.OnClientConnected.Invoke();
|
c.OnConnected += () => transport.OnClientConnected.Invoke();
|
||||||
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
|
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
|
||||||
c.OnReceivedData += (data, channel) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), channel);
|
c.OnReceivedData += (data, channel) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), channel);
|
||||||
|
|
||||||
if (SteamClient.IsValid)
|
if (SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
c.Connect(host);
|
c.Connect(host);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError("SteamWorks not initialized.");
|
Debug.LogError("SteamWorks not initialized.");
|
||||||
c.OnConnectionFailed(new SteamId());
|
c.OnConnectionFailed(new SteamId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Connect(string host)
|
private async void Connect(string host)
|
||||||
{
|
{
|
||||||
cancelToken = new CancellationTokenSource();
|
cancelToken = new CancellationTokenSource();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hostSteamID = ulong.Parse(host);
|
hostSteamID = ulong.Parse(host);
|
||||||
connectedComplete = new TaskCompletionSource<Task>();
|
connectedComplete = new TaskCompletionSource<Task>();
|
||||||
|
|
||||||
OnConnected += SetConnectedComplete;
|
OnConnected += SetConnectedComplete;
|
||||||
SendInternal(hostSteamID, InternalMessages.CONNECT);
|
SendInternal(hostSteamID, InternalMessages.CONNECT);
|
||||||
Task connectedCompleteTask = connectedComplete.Task;
|
Task connectedCompleteTask = connectedComplete.Task;
|
||||||
Task timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token);
|
var timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token);
|
||||||
|
|
||||||
if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask)
|
if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask)
|
||||||
{
|
{
|
||||||
if (cancelToken.IsCancellationRequested)
|
if (cancelToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Debug.LogError($"The connection attempt was cancelled.");
|
Debug.LogError($"The connection attempt was cancelled.");
|
||||||
}
|
}
|
||||||
else if (timeOutTask.IsCompleted)
|
else if (timeOutTask.IsCompleted)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection to {host} timed out.");
|
Debug.LogError($"Connection to {host} timed out.");
|
||||||
}
|
}
|
||||||
OnConnected -= SetConnectedComplete;
|
OnConnected -= SetConnectedComplete;
|
||||||
Debug.LogError("Connection timed out.");
|
Debug.LogError("Connection timed out.");
|
||||||
OnConnectionFailed(hostSteamID);
|
OnConnectionFailed(hostSteamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnConnected -= SetConnectedComplete;
|
OnConnected -= SetConnectedComplete;
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?");
|
Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?");
|
||||||
Error = true;
|
Error = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError(ex.Message);
|
Debug.LogError(ex.Message);
|
||||||
Error = true;
|
Error = true;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Error)
|
if (Error)
|
||||||
{
|
{
|
||||||
OnConnectionFailed(new SteamId());
|
OnConnectionFailed(new SteamId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
Debug.LogError("Sending Disconnect message");
|
Debug.LogError("Sending Disconnect message");
|
||||||
SendInternal(hostSteamID, InternalMessages.DISCONNECT);
|
SendInternal(hostSteamID, InternalMessages.DISCONNECT);
|
||||||
Dispose();
|
Dispose();
|
||||||
cancelToken?.Cancel();
|
cancelToken?.Cancel();
|
||||||
|
|
||||||
WaitForClose(hostSteamID);
|
WaitForClose(hostSteamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
|
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
|
||||||
|
|
||||||
protected override void OnReceiveData(byte[] data, SteamId clientSteamID, int channel)
|
protected override void OnReceiveData(byte[] data, SteamId clientSteamID, int channel)
|
||||||
{
|
{
|
||||||
if (clientSteamID != hostSteamID)
|
if (clientSteamID != hostSteamID)
|
||||||
{
|
{
|
||||||
Debug.LogError("Received a message from an unknown");
|
Debug.LogError("Received a message from an unknown");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnReceivedData.Invoke(data, channel);
|
OnReceivedData.Invoke(data, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewConnection(SteamId id)
|
protected override void OnNewConnection(SteamId id)
|
||||||
{
|
{
|
||||||
if (hostSteamID == id)
|
if (hostSteamID == id)
|
||||||
{
|
{
|
||||||
SteamNetworking.AcceptP2PSessionWithUser(id);
|
SteamNetworking.AcceptP2PSessionWithUser(id);
|
||||||
}
|
}
|
||||||
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, SteamId clientSteamID)
|
protected override void OnReceiveInternalData(InternalMessages type, SteamId clientSteamID)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case InternalMessages.ACCEPT_CONNECT:
|
case InternalMessages.ACCEPT_CONNECT:
|
||||||
if (!Connected)
|
if (!Connected)
|
||||||
{
|
{
|
||||||
Connected = true;
|
Connected = true;
|
||||||
Debug.LogError("Connection established.");
|
Debug.LogError("Connection established.");
|
||||||
OnConnected.Invoke();
|
OnConnected.Invoke();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InternalMessages.DISCONNECT:
|
case InternalMessages.DISCONNECT:
|
||||||
if (Connected)
|
if (Connected)
|
||||||
{
|
{
|
||||||
Connected = false;
|
Connected = false;
|
||||||
Debug.LogError("Disconnected.");
|
Debug.LogError("Disconnected.");
|
||||||
OnDisconnected.Invoke();
|
OnDisconnected.Invoke();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.LogError("Received unknown message type");
|
Debug.LogError("Received unknown message type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Send(byte[] data, int channelId) => Send(hostSteamID, data, channelId);
|
public void Send(byte[] data, int channelId) => Send(hostSteamID, data, channelId);
|
||||||
protected override void OnConnectionFailed(SteamId remoteId) => OnDisconnected.Invoke();
|
protected override void OnConnectionFailed(SteamId remoteId) => OnDisconnected.Invoke();
|
||||||
public void FlushData() { }
|
public void FlushData() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,121 +5,121 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public abstract class LegacyCommon
|
public abstract class LegacyCommon
|
||||||
{
|
{
|
||||||
private P2PSend[] channels;
|
private readonly P2PSend[] 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 readonly FizzyFacepunch transport;
|
protected readonly FizzyFacepunch transport;
|
||||||
|
|
||||||
protected LegacyCommon(FizzyFacepunch transport)
|
protected LegacyCommon(FizzyFacepunch transport)
|
||||||
{
|
{
|
||||||
channels = transport.Channels;
|
channels = transport.Channels;
|
||||||
|
|
||||||
SteamNetworking.OnP2PSessionRequest += OnNewConnection;
|
SteamNetworking.OnP2PSessionRequest += OnNewConnection;
|
||||||
SteamNetworking.OnP2PConnectionFailed += OnConnectFail;
|
SteamNetworking.OnP2PConnectionFailed += OnConnectFail;
|
||||||
|
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void WaitForClose(SteamId cSteamID) => transport.StartCoroutine(DelayedClose(cSteamID));
|
protected void WaitForClose(SteamId cSteamID) => transport.StartCoroutine(DelayedClose(cSteamID));
|
||||||
private IEnumerator DelayedClose(SteamId cSteamID)
|
private IEnumerator DelayedClose(SteamId cSteamID)
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
CloseP2PSessionWithUser(cSteamID);
|
CloseP2PSessionWithUser(cSteamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Dispose()
|
protected void Dispose()
|
||||||
{
|
{
|
||||||
SteamNetworking.OnP2PSessionRequest -= OnNewConnection;
|
SteamNetworking.OnP2PSessionRequest -= OnNewConnection;
|
||||||
SteamNetworking.OnP2PConnectionFailed -= OnConnectFail;
|
SteamNetworking.OnP2PConnectionFailed -= OnConnectFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void OnNewConnection(SteamId steamID);
|
protected abstract void OnNewConnection(SteamId steamID);
|
||||||
|
|
||||||
private void OnConnectFail(SteamId id, P2PSessionError err)
|
private void OnConnectFail(SteamId id, P2PSessionError err)
|
||||||
{
|
{
|
||||||
OnConnectionFailed(id);
|
OnConnectionFailed(id);
|
||||||
CloseP2PSessionWithUser(id);
|
CloseP2PSessionWithUser(id);
|
||||||
|
|
||||||
switch (err)
|
switch (err)
|
||||||
{
|
{
|
||||||
case P2PSessionError.NotRunningApp:
|
case P2PSessionError.NotRunningApp:
|
||||||
throw new Exception("Connection failed: The target user is not running the same game.");
|
throw new Exception("Connection failed: The target user is not running the same game.");
|
||||||
case P2PSessionError.NoRightsToApp:
|
case P2PSessionError.NoRightsToApp:
|
||||||
throw new Exception("Connection failed: The local user doesn't own the app that is running.");
|
throw new Exception("Connection failed: The local user doesn't own the app that is running.");
|
||||||
case P2PSessionError.DestinationNotLoggedIn:
|
case P2PSessionError.DestinationNotLoggedIn:
|
||||||
throw new Exception("Connection failed: Target user isn't connected to Steam.");
|
throw new Exception("Connection failed: Target user isn't connected to Steam.");
|
||||||
case P2PSessionError.Timeout:
|
case P2PSessionError.Timeout:
|
||||||
throw new Exception("Connection failed: The connection timed out because the target user didn't respond.");
|
throw new Exception("Connection failed: The connection timed out because the target user didn't respond.");
|
||||||
default:
|
default:
|
||||||
throw new Exception("Connection failed: Unknown error.");
|
throw new Exception("Connection failed: Unknown error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool SendInternal(SteamId target, InternalMessages type) => SteamNetworking.SendP2PPacket(target, new byte[] { (byte)type }, 1, internal_ch);
|
protected bool SendInternal(SteamId target, InternalMessages type) => SteamNetworking.SendP2PPacket(target, new byte[] { (byte)type }, 1, internal_ch);
|
||||||
protected void Send(SteamId host, byte[] msgBuffer, int channel) => SteamNetworking.SendP2PPacket(host, msgBuffer, msgBuffer.Length, channel, channels[Mathf.Min(channel, channels.Length - 1)]);
|
protected void Send(SteamId host, byte[] msgBuffer, int channel) => SteamNetworking.SendP2PPacket(host, msgBuffer, msgBuffer.Length, channel, channels[Mathf.Min(channel, channels.Length - 1)]);
|
||||||
private bool Receive(out SteamId clientSteamID, out byte[] receiveBuffer, int channel)
|
private bool Receive(out SteamId clientSteamID, out byte[] receiveBuffer, int channel)
|
||||||
{
|
{
|
||||||
if (SteamNetworking.IsP2PPacketAvailable(channel))
|
if (SteamNetworking.IsP2PPacketAvailable(channel))
|
||||||
{
|
{
|
||||||
var data = SteamNetworking.ReadP2PPacket(channel);
|
var data = SteamNetworking.ReadP2PPacket(channel);
|
||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
receiveBuffer = data.Value.Data;
|
receiveBuffer = data.Value.Data;
|
||||||
clientSteamID = data.Value.SteamId;
|
clientSteamID = data.Value.SteamId;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveBuffer = null;
|
receiveBuffer = null;
|
||||||
clientSteamID = 0;
|
clientSteamID = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void CloseP2PSessionWithUser(SteamId clientSteamID) => SteamNetworking.CloseP2PSessionWithUser(clientSteamID);
|
protected void CloseP2PSessionWithUser(SteamId clientSteamID) => SteamNetworking.CloseP2PSessionWithUser(clientSteamID);
|
||||||
|
|
||||||
public void ReceiveData()
|
public void ReceiveData()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (transport.enabled && Receive(out SteamId clientSteamID, out byte[] internalMessage, internal_ch))
|
while (transport.enabled && Receive(out var clientSteamID, out var internalMessage, internal_ch))
|
||||||
{
|
{
|
||||||
if (internalMessage.Length == 1)
|
if (internalMessage.Length == 1)
|
||||||
{
|
{
|
||||||
OnReceiveInternalData((InternalMessages)internalMessage[0], clientSteamID);
|
OnReceiveInternalData((InternalMessages)internalMessage[0], clientSteamID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError("Incorrect package length on internal channel.");
|
Debug.LogError("Incorrect package length on internal channel.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int chNum = 0; chNum < channels.Length; chNum++)
|
for (var chNum = 0; chNum < channels.Length; chNum++)
|
||||||
{
|
{
|
||||||
while (transport.enabled && Receive(out SteamId clientSteamID, out byte[] receiveBuffer, chNum))
|
while (transport.enabled && Receive(out var clientSteamID, out var receiveBuffer, chNum))
|
||||||
{
|
{
|
||||||
OnReceiveData(receiveBuffer, clientSteamID, chNum);
|
OnReceiveData(receiveBuffer, clientSteamID, chNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogException(e);
|
Debug.LogException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void OnReceiveInternalData(InternalMessages type, SteamId clientSteamID);
|
protected abstract void OnReceiveInternalData(InternalMessages type, SteamId clientSteamID);
|
||||||
protected abstract void OnReceiveData(byte[] data, SteamId clientSteamID, int channel);
|
protected abstract void OnReceiveData(byte[] data, SteamId clientSteamID, int channel);
|
||||||
protected abstract void OnConnectionFailed(SteamId remoteId);
|
protected abstract void OnConnectionFailed(SteamId remoteId);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,160 +5,160 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public class LegacyServer : LegacyCommon, IServer
|
public class LegacyServer : LegacyCommon, IServer
|
||||||
{
|
{
|
||||||
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;
|
||||||
private event Action<int, Exception> OnReceivedError;
|
private event Action<int, Exception> OnReceivedError;
|
||||||
|
|
||||||
private BidirectionalDictionary<SteamId, int> steamToMirrorIds;
|
private readonly BidirectionalDictionary<SteamId, int> steamToMirrorIds;
|
||||||
private int maxConnections;
|
private readonly int maxConnections;
|
||||||
private int nextConnectionID;
|
private int nextConnectionID;
|
||||||
|
|
||||||
public static LegacyServer CreateServer(FizzyFacepunch transport, int maxConnections)
|
public static LegacyServer CreateServer(FizzyFacepunch transport, int maxConnections)
|
||||||
{
|
{
|
||||||
LegacyServer s = new LegacyServer(transport, maxConnections);
|
var s = new LegacyServer(transport, maxConnections);
|
||||||
|
|
||||||
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
|
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
|
||||||
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
|
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
|
||||||
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);
|
||||||
|
|
||||||
SteamNetworking.OnP2PSessionRequest = (steamid) =>
|
SteamNetworking.OnP2PSessionRequest = (steamid) =>
|
||||||
{
|
{
|
||||||
Debug.LogError($"Incoming request from SteamId {steamid}.");
|
Debug.LogError($"Incoming request from SteamId {steamid}.");
|
||||||
SteamNetworking.AcceptP2PSessionWithUser(steamid);
|
SteamNetworking.AcceptP2PSessionWithUser(steamid);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!SteamClient.IsValid)
|
if (!SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
Debug.LogError("SteamWorks not initialized.");
|
Debug.LogError("SteamWorks not initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LegacyServer(FizzyFacepunch transport, int maxConnections) : base(transport)
|
private LegacyServer(FizzyFacepunch transport, int maxConnections) : base(transport)
|
||||||
{
|
{
|
||||||
this.maxConnections = maxConnections;
|
this.maxConnections = maxConnections;
|
||||||
steamToMirrorIds = new BidirectionalDictionary<SteamId, int>();
|
steamToMirrorIds = new BidirectionalDictionary<SteamId, int>();
|
||||||
nextConnectionID = 1;
|
nextConnectionID = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewConnection(SteamId id) => SteamNetworking.AcceptP2PSessionWithUser(id);
|
protected override void OnNewConnection(SteamId id) => SteamNetworking.AcceptP2PSessionWithUser(id);
|
||||||
|
|
||||||
protected override void OnReceiveInternalData(InternalMessages type, SteamId clientSteamID)
|
protected override void OnReceiveInternalData(InternalMessages type, SteamId clientSteamID)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case InternalMessages.CONNECT:
|
case InternalMessages.CONNECT:
|
||||||
if (steamToMirrorIds.Count >= maxConnections)
|
if (steamToMirrorIds.Count >= maxConnections)
|
||||||
{
|
{
|
||||||
SendInternal(clientSteamID, InternalMessages.DISCONNECT);
|
SendInternal(clientSteamID, InternalMessages.DISCONNECT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendInternal(clientSteamID, InternalMessages.ACCEPT_CONNECT);
|
SendInternal(clientSteamID, InternalMessages.ACCEPT_CONNECT);
|
||||||
|
|
||||||
int connectionId = nextConnectionID++;
|
var connectionId = nextConnectionID++;
|
||||||
steamToMirrorIds.Add(clientSteamID, connectionId);
|
steamToMirrorIds.Add(clientSteamID, connectionId);
|
||||||
OnConnected.Invoke(connectionId);
|
OnConnected.Invoke(connectionId);
|
||||||
Debug.LogError($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}");
|
Debug.LogError($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}");
|
||||||
break;
|
break;
|
||||||
case InternalMessages.DISCONNECT:
|
case InternalMessages.DISCONNECT:
|
||||||
if (steamToMirrorIds.TryGetValue(clientSteamID, out int connId))
|
if (steamToMirrorIds.TryGetValue(clientSteamID, out var connId))
|
||||||
{
|
{
|
||||||
OnDisconnected.Invoke(connId);
|
OnDisconnected.Invoke(connId);
|
||||||
CloseP2PSessionWithUser(clientSteamID);
|
CloseP2PSessionWithUser(clientSteamID);
|
||||||
steamToMirrorIds.Remove(clientSteamID);
|
steamToMirrorIds.Remove(clientSteamID);
|
||||||
Debug.LogError($"Client with SteamID {clientSteamID} disconnected.");
|
Debug.LogError($"Client with SteamID {clientSteamID} disconnected.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OnReceivedError.Invoke(-1, new Exception("ERROR Unknown SteamID while receiving disconnect message."));
|
OnReceivedError.Invoke(-1, new Exception("ERROR Unknown SteamID while receiving disconnect message."));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.LogError("Received unknown message type");
|
Debug.LogError("Received unknown message type");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnReceiveData(byte[] data, SteamId clientSteamID, int channel)
|
protected override void OnReceiveData(byte[] data, SteamId clientSteamID, int channel)
|
||||||
{
|
{
|
||||||
if (steamToMirrorIds.TryGetValue(clientSteamID, out int connectionId))
|
if (steamToMirrorIds.TryGetValue(clientSteamID, out var connectionId))
|
||||||
{
|
{
|
||||||
OnReceivedData.Invoke(connectionId, data, channel);
|
OnReceivedData.Invoke(connectionId, data, channel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CloseP2PSessionWithUser(clientSteamID);
|
CloseP2PSessionWithUser(clientSteamID);
|
||||||
Debug.LogError("Data received from steam client thats not known " + clientSteamID);
|
Debug.LogError("Data received from steam client thats not known " + clientSteamID);
|
||||||
OnReceivedError.Invoke(-1, new Exception("ERROR Unknown SteamID"));
|
OnReceivedError.Invoke(-1, new Exception("ERROR Unknown SteamID"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect(int connectionId)
|
public void Disconnect(int connectionId)
|
||||||
{
|
{
|
||||||
if (steamToMirrorIds.TryGetValue(connectionId, out SteamId steamID))
|
if (steamToMirrorIds.TryGetValue(connectionId, out var steamID))
|
||||||
{
|
{
|
||||||
SendInternal(steamID, InternalMessages.DISCONNECT);
|
SendInternal(steamID, InternalMessages.DISCONNECT);
|
||||||
steamToMirrorIds.Remove(connectionId);
|
steamToMirrorIds.Remove(connectionId);
|
||||||
}
|
}
|
||||||
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<SteamId, int> client in steamToMirrorIds)
|
foreach (KeyValuePair<SteamId, int> client in steamToMirrorIds)
|
||||||
{
|
{
|
||||||
Disconnect(client.Value);
|
Disconnect(client.Value);
|
||||||
WaitForClose(client.Key);
|
WaitForClose(client.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamNetworking.OnP2PSessionRequest = null;
|
SteamNetworking.OnP2PSessionRequest = null;
|
||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Send(int connectionId, byte[] data, int channelId)
|
public void Send(int connectionId, byte[] data, int channelId)
|
||||||
{
|
{
|
||||||
if (steamToMirrorIds.TryGetValue(connectionId, out SteamId steamId))
|
if (steamToMirrorIds.TryGetValue(connectionId, out var steamId))
|
||||||
{
|
{
|
||||||
Send(steamId, data, channelId);
|
Send(steamId, data, 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 (steamToMirrorIds.TryGetValue(connectionId, out SteamId steamId))
|
if (steamToMirrorIds.TryGetValue(connectionId, out var steamId))
|
||||||
{
|
{
|
||||||
return steamId.ToString();
|
return steamId.ToString();
|
||||||
}
|
}
|
||||||
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(SteamId remoteId)
|
protected override void OnConnectionFailed(SteamId remoteId)
|
||||||
{
|
{
|
||||||
int connectionId = steamToMirrorIds.TryGetValue(remoteId, out int connId) ? connId : nextConnectionID++;
|
var connectionId = steamToMirrorIds.TryGetValue(remoteId, out var connId) ? connId : nextConnectionID++;
|
||||||
OnDisconnected.Invoke(connectionId);
|
OnDisconnected.Invoke(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushData() { }
|
public void FlushData() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,192 +8,186 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public class NextClient : NextCommon, IClient
|
public class NextClient : NextCommon, IClient
|
||||||
{
|
{
|
||||||
public bool Connected { get; private set; }
|
public bool Connected { get; private set; }
|
||||||
public bool Error { get; private set; }
|
public bool Error { get; private set; }
|
||||||
|
|
||||||
private TimeSpan ConnectionTimeout;
|
private TimeSpan ConnectionTimeout;
|
||||||
|
|
||||||
private event Action<byte[], int> OnReceivedData;
|
private event Action<byte[], int> OnReceivedData;
|
||||||
private event Action OnConnected;
|
private event Action OnConnected;
|
||||||
private event Action OnDisconnected;
|
private event Action OnDisconnected;
|
||||||
private Action<string> SetTransportError;
|
private Action<string> SetTransportError;
|
||||||
|
|
||||||
private CancellationTokenSource cancelToken;
|
private CancellationTokenSource cancelToken;
|
||||||
private TaskCompletionSource<Task> connectedComplete;
|
private TaskCompletionSource<Task> connectedComplete;
|
||||||
private SteamId hostSteamID = 0;
|
private SteamId hostSteamID = 0;
|
||||||
private FizzyConnectionManager HostConnectionManager;
|
private FizzyConnectionManager HostConnectionManager;
|
||||||
private Connection HostConnection => HostConnectionManager.Connection;
|
private Connection HostConnection => HostConnectionManager.Connection;
|
||||||
private List<Action> BufferedData;
|
private readonly List<Action> BufferedData;
|
||||||
|
|
||||||
private NextClient(FizzyFacepunch transport)
|
private NextClient(FizzyFacepunch transport)
|
||||||
{
|
{
|
||||||
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout));
|
ConnectionTimeout = TimeSpan.FromSeconds(Math.Max(1, transport.Timeout));
|
||||||
BufferedData = new List<Action>();
|
BufferedData = new List<Action>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NextClient CreateClient(FizzyFacepunch transport, string host)
|
public static NextClient CreateClient(FizzyFacepunch transport, string host)
|
||||||
{
|
{
|
||||||
NextClient c = new NextClient(transport);
|
var c = new NextClient(transport);
|
||||||
|
|
||||||
c.OnConnected += () => transport.OnClientConnected.Invoke();
|
c.OnConnected += () => transport.OnClientConnected.Invoke();
|
||||||
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
|
c.OnDisconnected += () => transport.OnClientDisconnected.Invoke();
|
||||||
c.OnReceivedData += (data, ch) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), ch);
|
c.OnReceivedData += (data, ch) => transport.OnClientDataReceived.Invoke(new ArraySegment<byte>(data), ch);
|
||||||
c.SetTransportError = transport.SetTransportError;
|
c.SetTransportError = transport.SetTransportError;
|
||||||
|
|
||||||
if (SteamClient.IsValid)
|
if (SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
c.Connect(host);
|
c.Connect(host);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c.SetTransportError("SteamWorks not initialized");
|
c.SetTransportError("SteamWorks not initialized");
|
||||||
Debug.LogError("SteamWorks not initialized");
|
Debug.LogError("SteamWorks not initialized");
|
||||||
c.OnConnectionFailed();
|
c.OnConnectionFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Connect(string host)
|
private async void Connect(string host)
|
||||||
{
|
{
|
||||||
cancelToken = new CancellationTokenSource();
|
cancelToken = new CancellationTokenSource();
|
||||||
SteamNetworkingSockets.OnConnectionStatusChanged += OnConnectionStatusChanged;
|
SteamNetworkingSockets.OnConnectionStatusChanged += OnConnectionStatusChanged;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hostSteamID = UInt64.Parse(host);
|
hostSteamID = ulong.Parse(host);
|
||||||
connectedComplete = new TaskCompletionSource<Task>();
|
connectedComplete = new TaskCompletionSource<Task>();
|
||||||
OnConnected += SetConnectedComplete;
|
OnConnected += SetConnectedComplete;
|
||||||
HostConnectionManager = SteamNetworkingSockets.ConnectRelay<FizzyConnectionManager>(hostSteamID);
|
HostConnectionManager = SteamNetworkingSockets.ConnectRelay<FizzyConnectionManager>(hostSteamID);
|
||||||
HostConnectionManager.ForwardMessage = OnMessageReceived;
|
HostConnectionManager.ForwardMessage = OnMessageReceived;
|
||||||
Task connectedCompleteTask = connectedComplete.Task;
|
Task connectedCompleteTask = connectedComplete.Task;
|
||||||
Task timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token);
|
var timeOutTask = Task.Delay(ConnectionTimeout, cancelToken.Token);
|
||||||
|
|
||||||
if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask)
|
if (await Task.WhenAny(connectedCompleteTask, timeOutTask) != connectedCompleteTask)
|
||||||
{
|
{
|
||||||
if (cancelToken.IsCancellationRequested)
|
if (cancelToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
SetTransportError("The connection attempt was cancelled.");
|
SetTransportError("The connection attempt was cancelled.");
|
||||||
Debug.LogError($"The connection attempt was cancelled.");
|
Debug.LogError($"The connection attempt was cancelled.");
|
||||||
}
|
}
|
||||||
else if (timeOutTask.IsCompleted)
|
else if (timeOutTask.IsCompleted)
|
||||||
{
|
{
|
||||||
SetTransportError($"Connection to {host} timed out.");
|
SetTransportError($"Connection to {host} timed out.");
|
||||||
Debug.LogError($"Connection to {host} timed out.");
|
Debug.LogError($"Connection to {host} timed out.");
|
||||||
}
|
}
|
||||||
|
|
||||||
OnConnected -= SetConnectedComplete;
|
OnConnected -= SetConnectedComplete;
|
||||||
OnConnectionFailed();
|
OnConnectionFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnConnected -= SetConnectedComplete;
|
OnConnected -= SetConnectedComplete;
|
||||||
}
|
}
|
||||||
catch (FormatException)
|
catch (FormatException)
|
||||||
{
|
{
|
||||||
SetTransportError("Connection string was not in the right format. Did you enter a SteamId?");
|
SetTransportError("Connection string was not in the right format. Did you enter a SteamId?");
|
||||||
Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?");
|
Debug.LogError($"Connection string was not in the right format. Did you enter a SteamId?");
|
||||||
Error = true;
|
Error = true;
|
||||||
OnConnectionFailed();
|
OnConnectionFailed();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
SetTransportError(ex.Message);
|
SetTransportError(ex.Message);
|
||||||
Debug.LogError(ex.Message);
|
Debug.LogError(ex.Message);
|
||||||
Error = true;
|
Error = true;
|
||||||
OnConnectionFailed();
|
OnConnectionFailed();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (Error)
|
if (Error)
|
||||||
{
|
{
|
||||||
Debug.LogError("Connection failed.");
|
Debug.LogError("Connection failed.");
|
||||||
OnConnectionFailed();
|
OnConnectionFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMessageReceived(IntPtr dataPtr, int size)
|
private void OnMessageReceived(IntPtr dataPtr, int size)
|
||||||
{
|
{
|
||||||
(byte[] data, int ch) = ProcessMessage(dataPtr, size);
|
(var data, var ch) = ProcessMessage(dataPtr, size);
|
||||||
if (Connected)
|
if (Connected)
|
||||||
{
|
{
|
||||||
OnReceivedData(data, ch);
|
OnReceivedData(data, ch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BufferedData.Add(() => OnReceivedData(data, ch));
|
BufferedData.Add(() => OnReceivedData(data, ch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnConnectionStatusChanged(Connection conn, ConnectionInfo info)
|
private void OnConnectionStatusChanged(Connection conn, ConnectionInfo info)
|
||||||
{
|
{
|
||||||
ulong clientSteamID = info.Identity.SteamId;
|
ulong clientSteamID = info.Identity.SteamId;
|
||||||
if (info.State == ConnectionState.Connected)
|
if (info.State == ConnectionState.Connected)
|
||||||
{
|
{
|
||||||
Connected = true;
|
Connected = true;
|
||||||
OnConnected.Invoke();
|
OnConnected.Invoke();
|
||||||
Debug.LogError("Connection established.");
|
Debug.LogError("Connection established.");
|
||||||
|
|
||||||
if (BufferedData.Count > 0)
|
if (BufferedData.Count > 0)
|
||||||
{
|
{
|
||||||
Debug.LogError($"{BufferedData.Count} received before connection was established. Processing now.");
|
Debug.LogError($"{BufferedData.Count} received before connection was established. Processing now.");
|
||||||
{
|
{
|
||||||
foreach (Action a in BufferedData)
|
foreach (var a in BufferedData)
|
||||||
{
|
{
|
||||||
a();
|
a();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info.State == ConnectionState.ClosedByPeer)
|
else if (info.State == ConnectionState.ClosedByPeer)
|
||||||
{
|
{
|
||||||
SetTransportError("connection closed by peer");
|
SetTransportError("connection closed by peer");
|
||||||
Connected = false;
|
Connected = false;
|
||||||
OnDisconnected.Invoke();
|
OnDisconnected.Invoke();
|
||||||
Debug.LogError("Disconnected.");
|
Debug.LogError("Disconnected.");
|
||||||
conn.Close(false, 0, "Disconnected");
|
conn.Close(false, 0, "Disconnected");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection state changed: {info.State.ToString()}");
|
Debug.LogError($"Connection state changed: {info.State.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
cancelToken?.Cancel();
|
cancelToken?.Cancel();
|
||||||
SteamNetworkingSockets.OnConnectionStatusChanged -= OnConnectionStatusChanged;
|
SteamNetworkingSockets.OnConnectionStatusChanged -= OnConnectionStatusChanged;
|
||||||
|
|
||||||
if (HostConnectionManager != null)
|
if (HostConnectionManager != null)
|
||||||
{
|
{
|
||||||
Debug.LogError("Sending Disconnect message");
|
Debug.LogError("Sending Disconnect message");
|
||||||
HostConnection.Close(false, 0, "Graceful disconnect");
|
HostConnection.Close(false, 0, "Graceful disconnect");
|
||||||
HostConnectionManager = null;
|
HostConnectionManager = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReceiveData()
|
public void ReceiveData() => HostConnectionManager.Receive(MAX_MESSAGES);
|
||||||
{
|
|
||||||
HostConnectionManager.Receive(MAX_MESSAGES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Send(byte[] data, int channelId)
|
public void Send(byte[] data, int channelId)
|
||||||
{
|
{
|
||||||
Result res = SendSocket(HostConnection, data, channelId);
|
var res = SendSocket(HostConnection, data, channelId);
|
||||||
|
|
||||||
if (res != Result.OK)
|
if (res != Result.OK)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not send: {res.ToString()}");
|
Debug.LogError($"Could not send: {res.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
|
private void SetConnectedComplete() => connectedComplete.SetResult(connectedComplete.Task);
|
||||||
private void OnConnectionFailed() => OnDisconnected.Invoke();
|
private void OnConnectionFailed() => OnDisconnected.Invoke();
|
||||||
public void FlushData()
|
public void FlushData() => HostConnection.Flush();
|
||||||
{
|
}
|
||||||
HostConnection.Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,32 +7,32 @@ using UnityEngine;
|
|||||||
|
|
||||||
public abstract class NextCommon
|
public abstract class NextCommon
|
||||||
{
|
{
|
||||||
protected const int MAX_MESSAGES = 256;
|
protected const int MAX_MESSAGES = 256;
|
||||||
|
|
||||||
protected Result SendSocket(Connection conn, byte[] data, int channelId)
|
protected Result SendSocket(Connection conn, byte[] data, int channelId)
|
||||||
{
|
{
|
||||||
Array.Resize(ref data, data.Length + 1);
|
Array.Resize(ref data, data.Length + 1);
|
||||||
data[data.Length - 1] = (byte)channelId;
|
data[data.Length - 1] = (byte)channelId;
|
||||||
|
|
||||||
GCHandle pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
|
var pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
|
||||||
IntPtr pData = pinnedArray.AddrOfPinnedObject();
|
var pData = pinnedArray.AddrOfPinnedObject();
|
||||||
SendType sendFlag = channelId == Channels.Unreliable ? SendType.Unreliable : SendType.Reliable;
|
var sendFlag = channelId == Channels.Unreliable ? SendType.Unreliable : SendType.Reliable;
|
||||||
Result res = conn.SendMessage(pData, data.Length, sendFlag);
|
var res = conn.SendMessage(pData, data.Length, sendFlag);
|
||||||
if (res != Result.OK)
|
if (res != Result.OK)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Send issue: {res}");
|
Debug.LogWarning($"Send issue: {res}");
|
||||||
}
|
}
|
||||||
|
|
||||||
pinnedArray.Free();
|
pinnedArray.Free();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected (byte[], int) ProcessMessage(IntPtr ptrs, int size)
|
protected (byte[], int) ProcessMessage(IntPtr ptrs, int size)
|
||||||
{
|
{
|
||||||
byte[] managedArray = new byte[size];
|
var managedArray = new byte[size];
|
||||||
Marshal.Copy(ptrs, managedArray, 0, size);
|
Marshal.Copy(ptrs, managedArray, 0, size);
|
||||||
int channel = managedArray[managedArray.Length - 1];
|
int channel = managedArray[managedArray.Length - 1];
|
||||||
Array.Resize(ref managedArray, managedArray.Length - 1);
|
Array.Resize(ref managedArray, managedArray.Length - 1);
|
||||||
return (managedArray, channel);
|
return (managedArray, channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,186 +5,183 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Mirror.FizzySteam
|
namespace Mirror.FizzySteam
|
||||||
{
|
{
|
||||||
public class NextServer : NextCommon, IServer
|
public class NextServer : NextCommon, IServer
|
||||||
{
|
{
|
||||||
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;
|
||||||
private event Action<int, Exception> OnReceivedError;
|
private event Action<int, Exception> OnReceivedError;
|
||||||
|
|
||||||
private BidirectionalDictionary<Connection, int> connToMirrorID;
|
private readonly BidirectionalDictionary<Connection, int> connToMirrorID;
|
||||||
private BidirectionalDictionary<SteamId, int> steamIDToMirrorID;
|
private readonly BidirectionalDictionary<SteamId, int> steamIDToMirrorID;
|
||||||
private int maxConnections;
|
private readonly int maxConnections;
|
||||||
private int nextConnectionID;
|
private int nextConnectionID;
|
||||||
|
|
||||||
private FizzySocketManager listenSocket;
|
private FizzySocketManager listenSocket;
|
||||||
|
|
||||||
private NextServer(int maxConnections)
|
private NextServer(int maxConnections)
|
||||||
{
|
{
|
||||||
this.maxConnections = maxConnections;
|
this.maxConnections = maxConnections;
|
||||||
connToMirrorID = new BidirectionalDictionary<Connection, int>();
|
connToMirrorID = new BidirectionalDictionary<Connection, int>();
|
||||||
steamIDToMirrorID = new BidirectionalDictionary<SteamId, int>();
|
steamIDToMirrorID = new BidirectionalDictionary<SteamId, int>();
|
||||||
nextConnectionID = 1;
|
nextConnectionID = 1;
|
||||||
SteamNetworkingSockets.OnConnectionStatusChanged += OnConnectionStatusChanged;
|
SteamNetworkingSockets.OnConnectionStatusChanged += OnConnectionStatusChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NextServer CreateServer(FizzyFacepunch transport, int maxConnections)
|
public static NextServer CreateServer(FizzyFacepunch transport, int maxConnections)
|
||||||
{
|
{
|
||||||
NextServer s = new NextServer(maxConnections);
|
var s = new NextServer(maxConnections);
|
||||||
|
|
||||||
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
|
s.OnConnected += (id) => transport.OnServerConnected.Invoke(id);
|
||||||
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
|
s.OnDisconnected += (id) => transport.OnServerDisconnected.Invoke(id);
|
||||||
s.OnReceivedData += (id, data, ch) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), ch);
|
s.OnReceivedData += (id, data, ch) => transport.OnServerDataReceived.Invoke(id, new ArraySegment<byte>(data), ch);
|
||||||
s.OnReceivedError += (id, exception) => transport.OnServerError.Invoke(id, exception);
|
s.OnReceivedError += (id, exception) => transport.OnServerError.Invoke(id, exception);
|
||||||
|
|
||||||
if (!SteamClient.IsValid)
|
if (!SteamClient.IsValid)
|
||||||
{
|
{
|
||||||
Debug.LogError("SteamWorks not initialized.");
|
Debug.LogError("SteamWorks not initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Host();
|
s.Host();
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Host()
|
private void Host()
|
||||||
{
|
{
|
||||||
listenSocket = SteamNetworkingSockets.CreateRelaySocket<FizzySocketManager>();
|
listenSocket = SteamNetworkingSockets.CreateRelaySocket<FizzySocketManager>();
|
||||||
listenSocket.ForwardMessage = OnMessageReceived;
|
listenSocket.ForwardMessage = OnMessageReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnConnectionStatusChanged(Connection conn, ConnectionInfo info)
|
private void OnConnectionStatusChanged(Connection conn, ConnectionInfo info)
|
||||||
{
|
{
|
||||||
ulong clientSteamID = info.Identity.SteamId;
|
ulong clientSteamID = info.Identity.SteamId;
|
||||||
if (info.State == ConnectionState.Connecting)
|
if (info.State == ConnectionState.Connecting)
|
||||||
{
|
{
|
||||||
if (connToMirrorID.Count >= maxConnections)
|
if (connToMirrorID.Count >= maxConnections)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Incoming connection {clientSteamID} would exceed max connection count. Rejecting.");
|
Debug.LogError($"Incoming connection {clientSteamID} would exceed max connection count. Rejecting.");
|
||||||
conn.Close(false, 0, "Max Connection Count");
|
conn.Close(false, 0, "Max Connection Count");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result res;
|
Result res;
|
||||||
|
|
||||||
if ((res = conn.Accept()) == Result.OK)
|
if ((res = conn.Accept()) == Result.OK)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Accepting connection {clientSteamID}");
|
Debug.LogError($"Accepting connection {clientSteamID}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection {clientSteamID} could not be accepted: {res.ToString()}");
|
Debug.LogError($"Connection {clientSteamID} could not be accepted: {res.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info.State == ConnectionState.Connected)
|
else if (info.State == ConnectionState.Connected)
|
||||||
{
|
{
|
||||||
int connectionId = nextConnectionID++;
|
var connectionId = nextConnectionID++;
|
||||||
connToMirrorID.Add(conn, connectionId);
|
connToMirrorID.Add(conn, connectionId);
|
||||||
steamIDToMirrorID.Add(clientSteamID, connectionId);
|
steamIDToMirrorID.Add(clientSteamID, connectionId);
|
||||||
OnConnected.Invoke(connectionId);
|
OnConnected.Invoke(connectionId);
|
||||||
Debug.LogError($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}");
|
Debug.LogError($"Client with SteamID {clientSteamID} connected. Assigning connection id {connectionId}");
|
||||||
}
|
}
|
||||||
else if (info.State == ConnectionState.ClosedByPeer)
|
else if (info.State == ConnectionState.ClosedByPeer)
|
||||||
{
|
{
|
||||||
if (connToMirrorID.TryGetValue(conn, out int connId))
|
if (connToMirrorID.TryGetValue(conn, out var connId))
|
||||||
{
|
{
|
||||||
InternalDisconnect(connId, conn);
|
InternalDisconnect(connId, conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection {clientSteamID} state changed: {info.State.ToString()}");
|
Debug.LogError($"Connection {clientSteamID} state changed: {info.State.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InternalDisconnect(int connId, Connection socket)
|
private void InternalDisconnect(int connId, Connection socket)
|
||||||
{
|
{
|
||||||
OnDisconnected.Invoke(connId);
|
OnDisconnected.Invoke(connId);
|
||||||
socket.Close(false, 0, "Graceful disconnect");
|
socket.Close(false, 0, "Graceful disconnect");
|
||||||
connToMirrorID.Remove(connId);
|
connToMirrorID.Remove(connId);
|
||||||
steamIDToMirrorID.Remove(connId);
|
steamIDToMirrorID.Remove(connId);
|
||||||
Debug.LogError($"Client with SteamID {connId} disconnected.");
|
Debug.LogError($"Client with SteamID {connId} disconnected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Disconnect(int connectionId)
|
public void Disconnect(int connectionId)
|
||||||
{
|
{
|
||||||
if (connToMirrorID.TryGetValue(connectionId, out Connection conn))
|
if (connToMirrorID.TryGetValue(connectionId, out var conn))
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection id {connectionId} disconnected.");
|
Debug.LogError($"Connection id {connectionId} disconnected.");
|
||||||
conn.Close(false, 0, "Disconnected by server");
|
conn.Close(false, 0, "Disconnected by server");
|
||||||
steamIDToMirrorID.Remove(connectionId);
|
steamIDToMirrorID.Remove(connectionId);
|
||||||
connToMirrorID.Remove(connectionId);
|
connToMirrorID.Remove(connectionId);
|
||||||
OnDisconnected(connectionId);
|
OnDisconnected(connectionId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId);
|
Debug.LogWarning("Trying to disconnect unknown connection id: " + connectionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FlushData()
|
public void FlushData()
|
||||||
{
|
{
|
||||||
foreach (Connection conn in connToMirrorID.FirstTypes)
|
foreach (var conn in connToMirrorID.FirstTypes)
|
||||||
{
|
{
|
||||||
conn.Flush();
|
conn.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReceiveData()
|
public void ReceiveData() => listenSocket.Receive(MAX_MESSAGES);
|
||||||
{
|
|
||||||
listenSocket.Receive(MAX_MESSAGES);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMessageReceived(Connection conn, IntPtr dataPtr, int size)
|
private void OnMessageReceived(Connection conn, IntPtr dataPtr, int size)
|
||||||
{
|
{
|
||||||
(byte[] data, int ch) = ProcessMessage(dataPtr, size);
|
(var data, var ch) = ProcessMessage(dataPtr, size);
|
||||||
OnReceivedData(connToMirrorID[conn], data, ch);
|
OnReceivedData(connToMirrorID[conn], data, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Send(int connectionId, byte[] data, int channelId)
|
public void Send(int connectionId, byte[] data, int channelId)
|
||||||
{
|
{
|
||||||
if (connToMirrorID.TryGetValue(connectionId, out Connection conn))
|
if (connToMirrorID.TryGetValue(connectionId, out var conn))
|
||||||
{
|
{
|
||||||
Result res = SendSocket(conn, data, channelId);
|
var res = SendSocket(conn, data, channelId);
|
||||||
|
|
||||||
if (res == Result.NoConnection || res == Result.InvalidParam)
|
if (res == Result.NoConnection || res == Result.InvalidParam)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Connection to {connectionId} was lost.");
|
Debug.LogError($"Connection to {connectionId} was lost.");
|
||||||
InternalDisconnect(connectionId, conn);
|
InternalDisconnect(connectionId, conn);
|
||||||
}
|
}
|
||||||
else if (res != Result.OK)
|
else if (res != Result.OK)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Could not send: {res.ToString()}");
|
Debug.LogError($"Could not send: {res.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 (steamIDToMirrorID.TryGetValue(connectionId, out SteamId steamId))
|
if (steamIDToMirrorID.TryGetValue(connectionId, out var steamId))
|
||||||
{
|
{
|
||||||
return steamId.ToString();
|
return steamId.ToString();
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Shutdown()
|
public void Shutdown()
|
||||||
{
|
{
|
||||||
if (listenSocket != null)
|
if (listenSocket != null)
|
||||||
{
|
{
|
||||||
SteamNetworkingSockets.OnConnectionStatusChanged -= OnConnectionStatusChanged;
|
SteamNetworkingSockets.OnConnectionStatusChanged -= OnConnectionStatusChanged;
|
||||||
listenSocket.Close();
|
listenSocket.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user