Release 1.10.5.0 - Autumn Update 2025
This commit is contained in:
@@ -1850,6 +1850,10 @@ namespace Barotrauma
|
||||
HandleCommandForCrewOrSingleCharacter(args, ToggleGodMode, client);
|
||||
void ToggleGodMode(Character targetCharacter)
|
||||
{
|
||||
if (args.Length > 1 && bool.TryParse(args[1], out bool removeafflictions))
|
||||
{
|
||||
if (removeafflictions) { targetCharacter.CharacterHealth.RemoveAllAfflictions(); }
|
||||
}
|
||||
targetCharacter.GodMode = godmodeStateOnFirstCharacter ?? !targetCharacter.GodMode;
|
||||
godmodeStateOnFirstCharacter = targetCharacter.GodMode;
|
||||
GameMain.NetworkMember.CreateEntityEvent(targetCharacter, new Character.CharacterStatusEventData());
|
||||
|
||||
+5
-2
@@ -1530,9 +1530,12 @@ namespace Barotrauma
|
||||
modeElement.Add(GameMain.GameSession?.EventManager.Save());
|
||||
}
|
||||
|
||||
foreach (Identifier unlockedRecipe in GameMain.GameSession.UnlockedRecipes)
|
||||
foreach ((CharacterTeamType team, Identifier unlockedRecipe) in GameMain.GameSession.UnlockedRecipes)
|
||||
{
|
||||
modeElement.Add(new XElement("unlockedrecipe", new XAttribute("identifier", unlockedRecipe)));
|
||||
modeElement.Add(
|
||||
new XElement("unlockedrecipe",
|
||||
new XAttribute("identifier", unlockedRecipe),
|
||||
new XAttribute("team", team)));
|
||||
}
|
||||
|
||||
CampaignMetadata?.Save(modeElement);
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Barotrauma.Items.Components
|
||||
const float NetworkUpdateInterval = 5.0f;
|
||||
private float networkUpdateTimer;
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime)
|
||||
partial void UpdateNetworking(float deltaTime)
|
||||
{
|
||||
networkUpdateTimer -= deltaTime;
|
||||
if (networkUpdateTimer <= 0.0f)
|
||||
@@ -51,6 +51,7 @@ namespace Barotrauma.Items.Components
|
||||
msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10);
|
||||
msg.WriteBoolean(IsActive);
|
||||
msg.WriteBoolean(Hijacked);
|
||||
msg.WriteBoolean(Disabled);
|
||||
if (TargetLevel != null)
|
||||
{
|
||||
msg.WriteBoolean(true);
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class WifiComponent
|
||||
{
|
||||
private readonly int[] networkReceivedChannelMemory = new int[ChannelMemorySize];
|
||||
|
||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
SharedEventWrite(msg);
|
||||
@@ -11,8 +13,21 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ServerEventRead(IReadMessage msg, Client c)
|
||||
{
|
||||
SharedEventRead(msg);
|
||||
|
||||
int newChannel = msg.ReadRangedInteger(MinChannel, MaxChannel);
|
||||
for (int i = 0; i < ChannelMemorySize; i++)
|
||||
{
|
||||
networkReceivedChannelMemory[i] = msg.ReadRangedInteger(MinChannel, MaxChannel);
|
||||
}
|
||||
|
||||
if (item.CanClientAccess(c))
|
||||
{
|
||||
Channel = newChannel;
|
||||
for (int i = 0; i < ChannelMemorySize; i++)
|
||||
{
|
||||
channelMemory[i] = networkReceivedChannelMemory[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Create an event to notify other clients about the changes
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Barotrauma
|
||||
ServerLogRemovedItems();
|
||||
|
||||
#region local functions
|
||||
bool IsInventoryAccessible() => sender.Character.CanAccessInventory(this, IsDragAndDropGiveAllowed ? CharacterInventory.AccessLevel.Allowed : CharacterInventory.AccessLevel.Limited);
|
||||
bool IsInventoryAccessible() => sender.Character.CanAccessInventory(this, IsDragAndDropGiveAllowed ? CharacterInventory.AccessLevel.AllowFriendly : CharacterInventory.AccessLevel.AllowBotsAndPets);
|
||||
|
||||
void CreateCorrectiveNetworkEvent()
|
||||
{
|
||||
@@ -177,7 +177,7 @@ namespace Barotrauma
|
||||
if (item.GetComponent<Pickable>() is not Pickable pickable ||
|
||||
(pickable.IsAttached && !pickable.PickingDone) || item.AllowedSlots.None() || !item.IsInteractable(sender.Character))
|
||||
{
|
||||
DebugConsole.AddWarning($"Client {sender.Name} tried to pick up a non-pickable item \"{item}\" (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"})",
|
||||
DebugConsole.AddWarning($"Client {sender.Name} failed to put \"{item}\" in the inventory of {Owner} (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"})",
|
||||
item.Prefab.ContentPackage);
|
||||
continue;
|
||||
}
|
||||
@@ -187,13 +187,20 @@ namespace Barotrauma
|
||||
var holdable = item.GetComponent<Holdable>();
|
||||
if (holdable != null && !holdable.CanBeDeattached()) { continue; }
|
||||
|
||||
|
||||
bool itemAccessDenied = !prevItems.Contains(item) && !itemAccessibility[item] &&
|
||||
(sender.Character == null || item.PreviousParentInventory == null || !sender.Character.CanAccessInventory(item.PreviousParentInventory));
|
||||
|
||||
//more restricted "adding" of handcuffs: we can't allow putting handcuffs on a player just because dragging and dropping is allowed
|
||||
if (item.HasTag(Tags.HandLockerItem) && !itemAccessDenied)
|
||||
{
|
||||
itemAccessDenied =
|
||||
!sender.Character.CanAccessInventory(this, CharacterInventory.AccessLevel.AllowBotsAndPets);
|
||||
}
|
||||
if (itemAccessDenied)
|
||||
{
|
||||
#if DEBUG || UNSTABLE
|
||||
DebugConsole.NewMessage($"Client {sender.Name} failed to pick up item \"{item}\" (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"}). No access.", Color.Yellow);
|
||||
DebugConsole.NewMessage($"Client {sender.Name} failed to put \"{item}\" in the inventory of {Owner} (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"}). No access.", Color.Yellow);
|
||||
#endif
|
||||
if (item.body != null && !sender.PendingPositionUpdates.Contains(item))
|
||||
{
|
||||
|
||||
@@ -3716,7 +3716,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
UpdateVoteStatus();
|
||||
|
||||
SendChatMessage(peerDisconnectPacket.ChatMessage(client).Value, ChatMessageType.Server, changeType: peerDisconnectPacket.ConnectionChangeType);
|
||||
SendChatMessage(peerDisconnectPacket.ChatMessage(client.Name).Value, ChatMessageType.Server, changeType: peerDisconnectPacket.ConnectionChangeType);
|
||||
|
||||
UpdateCrewFrame();
|
||||
|
||||
@@ -4234,13 +4234,14 @@ namespace Barotrauma.Networking
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void UnlockRecipe(Identifier identifier)
|
||||
public void UnlockRecipe(CharacterTeamType team, Identifier identifier)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.UNLOCKRECIPE);
|
||||
msg.WriteByte((byte)team);
|
||||
msg.WriteIdentifier(identifier);
|
||||
foreach (var client in connectedClients)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.UNLOCKRECIPE);
|
||||
msg.WriteIdentifier(identifier);
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
+50
-2
@@ -137,6 +137,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Disconnect(connectedClient.Connection, PeerDisconnectPacket.Banned(banReason));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendDisconnectMessage(senderEndpoint, PeerDisconnectPacket.Banned(banReason));
|
||||
}
|
||||
}
|
||||
else if (packetHeader.IsDisconnectMessage())
|
||||
{
|
||||
@@ -149,9 +153,10 @@ namespace Barotrauma.Networking
|
||||
Disconnect(connectedClient.Connection, PeerDisconnectPacket.WithReason(DisconnectReason.Disconnected));
|
||||
}
|
||||
}
|
||||
else if (packetHeader.IsHeartbeatMessage())
|
||||
else if (packetHeader.IsHeartbeatMessage() || packetHeader.IsDoSProtectionMessage())
|
||||
{
|
||||
//message exists solely as a heartbeat, ignore its contents
|
||||
// ignore these messages, heartbeat messages just need to be acknowledged,
|
||||
// and only the owner should be sending DoS protection messages
|
||||
return;
|
||||
}
|
||||
else if (packetHeader.IsConnectionInitializationStep())
|
||||
@@ -206,6 +211,49 @@ namespace Barotrauma.Networking
|
||||
return;
|
||||
}
|
||||
|
||||
if (packetHeader.IsDoSProtectionMessage())
|
||||
{
|
||||
var packet = INetSerializableStruct.Read<DoSProtectionPacket>(inc);
|
||||
var disconnectPacket = INetSerializableStruct.Read<PeerDisconnectPacket>(inc);
|
||||
|
||||
if (packet.Endpoint.TryUnwrap(out var endpoint))
|
||||
{
|
||||
PendingClient? pendingClient = pendingClients.Find(c => c.Connection.Endpoint == endpoint);
|
||||
ClientConnectionData? connectedClientData = connectedClients.Find(c => c.Connection.Endpoint == endpoint);
|
||||
string? clientName;
|
||||
|
||||
if (pendingClient != null)
|
||||
{
|
||||
clientName = pendingClient.Name;
|
||||
if (packet.ShouldBan)
|
||||
{
|
||||
BanPendingClient(pendingClient, disconnectPacket.AdditionalInformation, duration: null);
|
||||
}
|
||||
RemovePendingClient(pendingClient, disconnectPacket);
|
||||
}
|
||||
else if (connectedClientData != null)
|
||||
{
|
||||
clientName = connectedClientData.TryGetClientName();
|
||||
if (packet.ShouldBan)
|
||||
{
|
||||
connectedClientData.BanClient(serverSettings, disconnectPacket.AdditionalInformation, duration: null);
|
||||
}
|
||||
Disconnect(connectedClientData.Connection, disconnectPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Unable to remove client {endpoint} for triggering DoS protection, client not found in pending or connected clients";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameServer.Log(errorMsg, ServerLog.MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
GameServer.Log($"Client {clientName ?? endpoint.ToString()} {(packet.ShouldBan ? "banned" : "disconnected")} due to DoS protection (Sending too many packets).", ServerLog.MessageType.DoSProtection);
|
||||
GameMain.Server?.SendChatMessage(disconnectPacket.ChatMessage(clientName).Value, ChatMessageType.Server, changeType: disconnectPacket.ConnectionChangeType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (OwnerConnection is null)
|
||||
|
||||
+47
-11
@@ -13,7 +13,7 @@ namespace Barotrauma.Networking
|
||||
protected ServerPeer(Callbacks callbacks, ServerSettings serverSettings) : base(callbacks)
|
||||
{
|
||||
this.serverSettings = serverSettings;
|
||||
this.connectedClients = new List<ConnectedClient>();
|
||||
this.connectedClients = new List<ClientConnectionData>();
|
||||
this.pendingClients = new List<PendingClient>();
|
||||
|
||||
List<ContentPackage> contentPackageList = new List<ContentPackage>();
|
||||
@@ -65,21 +65,57 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
protected sealed class ConnectedClient
|
||||
protected sealed class ClientConnectionData(TConnection connection)
|
||||
{
|
||||
public readonly TConnection Connection;
|
||||
public readonly MessageFragmenter Fragmenter;
|
||||
public readonly MessageDefragmenter Defragmenter;
|
||||
public readonly TConnection Connection = connection;
|
||||
public readonly MessageFragmenter Fragmenter = new();
|
||||
public readonly MessageDefragmenter Defragmenter = new();
|
||||
|
||||
public ConnectedClient(TConnection connection)
|
||||
/// <summary>
|
||||
/// Attempts to retrieve the name of the client associated with this connection
|
||||
/// from a higher layer.
|
||||
/// </summary>
|
||||
/// <returns>Name of the client if found, null otherwise.</returns>
|
||||
public string? TryGetClientName()
|
||||
{
|
||||
Connection = connection;
|
||||
Fragmenter = new();
|
||||
Defragmenter = new();
|
||||
if (GameMain.Server?.ConnectedClients is { } connClients)
|
||||
{
|
||||
foreach (Client? client in connClients)
|
||||
{
|
||||
if (client?.Connection is not { } clientConnection) { continue; }
|
||||
|
||||
if (clientConnection.EndpointMatches(Connection.Endpoint) )
|
||||
{
|
||||
return client.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void BanClient(ServerSettings settings, string banReason, TimeSpan? duration)
|
||||
{
|
||||
string clientName = TryGetClientName() ?? "Player";
|
||||
|
||||
Connection.AccountInfo.OtherMatchingIds.ForEach(BanAccountId);
|
||||
|
||||
if (Connection.AccountInfo.AccountId.TryUnwrap(out var accountId))
|
||||
{
|
||||
BanAccountId(accountId);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.BanList.BanPlayer(clientName, Connection.Endpoint, banReason, duration);
|
||||
}
|
||||
return;
|
||||
|
||||
void BanAccountId(AccountId id)
|
||||
=> settings.BanList.BanPlayer(clientName, id, banReason, duration);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly List<ConnectedClient> connectedClients;
|
||||
protected readonly List<ClientConnectionData> connectedClients;
|
||||
protected readonly List<PendingClient> pendingClients;
|
||||
protected readonly ServerSettings serverSettings;
|
||||
|
||||
@@ -235,7 +271,7 @@ namespace Barotrauma.Networking
|
||||
if (pendingClient.InitializationStep == ConnectionInitialization.Success)
|
||||
{
|
||||
TConnection newConnection = pendingClient.Connection;
|
||||
connectedClients.Add(new ConnectedClient(newConnection));
|
||||
connectedClients.Add(new ClientConnectionData(newConnection));
|
||||
pendingClients.Remove(pendingClient);
|
||||
|
||||
callbacks.OnInitializationComplete.Invoke(newConnection, pendingClient.Name);
|
||||
|
||||
Reference in New Issue
Block a user