Release 1.10.5.0 - Autumn Update 2025

This commit is contained in:
Regalis11
2025-09-17 13:44:21 +03:00
parent d13836ce87
commit caa0326cf8
120 changed files with 2584 additions and 635 deletions
@@ -10,30 +10,31 @@ sealed class DualStackP2PSocket : P2PSocket
private DualStackP2PSocket(
Callbacks callbacks,
Option<EosP2PSocket> eosSocket,
Option<SteamListenSocket> steamSocket) :
base(callbacks)
Option<SteamListenSocket> steamSocket,
OwnerOrClient type) :
base(callbacks, type)
{
this.eosSocket = eosSocket;
this.steamSocket = steamSocket;
}
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
public static Result<P2PSocket, Error> Create(Callbacks callbacks, OwnerOrClient type)
{
var eosP2PSocketResult = EosP2PSocket.Create(callbacks);
var steamP2PSocketResult = SteamListenSocket.Create(callbacks);
var eosP2PSocketResult = EosP2PSocket.Create(callbacks, type);
var steamP2PSocketResult = SteamListenSocket.Create(callbacks, type);
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));
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, type));
}
public override void ProcessIncomingMessages()
@@ -8,13 +8,14 @@ sealed class EosP2PSocket : P2PSocket
private EosP2PSocket(
Callbacks callbacks,
EosInterface.P2PSocket eosSocket)
: base(callbacks)
EosInterface.P2PSocket eosSocket,
OwnerOrClient type)
: base(callbacks, type)
{
this.eosSocket = eosSocket;
}
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
public static Result<P2PSocket, Error> Create(Callbacks callbacks, OwnerOrClient type)
{
if (!EosInterface.Core.IsInitialized) { return Result.Failure(new Error(ErrorCode.EosNotInitialized)); }
@@ -26,19 +27,25 @@ sealed class EosP2PSocket : P2PSocket
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);
var retVal = new EosP2PSocket(callbacks, eosSocket, type);
eosSocket.HandleIncomingConnection.Register("Event".ToIdentifier(), retVal.OnIncomingConnection);
eosSocket.HandleClosedConnection.Register("Event".ToIdentifier(), retVal.OnConnectionClosed);
return Result.Success((P2PSocket)retVal);
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));
EosP2PEndpoint endpoint = new EosP2PEndpoint(msg.Sender);
callbacks.OnData(endpoint, new ReadWriteMessage(msg.Buffer, 0, msg.ByteLength * 8, false));
if (Type is OwnerOrClient.Owner)
{
dosProtection.OnPacket(endpoint);
}
}
}
@@ -8,6 +8,15 @@ namespace Barotrauma.Networking;
abstract class P2PSocket : IDisposable
{
public readonly P2POwnerDoSProtection dosProtection;
public readonly OwnerOrClient Type;
public enum OwnerOrClient
{
Client,
Owner
}
public enum ErrorCode
{
EosNotInitialized,
@@ -38,12 +47,16 @@ abstract class P2PSocket : IDisposable
public readonly record struct Callbacks(
Predicate<P2PEndpoint> OnIncomingConnection,
Action<P2PEndpoint, PeerDisconnectPacket> OnConnectionClosed,
P2POwnerDoSProtection.ExcessivePacketDelegate OnExcessivePackets,
Action<P2PEndpoint, IReadMessage> OnData);
protected readonly Callbacks callbacks;
protected P2PSocket(Callbacks callbacks)
protected P2PSocket(Callbacks callbacks, OwnerOrClient type)
{
this.callbacks = callbacks;
Type = type;
dosProtection = new P2POwnerDoSProtection(callbacks.OnExcessivePackets);
}
public abstract void ProcessIncomingMessages();
@@ -64,13 +64,13 @@ sealed class SteamConnectSocket : P2PSocket
private readonly SteamP2PEndpoint expectedEndpoint;
private readonly ConnectionManager connectionManager;
private SteamConnectSocket(SteamP2PEndpoint expectedEndpoint, Callbacks callbacks, ConnectionManager connectionManager) : base(callbacks)
private SteamConnectSocket(SteamP2PEndpoint expectedEndpoint, Callbacks callbacks, ConnectionManager connectionManager, OwnerOrClient type) : base(callbacks, type)
{
this.expectedEndpoint = expectedEndpoint;
this.connectionManager = connectionManager;
}
public static Result<P2PSocket, Error> Create(SteamP2PEndpoint endpoint, Callbacks callbacks)
public static Result<P2PSocket, Error> Create(SteamP2PEndpoint endpoint, Callbacks callbacks, OwnerOrClient type)
{
if (!SteamManager.IsInitialized) { return Result.Failure(new Error(ErrorCode.SteamNotInitialized)); }
@@ -87,7 +87,7 @@ sealed class SteamConnectSocket : P2PSocket
if (connectionManager is null) { return Result.Failure(new Error(ErrorCode.FailedToCreateSteamP2PSocket)); }
connectionManager.SetEndpointAndCallbacks(endpoint, callbacks);
return Result.Success((P2PSocket)new SteamConnectSocket(endpoint, callbacks, connectionManager));
return Result.Success<P2PSocket>(new SteamConnectSocket(endpoint, callbacks, connectionManager, type));
}
public override void ProcessIncomingMessages()
@@ -10,12 +10,14 @@ sealed class SteamListenSocket : P2PSocket
private sealed class SocketManager : Steamworks.SocketManager, Steamworks.ISocketManager
{
private Callbacks callbacks;
private P2PSocket socket;
private readonly Dictionary<SteamP2PEndpoint, Steamworks.Data.Connection> endpointToConnection = new();
public void SetCallbacks(Callbacks callbacks)
{
this.callbacks = callbacks;
}
=> this.callbacks = callbacks;
public void SetSocket(P2PSocket socket)
=> this.socket = socket;
public override void OnConnecting(Steamworks.Data.Connection connection, Steamworks.Data.ConnectionInfo info)
{
@@ -65,7 +67,7 @@ sealed class SteamListenSocket : P2PSocket
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 || data == IntPtr.Zero) { return; }
@@ -75,6 +77,11 @@ sealed class SteamListenSocket : P2PSocket
Marshal.Copy(source: data, destination: dataArray, startIndex: 0, length: size);
callbacks.OnData(endpoint, new ReadWriteMessage(dataArray, bitPos: 0, lBits: size * 8, copyBuf: false));
if (socket?.Type is OwnerOrClient.Owner)
{
socket.dosProtection.OnPacket(endpoint);
}
}
internal bool SendMessage(SteamP2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)
@@ -107,26 +114,49 @@ sealed class SteamListenSocket : P2PSocket
private SteamListenSocket(
Callbacks callbacks,
SocketManager socketManager)
: base(callbacks)
SocketManager socketManager,
OwnerOrClient type)
: base(callbacks, type)
{
this.socketManager = socketManager;
}
public static Result<P2PSocket, Error> Create(Callbacks callbacks)
public static Result<P2PSocket, Error> Create(Callbacks callbacks, OwnerOrClient type)
{
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));
socketManager.SetCallbacks(callbacks);
P2PSocket socket = new SteamListenSocket(callbacks, socketManager, type);
socketManager.SetSocket(socket);
return Result.Success(socket);
}
public override void ProcessIncomingMessages()
{
socketManager.Receive();
const int bufferSize = 32;
const int maxIterations = 100;
// could technically cause a stack overflow since the call is recursive,
// use a while loop instead
int iteration;
for (iteration = 0; iteration < maxIterations; iteration++)
{
int received = socketManager.Receive(bufferSize: bufferSize, receiveToEnd: false);
if (received < bufferSize)
{
break;
}
}
if (iteration >= maxIterations)
{
DebugConsole.ThrowError("Steam P2P socket received too many messages in a single frame.");
}
}
public override bool SendMessage(P2PEndpoint endpoint, IWriteMessage outMsg, DeliveryMethod deliveryMethod)