Reapply "OBT1.1.0 Merge branch 'dev_pte' into dev"

This reverts commit 046483b9da.
This commit is contained in:
NotAlwaysTrue
2026-04-30 21:59:54 +08:00
parent 02689d0d86
commit 25683dcf39
85 changed files with 2413 additions and 779 deletions
@@ -8,6 +8,7 @@ using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using System.Linq;
namespace Barotrauma.Items.Components
{
@@ -688,12 +689,14 @@ namespace Barotrauma.Items.Components
item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: User), positionOut);
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
// Use ToList() snapshot for thread-safe iteration
var signalRecipients = item.LastSentSignalRecipients.ToList();
for (int i = signalRecipients.Count - 1; i >= 0; i--)
{
if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f || item.LastSentSignalRecipients[i].IsPower) { continue; }
if (item.LastSentSignalRecipients[i].Item.Prefab.FocusOnSelected)
if (signalRecipients[i].Item.Condition <= 0.0f || signalRecipients[i].IsPower) { continue; }
if (signalRecipients[i].Item.Prefab.FocusOnSelected)
{
return item.LastSentSignalRecipients[i].Item;
return signalRecipients[i].Item;
}
}
@@ -1,14 +1,17 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Barotrauma.Items.Components
{
partial class Sonar : Powered, IServerSerializable, IClientSerializable
{
public static List<Sonar> SonarList = new List<Sonar>();
private static readonly ConcurrentDictionary<Sonar, byte> _sonarDict = new ConcurrentDictionary<Sonar, byte>();
public static IEnumerable<Sonar> SonarList => _sonarDict.Keys;
public enum Mode
{
@@ -169,7 +172,7 @@ namespace Barotrauma.Items.Components
IsActive = true;
InitProjSpecific(element);
CurrentMode = Mode.Passive;
SonarList.Add(this);
_sonarDict.TryAdd(this, 0);
}
partial void InitProjSpecific(ContentXElement element);
@@ -291,13 +294,15 @@ namespace Barotrauma.Items.Components
return currentPingIndex != -1 && (character == null || characterUsable);
}
private static readonly Dictionary<string, List<Character>> targetGroups = new Dictionary<string, List<Character>>();
private static readonly ThreadLocal<Dictionary<string, List<Character>>> targetGroups =
new ThreadLocal<Dictionary<string, List<Character>>>(() => new Dictionary<string, List<Character>>());
public override bool CrewAIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
if (currentMode == Mode.Passive || !aiPingCheckPending) { return false; }
foreach (List<Character> targetGroup in targetGroups.Values)
var groups = targetGroups.Value;
foreach (List<Character> targetGroup in groups.Values)
{
targetGroup.Clear();
}
@@ -310,14 +315,14 @@ namespace Barotrauma.Items.Components
#warning This is not the best key for a dictionary.
string directionName = GetDirectionName(c.WorldPosition - item.WorldPosition).Value;
if (!targetGroups.ContainsKey(directionName))
if (!groups.ContainsKey(directionName))
{
targetGroups.Add(directionName, new List<Character>());
groups.Add(directionName, new List<Character>());
}
targetGroups[directionName].Add(c);
groups[directionName].Add(c);
}
foreach (KeyValuePair<string, List<Character>> targetGroup in targetGroups)
foreach (KeyValuePair<string, List<Character>> targetGroup in groups)
{
if (!targetGroup.Value.Any()) { continue; }
string dialogTag = "DialogSonarTarget";
@@ -401,7 +406,7 @@ namespace Barotrauma.Items.Components
MineralClusters = null;
#endif
SonarList.Remove(this);
_sonarDict.TryRemove(this, out _);
}
@@ -637,7 +637,7 @@ namespace Barotrauma.Items.Components
if (pathFinder == null)
{
pathFinder = new PathFinder(WayPoint.WayPointList, false)
pathFinder = new PathFinder(WayPoint.WayPointList.ToList(), false)
{
GetNodePenalty = GetNodePenalty
};