diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs index 50a1b3b39..08a7bad97 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs @@ -1214,15 +1214,22 @@ namespace Barotrauma } } - private readonly HashSet adjacentHulls = new HashSet(); + /// + /// Used in - ThreadLocal for thread safety during parallel updates + /// + private static readonly ThreadLocal> adjacentHullsLocal = + new ThreadLocal>(() => new HashSet()); + public IEnumerable GetConnectedHulls(bool includingThis, int? searchDepth = null, bool ignoreClosedGaps = false) { + var adjacentHulls = adjacentHullsLocal.Value; adjacentHulls.Clear(); int startStep = 0; searchDepth ??= 100; GetAdjacentHulls(adjacentHulls, ref startStep, searchDepth.Value, ignoreClosedGaps); if (!includingThis) { adjacentHulls.Remove(this); } - return adjacentHulls; + // Return a copy to prevent concurrent modification if the caller enumerates while another thread calls this method + return adjacentHulls.ToHashSet(); } private void GetAdjacentHulls(HashSet connectedHulls, ref int step, int searchDepth, bool ignoreClosedGaps = false) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index c2e123bd1..d0ddf3fe9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; +using System.Threading; using System.Xml.Linq; using Voronoi2; @@ -3655,9 +3656,15 @@ namespace Barotrauma return cells; } - private readonly List tempCells = new List(); + /// + /// Used in - ThreadLocal for thread safety during parallel updates + /// + private static readonly ThreadLocal> tempCellsLocal = + new ThreadLocal>(() => new List()); + public List GetCells(Vector2 worldPos, int searchDepth = 2) { + var tempCells = tempCellsLocal.Value; tempCells.Clear(); int gridPosX = (int)Math.Floor(worldPos.X / GridCellSize); int gridPosY = (int)Math.Floor(worldPos.Y / GridCellSize); @@ -3712,7 +3719,8 @@ namespace Barotrauma tempCells.AddRange(abyssIsland.Cells); } - return tempCells; + // Return a copy to prevent concurrent modification if the caller enumerates while another thread calls this method + return tempCells.ToList(); } public VoronoiCell GetClosestCell(Vector2 worldPos)