v1.3.0.1 (Epic Store release)
This commit is contained in:
+82
@@ -0,0 +1,82 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class DualStackP2PSocket : P2PSocket
|
||||
{
|
||||
private readonly Option<EosP2PSocket> eosSocket;
|
||||
private readonly Option<SteamListenSocket> steamSocket;
|
||||
|
||||
private DualStackP2PSocket(
|
||||
Callbacks callbacks,
|
||||
Option<EosP2PSocket> eosSocket,
|
||||
Option<SteamListenSocket> steamSocket) :
|
||||
base(callbacks)
|
||||
{
|
||||
this.eosSocket = eosSocket;
|
||||
this.steamSocket = steamSocket;
|
||||
}
|
||||
|
||||
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
|
||||
{
|
||||
var eosP2PSocketResult = EosP2PSocket.Create(callbacks);
|
||||
var steamP2PSocketResult = SteamListenSocket.Create(callbacks);
|
||||
if (eosP2PSocketResult.TryUnwrapFailure(out var eosError)
|
||||
&& steamP2PSocketResult.TryUnwrapFailure(out var steamError))
|
||||
{
|
||||
return Result.Failure(new Error(eosError, steamError));
|
||||
}
|
||||
return Result.Success((P2PSocket)new DualStackP2PSocket(
|
||||
callbacks,
|
||||
eosP2PSocketResult.TryUnwrapSuccess(out var eosP2PSocket)
|
||||
? Option.Some((EosP2PSocket)eosP2PSocket)
|
||||
: Option.None,
|
||||
steamP2PSocketResult.TryUnwrapSuccess(out var steamP2PSocket)
|
||||
? Option.Some((SteamListenSocket)steamP2PSocket)
|
||||
: Option.None));
|
||||
}
|
||||
|
||||
public override void ProcessIncomingMessages()
|
||||
{
|
||||
if (eosSocket.TryUnwrap(out var eosP2PSocket)) { eosP2PSocket.ProcessIncomingMessages(); }
|
||||
if (steamSocket.TryUnwrap(out var steamP2PSocket)) { steamP2PSocket.ProcessIncomingMessages(); }
|
||||
}
|
||||
|
||||
public override bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
return endpoint switch
|
||||
{
|
||||
EosP2PEndpoint eosP2PEndpoint when eosSocket.TryUnwrap(out var eosP2PSocket)
|
||||
=> eosP2PSocket.SendMessage(eosP2PEndpoint, outMsg, deliveryMethod),
|
||||
SteamP2PEndpoint steamP2PEndpoint when steamSocket.TryUnwrap(out var steamP2PSocket)
|
||||
=> steamP2PSocket.SendMessage(steamP2PEndpoint, outMsg, deliveryMethod),
|
||||
_
|
||||
=> false
|
||||
};
|
||||
}
|
||||
|
||||
public override void CloseConnection(P2PEndpoint endpoint)
|
||||
{
|
||||
switch (endpoint)
|
||||
{
|
||||
case EosP2PEndpoint eosP2PEndpoint:
|
||||
if (eosSocket.TryUnwrap(out var eosP2PSocket))
|
||||
{
|
||||
eosP2PSocket.CloseConnection(eosP2PEndpoint);
|
||||
}
|
||||
break;
|
||||
case SteamP2PEndpoint steamP2PEndpoint:
|
||||
if (steamSocket.TryUnwrap(out var steamP2PSocket))
|
||||
{
|
||||
steamP2PSocket.CloseConnection(steamP2PEndpoint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (eosSocket.TryUnwrap(out var eosP2PSocket)) { eosP2PSocket.Dispose(); }
|
||||
if (steamSocket.TryUnwrap(out var steamP2PSocket)) { steamP2PSocket.Dispose(); }
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class EosP2PSocket : P2PSocket
|
||||
{
|
||||
private readonly EosInterface.P2PSocket eosSocket;
|
||||
|
||||
private EosP2PSocket(
|
||||
Callbacks callbacks,
|
||||
EosInterface.P2PSocket eosSocket)
|
||||
: base(callbacks)
|
||||
{
|
||||
this.eosSocket = eosSocket;
|
||||
}
|
||||
|
||||
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
|
||||
{
|
||||
if (!EosInterface.Core.IsInitialized) { return Result.Failure(new Error(ErrorCode.EosNotInitialized)); }
|
||||
|
||||
var eosSocketId = new EosInterface.SocketId { SocketName = EosP2PEndpoint.SocketName };
|
||||
if (EosInterface.IdQueries.GetLoggedInPuids() is not { Length: > 0 } puids)
|
||||
{
|
||||
return Result.Failure(new Error(ErrorCode.EosNotLoggedIn));
|
||||
}
|
||||
var socketCreateResult = EosInterface.P2PSocket.Create(puids[0], eosSocketId);
|
||||
|
||||
if (!socketCreateResult.TryUnwrapSuccess(out var eosSocket)) { return Result.Failure(new Error(ErrorCode.FailedToCreateEosP2PSocket, socketCreateResult.ToString())); }
|
||||
var retVal = new EosP2PSocket(callbacks, eosSocket);
|
||||
|
||||
eosSocket.HandleIncomingConnection.Register("Event".ToIdentifier(), retVal.OnIncomingConnection);
|
||||
eosSocket.HandleClosedConnection.Register("Event".ToIdentifier(), retVal.OnConnectionClosed);
|
||||
|
||||
return Result.Success((P2PSocket)retVal);
|
||||
}
|
||||
|
||||
public override void ProcessIncomingMessages()
|
||||
{
|
||||
foreach (var msg in eosSocket.GetMessageBatch())
|
||||
{
|
||||
callbacks.OnData(new EosP2PEndpoint(msg.Sender), new ReadWriteMessage(msg.Buffer, 0, msg.ByteLength * 8, false));
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (endpoint is not EosP2PEndpoint { ProductUserId: var puid }) { return false; }
|
||||
var sendResult = eosSocket.SendMessage(new EosInterface.P2PSocket.OutgoingMessage(
|
||||
Buffer: outMsg.Buffer,
|
||||
ByteLength: outMsg.LengthBytes,
|
||||
Destination: puid,
|
||||
DeliveryMethod: deliveryMethod));
|
||||
return sendResult.IsSuccess;
|
||||
}
|
||||
|
||||
private void OnIncomingConnection(EosInterface.P2PSocket.IncomingConnectionRequest request)
|
||||
{
|
||||
var remoteEndpoint = new EosP2PEndpoint(request.RemoteUserId);
|
||||
|
||||
if (callbacks.OnIncomingConnection(remoteEndpoint))
|
||||
{
|
||||
request.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConnectionClosed(EosInterface.P2PSocket.RemoteConnectionClosed data)
|
||||
{
|
||||
var remoteEndpoint = new EosP2PEndpoint(data.RemoteUserId);
|
||||
|
||||
var peerDisconnectPacket = PeerDisconnectPacket.WithReason(data.Reason switch
|
||||
{
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.Unknown => DisconnectReason.Unknown,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.ClosedByLocalUser => DisconnectReason.Disconnected,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.ClosedByPeer => DisconnectReason.Disconnected,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.TimedOut => DisconnectReason.Timeout,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.TooManyConnections => DisconnectReason.ServerFull,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.InvalidMessage => DisconnectReason.Unknown,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.InvalidData => DisconnectReason.Unknown,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.ConnectionFailed => DisconnectReason.AuthenticationFailed,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.ConnectionClosed => DisconnectReason.Disconnected,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.NegotiationFailed => DisconnectReason.AuthenticationFailed,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.UnexpectedError => DisconnectReason.Unknown,
|
||||
EosInterface.P2PSocket.RemoteConnectionClosed.ConnectionClosedReason.Unhandled => DisconnectReason.Unknown,
|
||||
_ => DisconnectReason.Unknown
|
||||
});
|
||||
callbacks.OnConnectionClosed(remoteEndpoint, peerDisconnectPacket);
|
||||
}
|
||||
|
||||
public override void CloseConnection(P2PEndpoint endpoint)
|
||||
{
|
||||
if (endpoint is not EosP2PEndpoint { ProductUserId: var puid }) { return; }
|
||||
eosSocket.CloseConnection(puid);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
eosSocket.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
abstract class P2PSocket : IDisposable
|
||||
{
|
||||
public enum ErrorCode
|
||||
{
|
||||
EosNotInitialized,
|
||||
EosNotLoggedIn,
|
||||
FailedToCreateEosP2PSocket,
|
||||
|
||||
SteamNotInitialized,
|
||||
FailedToCreateSteamP2PSocket
|
||||
}
|
||||
|
||||
public readonly record struct Error(
|
||||
ImmutableArray<(ErrorCode Code, string AdditionalInfo)> CodesAndInfo)
|
||||
{
|
||||
public Error(ErrorCode code, string? additionalInfo = "") : this((code, additionalInfo ?? "").ToEnumerable().ToImmutableArray()) { }
|
||||
public Error(params Error[] innerErrors) : this(innerErrors.SelectMany(ie => ie.CodesAndInfo).ToImmutableArray()) { }
|
||||
|
||||
public override string? ToString()
|
||||
{
|
||||
if (CodesAndInfo.IsDefault)
|
||||
{
|
||||
return "default(Error)";
|
||||
}
|
||||
|
||||
return $"Errors({string.Join("; ", CodesAndInfo)})";
|
||||
}
|
||||
}
|
||||
|
||||
public readonly record struct Callbacks(
|
||||
Predicate<P2PEndpoint> OnIncomingConnection,
|
||||
Action<P2PEndpoint, PeerDisconnectPacket> OnConnectionClosed,
|
||||
Action<P2PEndpoint, IReadMessage> OnData);
|
||||
protected readonly Callbacks callbacks;
|
||||
|
||||
protected P2PSocket(Callbacks callbacks)
|
||||
{
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public abstract void ProcessIncomingMessages();
|
||||
|
||||
public abstract bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod);
|
||||
|
||||
public abstract void CloseConnection(P2PEndpoint endpoint);
|
||||
|
||||
public abstract void Dispose();
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Barotrauma.Steam;
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class SteamConnectSocket : P2PSocket
|
||||
{
|
||||
private sealed class ConnectionManager : Steamworks.ConnectionManager, Steamworks.IConnectionManager
|
||||
{
|
||||
private SteamP2PEndpoint endpoint;
|
||||
private Callbacks callbacks;
|
||||
public void SetEndpointAndCallbacks(SteamP2PEndpoint endpoint, Callbacks callbacks)
|
||||
{
|
||||
this.endpoint = endpoint;
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public override void OnMessage(IntPtr data, int size, long messageNum, long recvTime, int channel)
|
||||
{
|
||||
var dataArray = new byte[size];
|
||||
Marshal.Copy(source: data, destination: dataArray, startIndex: 0, length: size);
|
||||
|
||||
callbacks.OnData(endpoint, new ReadWriteMessage(dataArray, bitPos: 0, lBits: size * 8, copyBuf: false));
|
||||
}
|
||||
|
||||
public override void OnDisconnected(Steamworks.Data.ConnectionInfo info)
|
||||
{
|
||||
if (!info.Identity.IsSteamId) { return; }
|
||||
var remoteEndpoint = new SteamP2PEndpoint(new SteamId((Steamworks.SteamId)info.Identity));
|
||||
var peerDisconnectPacket = PeerDisconnectPacket.WithReason(info.EndReason switch
|
||||
{
|
||||
Steamworks.NetConnectionEnd.App_Generic => DisconnectReason.Disconnected,
|
||||
Steamworks.NetConnectionEnd.AppException_Generic => DisconnectReason.Unknown,
|
||||
|
||||
Steamworks.NetConnectionEnd.Local_OfflineMode => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_ManyRelayConnectivity => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_HostedServerPrimaryRelay => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_NetworkConfig => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_Rights => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_P2P_ICE_NoPublicAddresses => DisconnectReason.SteamP2PError,
|
||||
|
||||
Steamworks.NetConnectionEnd.Remote_Timeout => DisconnectReason.SteamP2PTimeOut,
|
||||
Steamworks.NetConnectionEnd.Remote_BadCrypt => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_BadCert => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_BadProtocolVersion => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_P2P_ICE_NoPublicAddresses => DisconnectReason.SteamP2PError,
|
||||
|
||||
Steamworks.NetConnectionEnd.Misc_Generic => DisconnectReason.Unknown,
|
||||
Steamworks.NetConnectionEnd.Misc_InternalError => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_Timeout => DisconnectReason.SteamP2PTimeOut,
|
||||
Steamworks.NetConnectionEnd.Misc_SteamConnectivity => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_NoRelaySessionsToClient => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_P2P_Rendezvous => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_P2P_NAT_Firewall => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_PeerSentNoConnection => DisconnectReason.SteamP2PError,
|
||||
|
||||
_ => DisconnectReason.Unknown
|
||||
});
|
||||
callbacks.OnConnectionClosed(remoteEndpoint, peerDisconnectPacket);
|
||||
base.OnDisconnected(info);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly SteamP2PEndpoint expectedEndpoint;
|
||||
private readonly ConnectionManager connectionManager;
|
||||
|
||||
private SteamConnectSocket(SteamP2PEndpoint expectedEndpoint, Callbacks callbacks, ConnectionManager connectionManager) : base(callbacks)
|
||||
{
|
||||
this.expectedEndpoint = expectedEndpoint;
|
||||
this.connectionManager = connectionManager;
|
||||
}
|
||||
|
||||
public static Result<P2PSocket, Error> Create(SteamP2PEndpoint endpoint, Callbacks callbacks)
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return Result.Failure(new Error(ErrorCode.SteamNotInitialized)); }
|
||||
|
||||
var connectionManager = Steamworks.SteamNetworkingSockets.ConnectRelay<ConnectionManager>(endpoint.SteamId.Value);
|
||||
if (connectionManager is null) { return Result.Failure(new Error(ErrorCode.FailedToCreateSteamP2PSocket)); }
|
||||
connectionManager.SetEndpointAndCallbacks(endpoint, callbacks);
|
||||
|
||||
return Result.Success((P2PSocket)new SteamConnectSocket(endpoint, callbacks, connectionManager));
|
||||
}
|
||||
|
||||
public override void ProcessIncomingMessages()
|
||||
{
|
||||
connectionManager.Receive();
|
||||
}
|
||||
|
||||
public override bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (endpoint != expectedEndpoint) { return false; }
|
||||
var result = connectionManager.Connection.SendMessage(
|
||||
data: outMsg.Buffer,
|
||||
offset: 0,
|
||||
length: outMsg.LengthBytes,
|
||||
sendType: deliveryMethod switch
|
||||
{
|
||||
DeliveryMethod.Reliable => Steamworks.Data.SendType.Reliable,
|
||||
_ => Steamworks.Data.SendType.Unreliable
|
||||
});
|
||||
return result == Steamworks.Result.OK;
|
||||
}
|
||||
|
||||
public override void CloseConnection(P2PEndpoint endpoint)
|
||||
{
|
||||
if (endpoint != expectedEndpoint) { return; }
|
||||
connectionManager.Close();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
connectionManager.Close();
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class SteamListenSocket : P2PSocket
|
||||
{
|
||||
private sealed class SocketManager : Steamworks.SocketManager, Steamworks.ISocketManager
|
||||
{
|
||||
private Callbacks callbacks;
|
||||
private readonly Dictionary<SteamP2PEndpoint, Steamworks.Data.Connection> endpointToConnection = new();
|
||||
|
||||
public void SetCallbacks(Callbacks callbacks)
|
||||
{
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
public override void OnConnecting(Steamworks.Data.Connection connection, Steamworks.Data.ConnectionInfo info)
|
||||
{
|
||||
if (!info.Identity.IsSteamId) { return; }
|
||||
var remoteEndpoint = new SteamP2PEndpoint(new SteamId((Steamworks.SteamId)info.Identity));
|
||||
endpointToConnection[remoteEndpoint] = connection;
|
||||
if (callbacks.OnIncomingConnection(remoteEndpoint))
|
||||
{
|
||||
connection.Accept();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDisconnected(Steamworks.Data.Connection connection, Steamworks.Data.ConnectionInfo info)
|
||||
{
|
||||
if (!info.Identity.IsSteamId) { return; }
|
||||
var remoteEndpoint = new SteamP2PEndpoint(new SteamId((Steamworks.SteamId)info.Identity));
|
||||
endpointToConnection.Remove(remoteEndpoint);
|
||||
var peerDisconnectPacket = PeerDisconnectPacket.WithReason(info.EndReason switch
|
||||
{
|
||||
Steamworks.NetConnectionEnd.App_Generic => DisconnectReason.Disconnected,
|
||||
Steamworks.NetConnectionEnd.AppException_Generic => DisconnectReason.Unknown,
|
||||
|
||||
Steamworks.NetConnectionEnd.Local_OfflineMode => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_ManyRelayConnectivity => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_HostedServerPrimaryRelay => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_NetworkConfig => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_Rights => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Local_P2P_ICE_NoPublicAddresses => DisconnectReason.SteamP2PError,
|
||||
|
||||
Steamworks.NetConnectionEnd.Remote_Timeout => DisconnectReason.SteamP2PTimeOut,
|
||||
Steamworks.NetConnectionEnd.Remote_BadCrypt => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_BadCert => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_BadProtocolVersion => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Remote_P2P_ICE_NoPublicAddresses => DisconnectReason.SteamP2PError,
|
||||
|
||||
Steamworks.NetConnectionEnd.Misc_Generic => DisconnectReason.Unknown,
|
||||
Steamworks.NetConnectionEnd.Misc_InternalError => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_Timeout => DisconnectReason.SteamP2PTimeOut,
|
||||
Steamworks.NetConnectionEnd.Misc_SteamConnectivity => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_NoRelaySessionsToClient => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_P2P_Rendezvous => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_P2P_NAT_Firewall => DisconnectReason.SteamP2PError,
|
||||
Steamworks.NetConnectionEnd.Misc_PeerSentNoConnection => DisconnectReason.SteamP2PError,
|
||||
|
||||
_ => DisconnectReason.Unknown
|
||||
});
|
||||
callbacks.OnConnectionClosed(remoteEndpoint, peerDisconnectPacket);
|
||||
base.OnDisconnected(connection, info);
|
||||
}
|
||||
|
||||
public override void OnMessage(Steamworks.Data.Connection connection, Steamworks.Data.NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel)
|
||||
{
|
||||
if (!identity.IsSteamId) { return; }
|
||||
var endpoint = new SteamP2PEndpoint(new SteamId((Steamworks.SteamId)identity));
|
||||
|
||||
var dataArray = new byte[size];
|
||||
Marshal.Copy(source: data, destination: dataArray, startIndex: 0, length: size);
|
||||
|
||||
callbacks.OnData(endpoint, new ReadWriteMessage(dataArray, bitPos: 0, lBits: size * 8, copyBuf: false));
|
||||
}
|
||||
|
||||
internal bool SendMessage(SteamP2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (!endpointToConnection.TryGetValue(endpoint, out var connection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = connection.SendMessage(
|
||||
data: outMsg.Buffer,
|
||||
offset: 0,
|
||||
length: outMsg.LengthBytes,
|
||||
sendType: deliveryMethod switch
|
||||
{
|
||||
DeliveryMethod.Reliable => Steamworks.Data.SendType.Reliable,
|
||||
_ => Steamworks.Data.SendType.Unreliable
|
||||
});
|
||||
return result == Steamworks.Result.OK;
|
||||
}
|
||||
|
||||
internal void CloseConnection(SteamP2PEndpoint endpoint)
|
||||
{
|
||||
if (!endpointToConnection.TryGetValue(endpoint, out var connection)) { return; }
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly SocketManager socketManager;
|
||||
|
||||
private SteamListenSocket(
|
||||
Callbacks callbacks,
|
||||
SocketManager socketManager)
|
||||
: base(callbacks)
|
||||
{
|
||||
this.socketManager = socketManager;
|
||||
}
|
||||
|
||||
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return Result.Failure(new Error(ErrorCode.SteamNotInitialized)); }
|
||||
|
||||
var socketManager = Steamworks.SteamNetworkingSockets.CreateRelaySocket<SocketManager>();
|
||||
if (socketManager is null) { return Result.Failure(new Error(ErrorCode.FailedToCreateSteamP2PSocket)); }
|
||||
socketManager.SetCallbacks(callbacks);
|
||||
|
||||
return Result.Success((P2PSocket)new SteamListenSocket(callbacks, socketManager));
|
||||
}
|
||||
|
||||
public override void ProcessIncomingMessages()
|
||||
{
|
||||
socketManager.Receive();
|
||||
}
|
||||
|
||||
public override bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (endpoint is not SteamP2PEndpoint steamP2PEndpoint) { return false; }
|
||||
return socketManager.SendMessage(steamP2PEndpoint, outMsg, deliveryMethod);
|
||||
}
|
||||
|
||||
public override void CloseConnection(P2PEndpoint endpoint)
|
||||
{
|
||||
if (endpoint is not SteamP2PEndpoint steamP2PEndpoint) { return; }
|
||||
socketManager.CloseConnection(steamP2PEndpoint);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
socketManager.Close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user