using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Steamworks.Data; namespace Steamworks { public static class SteamNetworkingSockets { static ISteamNetworkingSockets _internal; internal static ISteamNetworkingSockets Internal { get { if ( _internal == null ) { _internal = new ISteamNetworkingSockets(); _internal.Init(); SocketInterfaces = new Dictionary(); ConnectionInterfaces = new Dictionary(); } return _internal; } } #region SocketInterface static Dictionary SocketInterfaces; internal static SocketInterface GetSocketInterface( uint id ) { if ( SocketInterfaces == null ) return null; if ( id == 0 ) throw new System.ArgumentException( "Invalid Socket" ); if ( SocketInterfaces.TryGetValue( id, out var isocket ) ) return isocket; return null; } internal static void SetSocketInterface( uint id, SocketInterface iface ) { if ( id == 0 ) throw new System.ArgumentException( "Invalid Socket" ); Console.WriteLine( $"Installing Socket For {id}" ); SocketInterfaces[id] = iface; } #endregion #region ConnectionInterface static Dictionary ConnectionInterfaces; internal static ConnectionInterface GetConnectionInterface( uint id ) { if ( ConnectionInterfaces == null ) return null; if ( id == 0 ) return null; if ( ConnectionInterfaces.TryGetValue( id, out var iconnection ) ) return iconnection; return null; } internal static void SetConnectionInterface( uint id, ConnectionInterface iface ) { if ( id == 0 ) throw new System.ArgumentException( "Invalid Connection" ); ConnectionInterfaces[id] = iface; } #endregion internal static void Shutdown() { _internal = null; SocketInterfaces = null; ConnectionInterfaces = null; } internal static void InstallEvents( bool server = false ) { SteamNetConnectionStatusChangedCallback_t.Install( x => ConnectionStatusChanged( x ), server ); } private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t data ) { // // This is a message from/to a listen socket // if ( data.Nfo.listenSocket.Id > 0 ) { var iface = GetSocketInterface( data.Nfo.listenSocket.Id ); iface?.OnConnectionChanged( data.Conn, data.Nfo ); } else { var iface = GetConnectionInterface( data.Conn.Id ); iface?.OnConnectionChanged( data.Nfo ); } OnConnectionStatusChanged?.Invoke( data.Conn, data.Nfo ); } public static event Action OnConnectionStatusChanged; /// /// Creates a "server" socket that listens for clients to connect to by calling /// Connect, over ordinary UDP (IPv4 or IPv6) /// public static T CreateNormalSocket( NetAddress address ) where T : SocketInterface, new() { var t = new T(); t.Socket = Internal.CreateListenSocketIP( ref address ); SetSocketInterface( t.Socket.Id, t ); return t; } /// /// Connect to a socket created via CreateListenSocketIP /// public static T ConnectNormal( NetAddress address ) where T : ConnectionInterface, new() { var t = new T(); t.Connection = Internal.ConnectByIPAddress( ref address ); SetConnectionInterface( t.Connection.Id, t ); return t; } /// /// Creates a server that will be relayed via Valve's network (hiding the IP and improving ping) /// public static T CreateRelaySocket( int virtualport = 0 ) where T : SocketInterface, new() { var t = new T(); t.Socket = Internal.CreateListenSocketP2P( virtualport ); SetSocketInterface( t.Socket.Id, t ); return t; } /// /// Connect to a relay server /// public static T ConnectRelay( SteamId serverId, int virtualport = 0 ) where T : ConnectionInterface, new() { var t = new T(); NetIdentity identity = serverId; t.Connection = Internal.ConnectP2P( ref identity, virtualport ); SetConnectionInterface( t.Connection.Id, t ); return t; } } }