Unstable v0.19.5.0

This commit is contained in:
Juan Pablo Arce
2022-09-14 12:47:17 -03:00
parent 3f2c843247
commit 1fd2a51bbb
158 changed files with 5702 additions and 4813 deletions
@@ -71,6 +71,12 @@ namespace Barotrauma.Networking
{
expirationTime = parsedTime;
}
else
{
string error = $"Failed to parse the ban duration of \"{name}\" ({separatedLine[2]}) from the legacy ban list file (text file which has now been changed to XML). Considering the ban permanent.";
DebugConsole.ThrowError(error);
GameServer.AddPendingMessageToOwner(error, ChatMessageType.Error);
}
}
string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : "";
@@ -156,6 +162,8 @@ namespace Barotrauma.Networking
public void BanPlayer(string name, Either<Address, AccountId> addressOrAccountId, string reason, TimeSpan? duration)
{
if (addressOrAccountId.TryGet(out Address address) && address.IsLocalHost) { return; }
var existingBan = bannedPlayers.Find(bp => bp.AddressOrAccountId == addressOrAccountId);
if (existingBan != null) { bannedPlayers.Remove(existingBan); }
@@ -224,27 +224,55 @@ namespace Barotrauma.Networking
}
}
/// <summary>
/// Reset what this client has voted for and the kick votes given to this client
/// </summary>
public void ResetVotes(bool resetKickVotes)
{
for (int i = 0; i < votes.Length; i++)
{
votes[i] = null;
}
if (resetKickVotes)
{
kickVoters.Clear();
}
}
public void SetPermissions(ClientPermissions permissions, IEnumerable<DebugConsole.Command> permittedConsoleCommands)
{
this.Permissions = permissions;
this.PermittedConsoleCommands.Clear();
this.PermittedConsoleCommands.UnionWith(permittedConsoleCommands);
Permissions = permissions;
PermittedConsoleCommands.Clear();
PermittedConsoleCommands.UnionWith(permittedConsoleCommands);
if (Permissions.HasFlag(ClientPermissions.ManageSettings))
{
//ensure the client has the up-to-date server settings
GameMain.Server?.ServerSettings?.ForcePropertyUpdate();
}
}
public void GivePermission(ClientPermissions permission)
{
if (!this.Permissions.HasFlag(permission)) this.Permissions |= permission;
if (!Permissions.HasFlag(permission))
{
Permissions |= permission;
if (permission.HasFlag(ClientPermissions.ManageSettings))
{
//ensure the client has the up-to-date server settings
GameMain.Server?.ServerSettings?.ForcePropertyUpdate();
}
}
}
public void RemovePermission(ClientPermissions permission)
{
this.Permissions &= ~permission;
Permissions &= ~permission;
}
public bool HasPermission(ClientPermissions permission)
{
return this.Permissions.HasFlag(permission);
return Permissions.HasFlag(permission);
}
}
}
@@ -39,7 +39,7 @@ namespace Barotrauma.Networking
string resultFileName
= dir.StartsWith(ContentPackage.LocalModsDir)
? $"Local_{mod.Name}"
: $"Workshop_{mod.Name}_{mod.SteamWorkshopId}";
: $"Workshop_{mod.Name}_{(mod.UgcId.TryUnwrap(out var ugcId) ? ugcId.ToString() : "NULL")}";
resultFileName = ToolBox.RemoveInvalidFileNameChars(resultFileName.Replace('\\', '_').Replace('/', '_'));
resultFileName = $"{resultFileName}{Extension}";
return Path.Combine(UploadFolder, resultFileName);
File diff suppressed because it is too large Load Diff
@@ -246,7 +246,7 @@ namespace Barotrauma.Networking
" (created " + (Timing.TotalTime - firstEventToResend.CreateTime).ToString("0.##") + " s ago, " +
(lastSentToAnyoneTime - firstEventToResend.CreateTime).ToString("0.##") + " s older than last event sent to anyone)" +
" Events queued: " + events.Count + ", last sent to all: " + lastSentToAll, ServerLog.MessageType.Error);
server.DisconnectClient(c, "", DisconnectReason.ExcessiveDesyncOldEvent + "/ServerMessage.ExcessiveDesyncOldEvent");
server.DisconnectClient(c, PeerDisconnectPacket.WithReason(DisconnectReason.ExcessiveDesyncOldEvent));
}
);
}
@@ -260,7 +260,7 @@ namespace Barotrauma.Networking
{
DebugConsole.NewMessage(c.Name + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", Color.Red);
GameServer.Log(GameServer.ClientLogName(c) + " was kicked because they were expecting a removed network event (" + (c.LastRecvEntityEventID + 1).ToString() + ", last available is " + events[0].ID.ToString() + ")", ServerLog.MessageType.Error);
server.DisconnectClient(c, "", DisconnectReason.ExcessiveDesyncRemovedEvent + "/ServerMessage.ExcessiveDesyncRemovedEvent");
server.DisconnectClient(c, PeerDisconnectPacket.WithReason(DisconnectReason.ExcessiveDesyncRemovedEvent));
});
}
}
@@ -269,7 +269,7 @@ namespace Barotrauma.Networking
foreach (Client timedOutClient in timedOutClients)
{
GameServer.Log("Disconnecting client " + GameServer.ClientLogName(timedOutClient) + ". Syncing the client with the server took too long.", ServerLog.MessageType.Error);
GameMain.Server.DisconnectClient(timedOutClient, "", DisconnectReason.SyncTimeout + "/ServerMessage.SyncTimeout");
GameMain.Server.DisconnectClient(timedOutClient, PeerDisconnectPacket.WithReason(DisconnectReason.SyncTimeout));
}
bufferedEvents.RemoveAll(b => b.IsProcessed);
@@ -20,7 +20,7 @@ namespace Barotrauma.Networking
if (Sender != null && c.InGame)
{
msg.WriteUInt16(Sender.ID);
}
}
msg.WriteBoolean(false); //text color (no custom text colors for order messages)
msg.WritePadBits();
WriteOrder(msg);
@@ -15,7 +15,7 @@ namespace Barotrauma.Networking
private readonly List<NetIncomingMessage> incomingLidgrenMessages;
public LidgrenServerPeer(Option<int> ownKey, ServerSettings settings)
public LidgrenServerPeer(Option<int> ownKey, ServerSettings settings, Callbacks callbacks) : base(callbacks)
{
serverSettings = settings;
@@ -68,21 +68,21 @@ namespace Barotrauma.Networking
}
}
public override void Close(string? msg = null)
public override void Close()
{
if (netServer == null) { return; }
for (int i = pendingClients.Count - 1; i >= 0; i--)
{
RemovePendingClient(pendingClients[i], DisconnectReason.ServerShutdown, msg);
RemovePendingClient(pendingClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
}
for (int i = connectedClients.Count - 1; i >= 0; i--)
{
Disconnect(connectedClients[i], msg ?? DisconnectReason.ServerShutdown.ToString());
Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
}
netServer.Shutdown(msg ?? DisconnectReason.ServerShutdown.ToString());
netServer.Shutdown(PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown).ToLidgrenStringRepresentation());
pendingClients.Clear();
connectedClients.Clear();
@@ -91,7 +91,7 @@ namespace Barotrauma.Networking
Steamworks.SteamServer.OnValidateAuthTicketResponse -= OnAuthChange;
OnShutdown?.Invoke();
callbacks.OnShutdown.Invoke();
}
public override void Update(float deltaTime)
@@ -100,12 +100,6 @@ namespace Barotrauma.Networking
ToolBox.ThrowIfNull(incomingLidgrenMessages);
if (OnOwnerDetermined != null && OwnerConnection != null)
{
OnOwnerDetermined?.Invoke(OwnerConnection);
OnOwnerDetermined = null;
}
netServer.ReadMessages(incomingLidgrenMessages);
//process incoming connections first
@@ -193,14 +187,14 @@ namespace Barotrauma.Networking
if (connectedClients.Count >= serverSettings.MaxPlayers)
{
inc.SenderConnection.Deny(DisconnectReason.ServerFull.ToString());
inc.SenderConnection.Deny(PeerDisconnectPacket.WithReason(DisconnectReason.ServerFull).ToLidgrenStringRepresentation());
return;
}
if (serverSettings.BanList.IsBanned(new LidgrenEndpoint(inc.SenderConnection.RemoteEndPoint), out string banReason))
{
//IP banned: deny immediately
inc.SenderConnection.Deny($"{DisconnectReason.Banned}/ {banReason}");
inc.SenderConnection.Deny(PeerDisconnectPacket.Banned(banReason).ToLidgrenStringRepresentation());
return;
}
@@ -235,12 +229,12 @@ namespace Barotrauma.Networking
{
if (pendingClient != null)
{
RemovePendingClient(pendingClient, DisconnectReason.AuthenticationRequired, "Received data message from unauthenticated client");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationRequired));
}
else if (lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnected &&
lidgrenMsg.SenderConnection.Status != NetConnectionStatus.Disconnecting)
{
lidgrenMsg.SenderConnection.Disconnect($"{DisconnectReason.AuthenticationRequired}/ Received data message from unauthenticated client");
lidgrenMsg.SenderConnection.Disconnect(PeerDisconnectPacket.WithReason(DisconnectReason.AuthenticationRequired).ToLidgrenStringRepresentation());
}
return;
@@ -252,12 +246,12 @@ namespace Barotrauma.Networking
|| (conn.AccountInfo.AccountId.TryUnwrap(out var accountId) && serverSettings.BanList.IsBanned(accountId, out banReason))
|| conn.AccountInfo.OtherMatchingIds.Any(id => serverSettings.BanList.IsBanned(id, out banReason)))
{
Disconnect(conn, $"{DisconnectReason.Banned}/ {banReason}");
Disconnect(conn, PeerDisconnectPacket.Banned(banReason));
return;
}
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
OnMessageReceived?.Invoke(conn, packet.GetReadMessage(packetHeader.IsCompressed(), conn));
callbacks.OnMessageReceived.Invoke(conn, packet.GetReadMessage(packetHeader.IsCompressed(), conn));
}
}
@@ -275,12 +269,11 @@ namespace Barotrauma.Networking
{
DebugConsole.NewMessage("Owner disconnected: closing the server...");
GameServer.Log("Owner disconnected: closing the server...", ServerLog.MessageType.ServerMessage);
Close($"{DisconnectReason.ServerShutdown}/ Owner disconnected");
Close();
}
else
{
#warning TODO: kill off disconnect in layer 1
Disconnect(conn, $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == conn).Name}");
Disconnect(conn, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
}
}
else
@@ -288,7 +281,7 @@ namespace Barotrauma.Networking
PendingClient? pendingClient = pendingClients.Find(c => c.Connection is LidgrenConnection l && l.NetConnection == inc.SenderConnection);
if (pendingClient != null)
{
RemovePendingClient(pendingClient, DisconnectReason.Unknown, $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
}
}
@@ -312,9 +305,11 @@ namespace Barotrauma.Networking
{
if (status == Steamworks.AuthResponse.OK) { return; }
if (connectedClients.Find(c => c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId) is LidgrenConnection connection)
if (connectedClients.Find(c
=> c.AccountInfo.AccountId is Some<AccountId> { Value: SteamId id } && id.Value == steamId)
is LidgrenConnection connection)
{
Disconnect(connection, $"{DisconnectReason.SteamAuthenticationFailed}/ Steam authentication status changed: {status}");
Disconnect(connection, PeerDisconnectPacket.SteamAuthError(status));
}
return;
@@ -325,7 +320,7 @@ namespace Barotrauma.Networking
|| serverSettings.BanList.IsBanned(new SteamId(steamId), out banReason)
|| serverSettings.BanList.IsBanned(new SteamId(ownerId), out banReason))
{
RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason));
return;
}
@@ -337,7 +332,7 @@ namespace Barotrauma.Networking
}
else
{
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam authentication failed: {status}");
RemovePendingClient(pendingClient, PeerDisconnectPacket.SteamAuthError(status));
}
}
@@ -374,7 +369,7 @@ namespace Barotrauma.Networking
SendMsgInternal(conn, headers, body);
}
public override void Disconnect(NetworkConnection conn, string? msg = null)
public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket)
{
if (netServer == null) { return; }
@@ -384,11 +379,11 @@ namespace Barotrauma.Networking
{
lidgrenConn.Status = NetworkConnectionStatus.Disconnected;
connectedClients.Remove(lidgrenConn);
OnDisconnect?.Invoke(conn, msg);
callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket);
if (conn.AccountInfo.AccountId is Some<AccountId> { Value: SteamId steamId }) { SteamManager.StopAuthSession(steamId); }
}
lidgrenConn.NetConnection.Disconnect(msg ?? "Disconnected");
lidgrenConn.NetConnection.Disconnect(peerDisconnectPacket.ToLidgrenStringRepresentation());
}
protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
@@ -413,6 +408,7 @@ namespace Barotrauma.Networking
{
ownerKey = Option<int>.None();
OwnerConnection = pendingClient.Connection;
callbacks.OnOwnerDetermined.Invoke(OwnerConnection);
}
}
@@ -440,7 +436,7 @@ namespace Barotrauma.Networking
{
if (requireSteamAuth)
{
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: Steam ID not provided");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed));
return;
}
}
@@ -451,7 +447,7 @@ namespace Barotrauma.Networking
{
if (requireSteamAuth)
{
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, $"Steam auth session failed to start: {authSessionStartState}");
RemovePendingClient(pendingClient, PeerDisconnectPacket.SteamAuthError(authSessionStartState));
}
else
{
@@ -471,7 +467,7 @@ namespace Barotrauma.Networking
{
if (pendingClient.AccountInfo.AccountId != packet.SteamId.Select(uid => (AccountId)uid))
{
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "SteamID mismatch");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.SteamAuthenticationFailed));
}
}
}
@@ -9,26 +9,31 @@ namespace Barotrauma.Networking
{
internal abstract class ServerPeer
{
public delegate void MessageCallback(NetworkConnection connection, IReadMessage message);
public readonly record struct Callbacks(
Callbacks.MessageCallback OnMessageReceived,
Callbacks.DisconnectCallback OnDisconnect,
Callbacks.InitializationCompleteCallback OnInitializationComplete,
Callbacks.ShutdownCallback OnShutdown,
Callbacks.OwnerDeterminedCallback OnOwnerDetermined)
{
public delegate void MessageCallback(NetworkConnection connection, IReadMessage message);
public delegate void DisconnectCallback(NetworkConnection connection, PeerDisconnectPacket peerDisconnectPacket);
public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName);
public delegate void ShutdownCallback();
public delegate void OwnerDeterminedCallback(NetworkConnection connection);
}
public delegate void DisconnectCallback(NetworkConnection connection, string? reason);
public delegate void InitializationCompleteCallback(NetworkConnection connection, string? clientName);
public delegate void ShutdownCallback();
public delegate void OwnerDeterminedCallback(NetworkConnection connection);
public MessageCallback? OnMessageReceived;
public DisconnectCallback? OnDisconnect;
public InitializationCompleteCallback? OnInitializationComplete;
public ShutdownCallback? OnShutdown;
public OwnerDeterminedCallback? OnOwnerDetermined;
protected readonly Callbacks callbacks;
protected ServerPeer(Callbacks callbacks)
{
this.callbacks = callbacks;
}
public abstract void InitializeSteamServerCallbacks();
public abstract void Start();
public abstract void Close(string? msg = null);
public abstract void Close();
public abstract void Update(float deltaTime);
protected sealed class PendingClient
@@ -84,15 +89,16 @@ namespace Barotrauma.Networking
if (!Client.IsValidName(authPacket.Name, serverSettings))
{
RemovePendingClient(pendingClient, DisconnectReason.InvalidName, "");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.InvalidName));
return;
}
bool isCompatibleVersion = NetworkMember.IsCompatible(authPacket.GameVersion, GameMain.Version.ToString()) ?? false;
bool isCompatibleVersion =
Version.TryParse(authPacket.GameVersion, out var remoteVersion)
&& NetworkMember.IsCompatible(remoteVersion, GameMain.Version);
if (!isCompatibleVersion)
{
RemovePendingClient(pendingClient, DisconnectReason.InvalidVersion,
$"DisconnectMessage.InvalidVersion~[version]={GameMain.Version}~[clientversion]={authPacket.GameVersion}");
RemovePendingClient(pendingClient, PeerDisconnectPacket.InvalidVersion());
GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", ServerLog.MessageType.Error);
DebugConsole.NewMessage($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (incompatible game version)", Microsoft.Xna.Framework.Color.Red);
@@ -104,7 +110,7 @@ namespace Barotrauma.Networking
Client nameTaken = GameMain.Server.ConnectedClients.Find(c => Homoglyphs.Compare(c.Name.ToLower(), authPacket.Name.ToLower()));
if (nameTaken != null)
{
RemovePendingClient(pendingClient, DisconnectReason.NameTaken, "");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.NameTaken));
GameServer.Log($"{authPacket.Name} ({authPacket.SteamId}) couldn't join the server (name too similar to the name of the client \"" + nameTaken.Name + "\").", ServerLog.MessageType.Error);
return;
}
@@ -135,7 +141,7 @@ namespace Barotrauma.Networking
{
const string banMsg = "Failed to enter correct password too many times";
BanPendingClient(pendingClient, banMsg, null);
RemovePendingClient(pendingClient, DisconnectReason.Banned, banMsg);
RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banMsg));
return;
}
}
@@ -190,13 +196,13 @@ namespace Barotrauma.Networking
{
if (IsPendingClientBanned(pendingClient, out string? banReason))
{
RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason));
return;
}
if (connectedClients.Count >= serverSettings.MaxPlayers)
{
RemovePendingClient(pendingClient, DisconnectReason.ServerFull, "");
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.ServerFull));
}
if (pendingClient.InitializationStep == ConnectionInitialization.Success)
@@ -205,15 +211,15 @@ namespace Barotrauma.Networking
connectedClients.Add(newConnection);
pendingClients.Remove(pendingClient);
CheckOwnership(pendingClient);
callbacks.OnInitializationComplete.Invoke(newConnection, pendingClient.Name);
OnInitializationComplete?.Invoke(newConnection, pendingClient.Name);
CheckOwnership(pendingClient);
}
pendingClient.TimeOut -= Timing.Step;
if (pendingClient.TimeOut < 0.0)
{
RemovePendingClient(pendingClient, DisconnectReason.Unknown, Lidgren.Network.NetConnection.NoResponseMessage);
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Timeout));
}
if (Timing.TotalTime < pendingClient.UpdateTime) { return; }
@@ -237,7 +243,7 @@ namespace Barotrauma.Networking
structToSend = new ServerPeerContentPackageOrderPacket
{
ServerName = GameMain.Server.ServerName,
ContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent)
ContentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent || cp.Files.All(f => f is SubmarineFile))
.Select(contentPackage => new ServerContentPackage(contentPackage, timeNow))
.ToImmutableArray()
};
@@ -267,11 +273,11 @@ namespace Barotrauma.Networking
protected virtual void CheckOwnership(PendingClient pendingClient) { }
protected void RemovePendingClient(PendingClient pendingClient, DisconnectReason reason, string? msg)
protected void RemovePendingClient(PendingClient pendingClient, PeerDisconnectPacket peerDisconnectPacket)
{
if (pendingClients.Contains(pendingClient))
{
Disconnect(pendingClient.Connection, $"{reason}/{msg}");
Disconnect(pendingClient.Connection, peerDisconnectPacket);
pendingClients.Remove(pendingClient);
@@ -285,6 +291,6 @@ namespace Barotrauma.Networking
}
public abstract void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod, bool compressPastThreshold = true);
public abstract void Disconnect(NetworkConnection conn, string? msg = null);
public abstract void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket);
}
}
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
namespace Barotrauma.Networking
{
@@ -16,7 +17,7 @@ namespace Barotrauma.Networking
private SteamId ReadSteamId(IReadMessage inc) => new SteamId(inc.ReadUInt64() ^ ownerKey64);
private void WriteSteamId(IWriteMessage msg, SteamId val) => msg.WriteUInt64(val.Value ^ ownerKey64);
public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings)
public SteamP2PServerPeer(SteamId steamId, int ownerKey, ServerSettings settings, Callbacks callbacks) : base(callbacks)
{
serverSettings = settings;
@@ -43,7 +44,7 @@ namespace Barotrauma.Networking
started = true;
}
public override void Close(string? msg = null)
public override void Close()
{
if (!started) { return; }
@@ -51,12 +52,12 @@ namespace Barotrauma.Networking
for (int i = pendingClients.Count - 1; i >= 0; i--)
{
RemovePendingClient(pendingClients[i], DisconnectReason.ServerShutdown, msg);
RemovePendingClient(pendingClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
}
for (int i = connectedClients.Count - 1; i >= 0; i--)
{
Disconnect(connectedClients[i], msg ?? DisconnectReason.ServerShutdown.ToString());
Disconnect(connectedClients[i], PeerDisconnectPacket.WithReason(DisconnectReason.ServerShutdown));
}
pendingClients.Clear();
@@ -64,19 +65,13 @@ namespace Barotrauma.Networking
ChildServerRelay.ShutDown();
OnShutdown?.Invoke();
callbacks.OnShutdown.Invoke();
}
public override void Update(float deltaTime)
{
if (!started) { return; }
if (OnOwnerDetermined != null && OwnerConnection != null)
{
OnOwnerDetermined?.Invoke(OwnerConnection);
OnOwnerDetermined = null;
}
//backwards for loop so we can remove elements while iterating
for (int i = connectedClients.Count - 1; i >= 0; i--)
{
@@ -84,7 +79,7 @@ namespace Barotrauma.Networking
conn.Decay(deltaTime);
if (conn.Timeout < 0.0)
{
Disconnect(conn, "Timed out");
Disconnect(conn, PeerDisconnectPacket.WithReason(DisconnectReason.Timeout));
}
}
@@ -149,24 +144,22 @@ namespace Barotrauma.Networking
{
if (pendingClient != null)
{
RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
RemovePendingClient(pendingClient, PeerDisconnectPacket.Banned(banReason));
}
else if (connectedClient != null)
{
Disconnect(connectedClient, $"{DisconnectReason.Banned}/ {banReason}");
Disconnect(connectedClient, PeerDisconnectPacket.Banned(banReason));
}
}
else if (packetHeader.IsDisconnectMessage())
{
if (pendingClient != null)
{
string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}";
RemovePendingClient(pendingClient, DisconnectReason.Unknown, disconnectMsg);
RemovePendingClient(pendingClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
}
else if (connectedClient != null)
{
string disconnectMsg = $"ServerMessage.HasDisconnected~[client]={GameMain.Server.ConnectedClients.First(c => c.Connection == connectedClient).Name}";
Disconnect(connectedClient, disconnectMsg, false);
Disconnect(connectedClient, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
}
}
else if (packetHeader.IsHeartbeatMessage())
@@ -176,28 +169,27 @@ namespace Barotrauma.Networking
}
else if (packetHeader.IsConnectionInitializationStep())
{
if (!initialization.HasValue) { return; }
ConnectionInitialization initializationStep = initialization.Value;
if (pendingClient != null)
{
pendingClient.Connection.SetAccountInfo(new AccountInfo(senderSteamId, sentOwnerSteamId));
ReadConnectionInitializationStep(
pendingClient,
new ReadWriteMessage(inc.Buffer, inc.BitPosition, inc.LengthBits, false),
initialization ?? throw new Exception("Initialization step missing"));
initializationStep);
}
else if (initialization.HasValue)
else if (initializationStep == ConnectionInitialization.ConnectionStarted)
{
ConnectionInitialization initializationStep = initialization.Value;
if (initializationStep == ConnectionInitialization.ConnectionStarted)
{
pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId)));
}
pendingClients.Add(new PendingClient(new SteamP2PConnection(senderSteamId)));
}
}
else if (connectedClient != null)
{
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, connectedClient);
OnMessageReceived?.Invoke(connectedClient, msg);
callbacks.OnMessageReceived.Invoke(connectedClient, msg);
}
}
else //sender is owner
@@ -227,7 +219,8 @@ namespace Barotrauma.Networking
};
OwnerConnection.SetAccountInfo(new AccountInfo(ownerSteamId, ownerSteamId));
OnInitializationComplete?.Invoke(OwnerConnection, packet.OwnerName);
callbacks.OnInitializationComplete.Invoke(OwnerConnection, packet.OwnerName);
callbacks.OnOwnerDetermined.Invoke(OwnerConnection);
}
return;
@@ -241,7 +234,7 @@ namespace Barotrauma.Networking
{
var packet = INetSerializableStruct.Read<PeerPacketMessage>(inc);
IReadMessage msg = new ReadOnlyMessage(packet.Buffer, packetHeader.IsCompressed(), 0, packet.Length, OwnerConnection);
OnMessageReceived?.Invoke(OwnerConnection!, msg);
callbacks.OnMessageReceived.Invoke(OwnerConnection!, msg);
}
}
}
@@ -281,27 +274,21 @@ namespace Barotrauma.Networking
SendMsgInternal(steamP2PConn, headers, body);
}
private void SendDisconnectMessage(SteamId steamId, string? msg)
private void SendDisconnectMessage(SteamId steamId, PeerDisconnectPacket peerDisconnectPacket)
{
if (!started) { return; }
if (string.IsNullOrWhiteSpace(msg)) { return; }
var headers = new PeerPacketHeaders
{
DeliveryMethod = DeliveryMethod.Reliable,
PacketHeader = PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage,
Initialization = null
};
var packet = new PeerDisconnectPacket
{
Message = msg
};
SendMsgInternal(steamId, headers, packet);
SendMsgInternal(steamId, headers, peerDisconnectPacket);
}
private void Disconnect(NetworkConnection conn, string? msg, bool sendDisconnectMessage)
public override void Disconnect(NetworkConnection conn, PeerDisconnectPacket peerDisconnectPacket)
{
if (!started) { return; }
@@ -309,26 +296,21 @@ namespace Barotrauma.Networking
if (!conn.AccountInfo.AccountId.TryUnwrap(out var connAccountId) || !(connAccountId is SteamId connSteamId)) { return; }
if (sendDisconnectMessage) { SendDisconnectMessage(connSteamId, msg); }
SendDisconnectMessage(connSteamId, peerDisconnectPacket);
if (connectedClients.Contains(steamp2pConn))
{
steamp2pConn.Status = NetworkConnectionStatus.Disconnected;
connectedClients.Remove(steamp2pConn);
OnDisconnect?.Invoke(conn, msg);
callbacks.OnDisconnect.Invoke(conn, peerDisconnectPacket);
Steam.SteamManager.StopAuthSession(connSteamId);
}
else if (steamp2pConn == OwnerConnection)
{
//TODO: fix?
throw new InvalidOperationException("Cannot disconnect owner peer");
}
}
public override void Disconnect(NetworkConnection conn, string? msg = null)
{
Disconnect(conn, msg, true);
}
protected override void SendMsgInternal(NetworkConnection conn, PeerPacketHeaders headers, INetSerializableStruct? body)
{
var connSteamId = conn is SteamP2PConnection { Endpoint: SteamP2PEndpoint { SteamId: var id } } ? id : null;
@@ -505,9 +505,10 @@ namespace Barotrauma.Networking
var characterData = campaign?.GetClientCharacterData(clients[i]);
if (characterData != null && Level.Loaded?.Type != LevelData.LevelType.Outpost && characterData.HasSpawned)
{
//we need to reapply the previous respawn penalty affliction or successive deaths won't make it stack
characterData.ApplyHealthData(character, (AfflictionPrefab ap) => ap == GetRespawnPenaltyAfflictionPrefab());
GiveRespawnPenaltyAffliction(character);
}
if (characterData == null || characterData.HasSpawned)
{
//give the character the items they would've gotten if they had spawned in the main sub
@@ -555,7 +556,7 @@ namespace Barotrauma.Networking
foreach (Skill skill in characterInfo.Job.GetSkills())
{
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
if (skillPrefab == null) { continue; }
if (skillPrefab == null || skill.Level < skillPrefab.LevelRange.End) { continue; }
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillReductionOnDeath);
}
}
@@ -18,10 +18,14 @@ namespace Barotrauma.Networking
{
if (!PropEquals(lastSyncedValue, Value))
{
LastUpdateID = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID);
LastUpdateID = GameMain.NetLobbyScreen.LastUpdateID;
lastSyncedValue = Value;
}
}
public void ForceUpdate()
{
LastUpdateID = GameMain.NetLobbyScreen.LastUpdateID++;
}
}
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
@@ -54,6 +58,15 @@ namespace Barotrauma.Networking
LoadClientPermissions();
}
public void ForcePropertyUpdate()
{
UpdateFlag(NetFlags.Properties);
foreach (NetPropertyData property in netProperties.Values)
{
property.ForceUpdate();
}
}
private void WriteNetProperties(IWriteMessage outMsg, Client c)
{
foreach (UInt32 key in netProperties.Keys)
@@ -197,27 +210,32 @@ namespace Barotrauma.Networking
{
int orBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
int andBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
GameMain.NetLobbyScreen.MissionType = (Barotrauma.MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits);
GameMain.NetLobbyScreen.MissionType = (MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits);
int traitorSetting = (int)TraitorsEnabled + incMsg.ReadByte() - 1;
if (traitorSetting < 0) traitorSetting = 2;
if (traitorSetting > 2) traitorSetting = 0;
if (traitorSetting < 0) { traitorSetting = 2; }
if (traitorSetting > 2) { traitorSetting = 0; }
TraitorsEnabled = (YesNoMaybe)traitorSetting;
int botCount = BotCount + incMsg.ReadByte() - 1;
if (botCount < 0) botCount = MaxBotCount;
if (botCount > MaxBotCount) botCount = 0;
if (botCount < 0) { botCount = MaxBotCount; }
if (botCount > MaxBotCount) { botCount = 0; }
BotCount = botCount;
int botSpawnMode = (int)BotSpawnMode + incMsg.ReadByte() - 1;
if (botSpawnMode < 0) botSpawnMode = 1;
if (botSpawnMode > 1) botSpawnMode = 0;
if (botSpawnMode < 0) { botSpawnMode = 1; }
if (botSpawnMode > 1) { botSpawnMode = 0; }
BotSpawnMode = (BotSpawnMode)botSpawnMode;
float levelDifficulty = incMsg.ReadSingle();
if (levelDifficulty >= 0.0f) SelectedLevelDifficulty = levelDifficulty;
if (levelDifficulty >= 0.0f) { SelectedLevelDifficulty = levelDifficulty; }
UseRespawnShuttle = incMsg.ReadBoolean();
bool changedUseRespawnShuttle = incMsg.ReadBoolean();
bool useRespawnShuttle = incMsg.ReadBoolean();
if (changedUseRespawnShuttle)
{
UseRespawnShuttle = useRespawnShuttle;
}
bool changedAutoRestart = incMsg.ReadBoolean();
bool autoRestart = incMsg.ReadBoolean();
@@ -216,6 +216,14 @@ namespace Barotrauma
}
}
public void ResetVotes(IEnumerable<Client> connectedClients, bool resetKickVotes)
{
foreach (Client client in connectedClients)
{
client.ResetVotes(resetKickVotes);
}
}
public void ServerRead(IReadMessage inc, Client sender)
{
if (GameMain.Server == null || sender == null) { return; }