diff --git a/.github/DISCUSSION_TEMPLATE/bug-reports.yml b/.github/DISCUSSION_TEMPLATE/bug-reports.yml index 86b2fa804..29cf8bd5a 100644 --- a/.github/DISCUSSION_TEMPLATE/bug-reports.yml +++ b/.github/DISCUSSION_TEMPLATE/bug-reports.yml @@ -73,7 +73,7 @@ body: label: Version description: Which version of the game did the bug happen in? You can see the current version number in the bottom left corner of your screen in the main menu. options: - - v1.10.6.0 (Autumn Update 2025 Hotfix 1) + - v1.10.7.0 (Autumn Update 2025 Hotfix 2) - Other validations: required: true diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 1f11c405f..f43925557 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -3818,9 +3818,12 @@ namespace Barotrauma.Networking outMsg.WriteUInt16(eventId); outMsg.WriteUInt16(entityId); outMsg.WriteByte((byte)Submarine.Loaded.Count); - foreach (Submarine sub in Submarine.Loaded) + //server has restrictions on the length and number of subs listed in the error (see GameServer.HandleClientError), + //let's adhere to those + foreach (Submarine sub in Submarine.Loaded.Take(5)) { - outMsg.WriteString(sub.Info.Name); + string subNameTruncated = sub.Info.Name.Length > 16 ? sub.Info.Name.Substring(0, 16) : sub.Info.Name; + outMsg.WriteString(subNameTruncated); } break; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs index 21c9b94c8..24061c7e7 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs @@ -2703,34 +2703,40 @@ namespace Barotrauma }; new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), minDifficultyGroup.RectTransform), TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true); - var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), minDifficultyGroup.RectTransform), NumberType.Int) + var minLevelDifficultyInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), minDifficultyGroup.RectTransform), NumberType.Int) { IntValue = (int)(extraSubInfo?.MinLevelDifficulty ?? 0), MinValueInt = 0, MaxValueInt = 100, OnValueChanged = (numberInput) => { - extraSubInfo.MinLevelDifficulty = numberInput.IntValue; + if (GetExtraSubmarineInfo(MainSub?.Info) is { } extraSubInfo) + { + extraSubInfo.MinLevelDifficulty = numberInput.IntValue; + } } }; - minDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize; + minDifficultyGroup.RectTransform.MaxSize = minLevelDifficultyInput.TextBox.RectTransform.MaxSize; var maxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), maxDifficultyGroup.RectTransform), TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true); - numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), maxDifficultyGroup.RectTransform), NumberType.Int) + var maxLevelDifficultyInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), maxDifficultyGroup.RectTransform), NumberType.Int) { IntValue = (int)(extraSubInfo?.MaxLevelDifficulty ?? 100), MinValueInt = 0, MaxValueInt = 100, OnValueChanged = (numberInput) => { - extraSubInfo.MaxLevelDifficulty = numberInput.IntValue; + if (GetExtraSubmarineInfo(MainSub?.Info) is { } extraSubInfo) + { + extraSubInfo.MaxLevelDifficulty = numberInput.IntValue; + } } }; - maxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize; + maxDifficultyGroup.RectTransform.MaxSize = maxLevelDifficultyInput.TextBox.RectTransform.MaxSize; GUITextBox missionTagsBox = CreateMissionTagsUI(extraSettingsContainer, extraSubInfo?.MissionTags ?? Enumerable.Empty(), ChangeMissionTags); @@ -2810,7 +2816,7 @@ namespace Barotrauma }; new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), enemySubmarineRewardGroup.RectTransform), TextManager.Get("enemysub.reward"), textAlignment: Alignment.CenterLeft, wrap: true); - numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), enemySubmarineRewardGroup.RectTransform), NumberType.Int, buttonVisibility: GUINumberInput.ButtonVisibility.ForceHidden) + var enemySubRewardInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), enemySubmarineRewardGroup.RectTransform), NumberType.Int, buttonVisibility: GUINumberInput.ButtonVisibility.ForceHidden) { IntValue = (int)(MainSub?.Info?.EnemySubmarineInfo?.Reward ?? 4000), MinValueInt = 0, @@ -2820,14 +2826,14 @@ namespace Barotrauma MainSub.Info.EnemySubmarineInfo.Reward = numberInput.IntValue; } }; - enemySubmarineRewardGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize; + enemySubmarineRewardGroup.RectTransform.MaxSize = enemySubRewardInput.TextBox.RectTransform.MaxSize; var enemySubmarineDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), enemySubmarineSettingsContainer.RectTransform), isHorizontal: true) { Stretch = true }; new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), enemySubmarineDifficultyGroup.RectTransform), TextManager.Get("preferreddifficulty"), textAlignment: Alignment.CenterLeft, wrap: true); - numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), enemySubmarineDifficultyGroup.RectTransform), NumberType.Int) + var enemySubDifficultyInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), enemySubmarineDifficultyGroup.RectTransform), NumberType.Int) { IntValue = (int)(MainSub?.Info?.EnemySubmarineInfo?.PreferredDifficulty ?? 50), MinValueInt = 0, @@ -2837,7 +2843,7 @@ namespace Barotrauma MainSub.Info.EnemySubmarineInfo.PreferredDifficulty = numberInput.IntValue; } }; - enemySubmarineDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize; + enemySubmarineDifficultyGroup.RectTransform.MaxSize = enemySubDifficultyInput.TextBox.RectTransform.MaxSize; //-------------------------------------------------------- @@ -3131,6 +3137,8 @@ namespace Barotrauma if (newExtraSubInfo != null) { missionTagsBox.Text = string.Join(',', newExtraSubInfo.MissionTags); + newExtraSubInfo.MinLevelDifficulty = minLevelDifficultyInput?.IntValue ?? 0; + newExtraSubInfo.MaxLevelDifficulty = maxLevelDifficultyInput?.IntValue ?? 100; } previewImageButtonHolder.Children.ForEach(c => c.Enabled = MainSub.Info.AllowPreviewImage); diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 106a24817..13be75dd3 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2024 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 771015d07..668089155 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2024 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index b3fc5e735..51b59200d 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2024 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 04aa4b0b0..bdca0bd3a 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2023 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index b4934b418..3e461451b 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2023 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index c06181b45..290f23d36 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -1064,52 +1064,74 @@ namespace Barotrauma.Networking string errorStr = "Unhandled error report"; string errorStrNoName = errorStr; - ClientNetError error = (ClientNetError)inc.ReadByte(); - switch (error) + bool malformedData = false; + try { - case ClientNetError.MISSING_EVENT: - UInt16 expectedID = inc.ReadUInt16(); - UInt16 receivedID = inc.ReadUInt16(); - errorStr = errorStrNoName = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString(); - break; - case ClientNetError.MISSING_ENTITY: - UInt16 eventID = inc.ReadUInt16(); - UInt16 entityID = inc.ReadUInt16(); - byte subCount = inc.ReadByte(); - List subNames = new List(); - for (int i = 0; i < subCount; i++) - { - subNames.Add(inc.ReadString()); - } - Entity entity = Entity.FindEntityByID(entityID); - if (entity == null) - { - errorStr = errorStrNoName = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ")."; - } - else if (entity is Character character) - { - errorStr = $"Missing character {character.Name} (event id {eventID}, entity id {entityID})."; - errorStrNoName = $"Missing character {character.SpeciesName} (event id {eventID}, entity id {entityID})."; - } - else if (entity is Item item) - { - errorStr = errorStrNoName = $"Missing item {item.Name}, sub: {item.Submarine?.Info?.Name ?? "none"} (event id {eventID}, entity id {entityID})."; - } - else - { - errorStr = errorStrNoName = $"Missing entity {entity}, sub: {entity.Submarine?.Info?.Name ?? "none"} (event id {eventID}, entity id {entityID})."; - } - if (GameStarted) - { - var serverSubNames = Submarine.Loaded.Select(s => s.Info.Name); - if (subCount != Submarine.Loaded.Count || !subNames.SequenceEqual(serverSubNames)) + ClientNetError error = (ClientNetError)inc.ReadByte(); + switch (error) + { + case ClientNetError.MISSING_EVENT: + UInt16 expectedID = inc.ReadUInt16(); + UInt16 receivedID = inc.ReadUInt16(); + errorStr = errorStrNoName = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString(); + break; + case ClientNetError.MISSING_ENTITY: + UInt16 eventID = inc.ReadUInt16(); + UInt16 entityID = inc.ReadUInt16(); + int subCount = inc.ReadByte(); + List subNames = new List(); + for (int i = 0; i < Math.Min(subCount, 5); i++) { - string subErrorStr = $" Loaded submarines don't match (client: {string.Join(", ", subNames)}, server: {string.Join(", ", serverSubNames)})."; - errorStr += subErrorStr; - errorStrNoName += subErrorStr; + string subName = inc.ReadString(); + if (subName == null || subName.Length > 16) + { + malformedData = true; + } + else + { + subNames.Add(subName); + } } - } - break; + Entity entity = Entity.FindEntityByID(entityID); + if (entity == null) + { + errorStr = errorStrNoName = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ")."; + } + else if (entity is Character character) + { + errorStr = $"Missing character {character.Name} (event id {eventID}, entity id {entityID})."; + errorStrNoName = $"Missing character {character.SpeciesName} (event id {eventID}, entity id {entityID})."; + } + else if (entity is Item item) + { + errorStr = errorStrNoName = $"Missing item {item.Name}, sub: {item.Submarine?.Info?.Name ?? "none"} (event id {eventID}, entity id {entityID})."; + } + else + { + errorStr = errorStrNoName = $"Missing entity {entity}, sub: {entity.Submarine?.Info?.Name ?? "none"} (event id {eventID}, entity id {entityID})."; + } + if (GameStarted) + { + var serverSubNames = Submarine.Loaded.Select(s => s.Info.Name); + if (subCount != Submarine.Loaded.Count || !subNames.SequenceEqual(serverSubNames)) + { + string subErrorStr = $" Loaded submarines don't match (client: {string.Join(", ", subNames)}, server: {string.Join(", ", serverSubNames)})."; + errorStr += subErrorStr; + errorStrNoName += subErrorStr; + } + } + break; + } + } + catch (Exception e) + { + DebugConsole.ThrowError($"Failed to read error data from the client {ClientLogName(c)}.", e); + malformedData = true; + } + if (malformedData) + { + KickClient(c, "Received malformed error data."); + return; } Log(ClientLogName(c) + " has reported an error: " + errorStr, ServerLog.MessageType.Error); @@ -1133,7 +1155,6 @@ namespace Barotrauma.Networking { KickClient(c, errorStr); } - } private void WriteEventErrorData(Client client, string errorStr) diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 6d1f33b66..9b465aea3 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 1.10.6.0 + 1.10.7.0 Copyright © FakeFish 2018-2023 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 105a78eed..9d3063420 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,4 +1,11 @@ ------------------------------------------------------------------------------------------------------------------------------------------------- +v1.10.7.0 +------------------------------------------------------------------------------------------------------------------------------------------------- + +- Additional fixes to multiplayer exploits. +- Fixed crashing when editing a beacon station's, wreck's or enemy sub's min/max level difficulty settings in the sub editor before you have saved the sub for the first time. + +------------------------------------------------------------------------------------------------------------------------------------------------- v1.10.6.0 ------------------------------------------------------------------------------------------------------------------------------------------------- @@ -9,7 +16,7 @@ v1.10.6.0 - Railgun shells now disappear shortly after the first impact: the change in the previous update (which allowed them to penetrate multiple limbs/targets) had the side-effect that a shell that went through a single limb could fall back on the submarine and still do full damage. ------------------------------------------------------------------------------------------------------------------------------------------------- -v1.10.5.0 +v1.10.5.0 (Autumn Update 2025) ------------------------------------------------------------------------------------------------------------------------------------------------- Balance: