diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index af94426d0..4312cd07c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -3387,21 +3387,9 @@ namespace Barotrauma characterUpdateTick++; - if (characterUpdateTick % CharacterUpdateInterval == 0) + for (int i = 0; i < CharacterList.Count; i++) { - for (int i = 0; i < CharacterList.Count; i++) - { - if (GameMain.LuaCs.Game.UpdatePriorityCharacters.Contains(CharacterList[i])) continue; - - CharacterList[i].Update(deltaTime * CharacterUpdateInterval, cam); - } - } - - foreach (Character character in GameMain.LuaCs.Game.UpdatePriorityCharacters) - { - if (character.Removed) { continue; } - Debug.Assert(character is { Removed: false }); - character.Update(deltaTime, cam); + CharacterList[i].Update(deltaTime, cam); } #if CLIENT diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs index a79e4c1c6..8a6cb6c30 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs @@ -814,6 +814,7 @@ namespace Barotrauma { SingleThreadWorker.GlobalWorker.AddAction(() => { + if (outsideCollisionBlocker == null) { return; } outsideCollisionBlocker.Enabled = false; }); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs index d64738684..97b3a8697 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -650,7 +650,8 @@ namespace Barotrauma // Buffer lists to avoid repeated allocations var hullList = Hull.HullList.ToList(); var structureList = Structure.WallList.ToList(); - var gapList = Gap.GapList.ToList(); + // First, WHY THIS LINQ GOT A NULL ERROR? Second, WHY?? + List shuffledGaps = Gap.GapList?.OrderBy(g => Rand.Int(int.MaxValue)).ToList() ?? Gap.GapList.ToList(); var itemList = Item.ItemList.ToList(); // First phase: parallel updates that have no order dependencies @@ -679,14 +680,12 @@ namespace Barotrauma // moved waterflow reset here to see if we can reduce at least some time { - // if crashed, go ask the god damn physics engine :( - var shuffledGaps = gapList.OrderBy(g => Rand.Int(int.MaxValue)).ToList(); + if (shuffledGaps == null) { shuffledGaps = Gap.GapList; } Parallel.ForEach(shuffledGaps, parallelOptions, gap => { gap.ResetWaterFlowThisFrame(); gap.Update(deltaTime, cam); }); - SingleThreadWorker.GlobalWorker.RunActions(); }, // Powered components update () => @@ -695,6 +694,8 @@ namespace Barotrauma } ); + SingleThreadWorker.GlobalWorker.RunActions(); + #if CLIENT // Hull Cheats need to be executed after Hull update Hull.UpdateCheats(deltaTime, cam); @@ -709,7 +710,6 @@ namespace Barotrauma // Item update (Item.Update() is not thread-safe and must be executed on the main thread) Item.UpdatePendingConditionUpdates(deltaTime); - float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; Item lastUpdatedItem = null; try @@ -717,7 +717,7 @@ namespace Barotrauma foreach (Item item in itemList) { lastUpdatedItem = item; - item.Update(scaledDeltaTime, cam); + item.Update(deltaTime, cam); } } catch (InvalidOperationException e) @@ -729,7 +729,7 @@ namespace Barotrauma throw new InvalidOperationException($"Error while updating item {lastUpdatedItem?.Name ?? "null"}", innerException: e); } - UpdateAllProjSpecific(scaledDeltaTime); + UpdateAllProjSpecific(deltaTime); Spawner?.Update(); #if CLIENT diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 496d79bb1..0aa9dcf37 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -1,6 +1,4 @@ -//#define RUN_PHYSICS_IN_SEPARATE_THREAD - -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using System.Threading; using FarseerPhysics.Dynamics; using FarseerPhysics; @@ -23,9 +21,10 @@ namespace Barotrauma private object updateLock = new object(); private double physicsTime; + // -2 here bcuz we alread have a SEEM thread there private static readonly ParallelOptions parallelOptions = new ParallelOptions { - MaxDegreeOfParallelism = Math.Max(4, Environment.ProcessorCount - 1) + MaxDegreeOfParallelism = Math.Max(4, Environment.ProcessorCount - 2) }; #if CLIENT @@ -78,14 +77,6 @@ namespace Barotrauma MapEntity.ClearHighlightedEntities(); -#if RUN_PHYSICS_IN_SEPARATE_THREAD - var physicsThread = new Thread(ExecutePhysics) - { - Name = "Physics thread", - IsBackground = true - }; - physicsThread.Start(); -#endif } public override void Deselect() @@ -114,15 +105,11 @@ namespace Barotrauma public override void Update(double deltaTime) { + var submarines = Submarine.Loaded.ToList(); + var physicsBodies = PhysicsBody.List.ToList(); + #warning For now CL side performance counter is partly useless bucz multiple changes on such things. Need time to take care of it -#if RUN_PHYSICS_IN_SEPARATE_THREAD - physicsTime += deltaTime; - lock (updateLock) - { -#endif - - #if DEBUG && CLIENT if (GameMain.GameSession != null && !DebugConsole.IsOpen && GUI.KeyboardDispatcher.Subscriber == null) { @@ -150,8 +137,6 @@ namespace Barotrauma GameTime += deltaTime; - var physicsBodies = PhysicsBody.List.ToList(); - Parallel.ForEach(physicsBodies, parallelOptions, body => { if ((body.Enabled || body.UserData is Character) && @@ -162,14 +147,6 @@ namespace Barotrauma }); GameMain.GameSession?.Update((float)deltaTime); - Parallel.ForEach(physicsBodies, parallelOptions, body => - { - if (body.Enabled && body.BodyType != BodyType.Static) - { - body.SetPrevTransform(body.SimPosition, body.Rotation); - } - }); - MapEntity.ClearHighlightedEntities(); #if CLIENT @@ -254,20 +231,19 @@ namespace Barotrauma StatusEffect.UpdateAll((float)deltaTime); #endif - var submarines = Submarine.Loaded.ToList(); - - Parallel.ForEach(submarines, parallelOptions, sub => + foreach (Submarine sub in submarines) { sub.SetPrevTransform(sub.Position); - }); + } - Parallel.ForEach(physicsBodies, parallelOptions, body => + foreach (var body in physicsBodies) { - if (body.Enabled && body.BodyType != FarseerPhysics.BodyType.Static) - { - body.SetPrevTransform(body.SimPosition, body.Rotation); + if (body.Enabled && body.BodyType != FarseerPhysics.BodyType.Static) + { + body.SetPrevTransform(body.SimPosition, body.Rotation); } - }); + } + #if CLIENT MapEntity.UpdateAll((float)deltaTime, cam, parallelOptions); @@ -306,8 +282,6 @@ namespace Barotrauma GameMain.PerformanceCounter.AddElapsedTicks("Update:Submarine", sw.ElapsedTicks); sw.Restart(); #endif - -#if !RUN_PHYSICS_IN_SEPARATE_THREAD try { GameMain.World.Step((float)Timing.Step); @@ -318,17 +292,12 @@ namespace Barotrauma DebugConsole.ThrowError(errorMsg, e); GameAnalyticsManager.AddErrorEventOnce("GameScreen.Update:WorldLockedException" + e.Message, GameAnalyticsManager.ErrorSeverity.Critical, errorMsg); } -#endif #if CLIENT sw.Stop(); GameMain.PerformanceCounter.AddElapsedTicks("Update:Physics", sw.ElapsedTicks); #endif UpdateProjSpecific(deltaTime); - -#if RUN_PHYSICS_IN_SEPARATE_THREAD - } -#endif } partial void UpdateProjSpecific(double deltaTime); diff --git a/Barotrauma/BarotraumaShared/SharedSource/SingleThreadWorker.cs b/Barotrauma/BarotraumaShared/SharedSource/SingleThreadWorker.cs index 6902f8a28..8beef7b85 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/SingleThreadWorker.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/SingleThreadWorker.cs @@ -9,16 +9,27 @@ namespace Barotrauma public static SingleThreadWorker GlobalWorker = new SingleThreadWorker(); + /// + /// Initilize a SingleThreadWorker + /// SingleThreadWorker or STW for short is a FIFO queue ensure single-thread execution of a series of actions. + /// public SingleThreadWorker() { ActionQueue = new ConcurrentQueue(); } + /// + /// Add a pending action in a STW queue + /// + /// public void AddAction(Action action) { ActionQueue.Enqueue(action); } + /// + /// Run all pending actions in the STW queue + /// [STAThread] public void RunActions() { @@ -32,8 +43,9 @@ namespace Barotrauma { // Just try-catch and do nothing but print errorlogs. We cannot afford crashing the game. ConsoleColor originalForeground = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine($"WARNING: Error occurred when running Single Thread Actions \n{e}"); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"WARNING: Error occurred when running Single Thread Actions. " + + $"If the server didn't crash or stop responding then this should be fine \n{e}"); Console.ForegroundColor = Console.ForegroundColor; } }