Fixed multiple LINQ using shared resources and cause crashes
Added an null check in AIObjectiveManager.cs to avoid accessing removed resources Use shuffledGaps instead of gapList to ensure update order requirement(already in master) Updated parallelism count
This commit is contained in:
@@ -382,8 +382,13 @@ namespace Barotrauma
|
||||
}
|
||||
steeringBuffer = Math.Clamp(steeringBuffer, minSteeringBuffer, maxSteeringBuffer);
|
||||
|
||||
AnimController.Crouching = shouldCrouch;
|
||||
CheckCrouching(deltaTime);
|
||||
// in case of somehow AnimController was a null, eg. something removed AnimController in the middle of an update
|
||||
if (AnimController != null)
|
||||
{
|
||||
AnimController.Crouching = shouldCrouch;
|
||||
CheckCrouching(deltaTime);
|
||||
}
|
||||
|
||||
Character.ClearInputs();
|
||||
|
||||
if (SortTimer > 0.0f)
|
||||
@@ -1638,7 +1643,8 @@ namespace Barotrauma
|
||||
if (mode == AIObjectiveCombat.CombatMode.None) { return; }
|
||||
if (Character.IsDead || Character.IsIncapacitated || Character.Removed) { return; }
|
||||
if (!Character.IsBot) { return; }
|
||||
if (ObjectiveManager.Objectives.FirstOrDefault(o => o is AIObjectiveCombat) is AIObjectiveCombat combatObjective)
|
||||
List<AIObjective> ObjectivesLocal = ObjectiveManager.Objectives;
|
||||
if (ObjectivesLocal.FirstOrDefault(o => o is AIObjectiveCombat) is AIObjectiveCombat combatObjective)
|
||||
{
|
||||
// Don't replace offensive mode with something else
|
||||
if (combatObjective.Mode == AIObjectiveCombat.CombatMode.Offensive && mode != AIObjectiveCombat.CombatMode.Offensive) { return; }
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Objectives.RemoveAll(o => o.GetType() == type);
|
||||
Objectives.RemoveAll(o => o?.GetType() == type);
|
||||
}
|
||||
Objectives.Add(objective);
|
||||
}
|
||||
|
||||
@@ -345,7 +345,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Connection recipient = wire.OtherConnection(this);
|
||||
if (recipient == null) { continue; }
|
||||
if (recipient.item == this.item || signal.source?.LastSentSignalRecipients.LastOrDefault() == recipient) { continue; }
|
||||
List<Connection> LastSentSignalRecipientsCopy = signal.source?.LastSentSignalRecipients.ToList();
|
||||
if (recipient.item == this.item || LastSentSignalRecipientsCopy.LastOrDefault() == recipient) { continue; }
|
||||
|
||||
signal.source?.LastSentSignalRecipients.Add(recipient);
|
||||
#if CLIENT
|
||||
|
||||
@@ -816,7 +816,7 @@ namespace Barotrauma
|
||||
|
||||
// Gap update (has order dependencies, keep random order but execute sequentially)
|
||||
var shuffledGaps = gapList.OrderBy(g => Rand.Int(int.MaxValue)).ToList();
|
||||
Parallel.ForEach(gapList, parallelOptions, gap =>
|
||||
Parallel.ForEach(shuffledGaps, parallelOptions, gap =>
|
||||
{
|
||||
PhysicsBodyQueue.IsInParallelContext = true;
|
||||
try
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma
|
||||
|
||||
private static readonly ParallelOptions parallelOptions = new ParallelOptions
|
||||
{
|
||||
MaxDegreeOfParallelism = Environment.ProcessorCount * 2,
|
||||
MaxDegreeOfParallelism = Math.Max(4,Environment.ProcessorCount - 1),
|
||||
};
|
||||
|
||||
#if CLIENT
|
||||
@@ -259,33 +259,15 @@ namespace Barotrauma
|
||||
Character.Controlled?.UpdateLocalCursor(cam);
|
||||
|
||||
#elif SERVER
|
||||
Parallel.Invoke(parallelOptions,
|
||||
() =>
|
||||
{
|
||||
PhysicsBodyQueue.IsInParallelContext = true;
|
||||
try
|
||||
{
|
||||
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, Camera.Instance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
PhysicsBodyQueue.IsInParallelContext = false;
|
||||
}
|
||||
},
|
||||
() =>
|
||||
{
|
||||
PhysicsBodyQueue.IsInParallelContext = true;
|
||||
try
|
||||
{
|
||||
Character.UpdateAll((float)deltaTime, Camera.Instance);
|
||||
}
|
||||
finally
|
||||
{
|
||||
PhysicsBodyQueue.IsInParallelContext = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// DO NOT PARALLELIZE THESE TWO OR IT MAY STUCK HERE
|
||||
// SO FOLLOW THE ORIGINAL SINGLE-THREAD LOGIC STRICTLY
|
||||
|
||||
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, Camera.Instance);
|
||||
|
||||
Character.UpdateAll((float)deltaTime, Camera.Instance);
|
||||
|
||||
StatusEffect.UpdateAll((float)deltaTime);
|
||||
|
||||
PhysicsBodyQueue.ProcessPendingOperations();
|
||||
#endif
|
||||
|
||||
@@ -310,8 +292,6 @@ namespace Barotrauma
|
||||
|
||||
MapEntity.UpdateAll((float)deltaTime, Camera.Instance, parallelOptions);
|
||||
|
||||
StatusEffect.UpdateAll((float)deltaTime);
|
||||
|
||||
#endif
|
||||
|
||||
#if CLIENT
|
||||
@@ -321,6 +301,7 @@ namespace Barotrauma
|
||||
#endif
|
||||
//Character.UpdateAnimAll is not thread-safe and must be executed on the main thread
|
||||
Character.UpdateAnimAll((float)deltaTime);
|
||||
PhysicsBodyQueue.ProcessPendingOperations();
|
||||
|
||||
#if CLIENT
|
||||
Ragdoll.UpdateAll((float)deltaTime, cam);
|
||||
|
||||
Reference in New Issue
Block a user