diff --git a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs index 9186bd504..d6d4c5d8d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs @@ -37,10 +37,6 @@ namespace Barotrauma { get { return PhysicsBody.List.Count; } } - public int ConnectClients - { - get { return Client.ClientList.Count; } - } public double RealTickRate { @@ -164,7 +160,6 @@ namespace Barotrauma return $"Server Performence Info \n" + $"Item Count: {ItemCount}\n" + $"Character Count: {CharacterCount}\n" + - $"Clients Count {ConnectClients}\n " + $"PhysicsBody Count: {PhysicsBodyCount}\n" + $"Tick Rate: {RealTickRate}\n" + $"Min Tick Rate: {TickRateLow}\n" + diff --git a/Barotrauma/BarotraumaServer/ServerSource/Program.cs b/Barotrauma/BarotraumaServer/ServerSource/Program.cs index 1f5a9727b..35e2503ef 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Program.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Program.cs @@ -64,7 +64,7 @@ namespace Barotrauma GameMain.ShouldRun = false; }; #endif - Console.WriteLine("Barotrauma Dedicated Server(EP) " + GameMain.Version + + Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version + " (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")"); if (Console.IsOutputRedirected) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs index 261a21706..b05cc6be7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelObjects/LevelTrigger.cs @@ -479,7 +479,7 @@ namespace Barotrauma { foreach (Fixture fixture in triggerBody.FarseerBody.FixtureList) { - ContactEdge contactEdge = fixture.Body.ContactList == null ? null: fixture.Body.ContactList.CreateCopy(); + ContactEdge contactEdge = fixture.Body.ContactList.CreateCopy(); while (contactEdge != null) { if (contactEdge.Contact != null && diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs index 2634f9560..48ea30861 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -642,34 +642,44 @@ namespace Barotrauma /// public static void UpdateAll(float deltaTime, Camera cam , ParallelOptions parallelOptions) { + mapEntityUpdateTick++; #if CLIENT var sw = new System.Diagnostics.Stopwatch(); sw.Start(); #endif + bool shouldUpdateMapEntities = mapEntityUpdateTick % MapEntityUpdateInterval == 0; + bool shouldUpdatePower = mapEntityUpdateTick % PoweredUpdateInterval == 0; + // Buffer lists to avoid repeated allocations - var hullList = Hull.HullList.ToList(); - var structureList = Structure.WallList.ToList(); + var hullList = shouldUpdateMapEntities ? Hull.HullList.ToList() : null; + var structureList = shouldUpdateMapEntities ? Structure.WallList.ToList() : null; var gapList = Gap.GapList.ToList(); - var itemList = Item.ItemList.ToList(); + var itemList = shouldUpdateMapEntities ? Item.ItemList.ToList() : null; // First phase: parallel updates that have no order dependencies Parallel.Invoke(parallelOptions, // Hull parallel update () => { - Parallel.ForEach(hullList, parallelOptions, hull => + if (shouldUpdateMapEntities && hullList != null) { - hull.Update(deltaTime, cam); - }); + Parallel.ForEach(hullList, parallelOptions, hull => + { + hull.Update(deltaTime * MapEntityUpdateInterval, cam); + }); + } }, // Structure parallel update () => { - Parallel.ForEach(structureList, parallelOptions, structure => + if (shouldUpdateMapEntities && structureList != null) { - structure.Update(deltaTime, cam); - }); + Parallel.ForEach(structureList, parallelOptions, structure => + { + structure.Update(deltaTime * MapEntityUpdateInterval, cam); + }); + } }, // Gap reset (must be done before update) () => @@ -682,21 +692,27 @@ namespace Barotrauma // Powered components update () => { - Powered.UpdatePower(deltaTime); + if (shouldUpdatePower) + { + Powered.UpdatePower(deltaTime * PoweredUpdateInterval); + } } ); #if CLIENT // Hull Cheats need to be executed after Hull update - Hull.UpdateCheats(deltaTime, cam); + if (shouldUpdateMapEntities) + { + Hull.UpdateCheats(deltaTime * MapEntityUpdateInterval, cam); + } #endif // 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 => + foreach (Gap gap in shuffledGaps) { gap.Update(deltaTime, cam); - }); + } #if CLIENT sw.Stop(); @@ -705,30 +721,33 @@ namespace Barotrauma #endif // 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 + if (shouldUpdateMapEntities && itemList != null) { - foreach (Item item in itemList) + Item.UpdatePendingConditionUpdates(deltaTime); + + float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; + Item lastUpdatedItem = null; + + try { - lastUpdatedItem = item; - item.Update(scaledDeltaTime, cam); + foreach (Item item in itemList) + { + lastUpdatedItem = item; + item.Update(scaledDeltaTime, cam); + } + } + catch (InvalidOperationException e) + { + GameAnalyticsManager.AddErrorEventOnce( + "MapEntity.UpdateAll:ItemUpdateInvalidOperation", + GameAnalyticsManager.ErrorSeverity.Critical, + $"Error while updating item {lastUpdatedItem?.Name ?? "null"}: {e.Message}"); + throw new InvalidOperationException($"Error while updating item {lastUpdatedItem?.Name ?? "null"}", innerException: e); } - } - catch (InvalidOperationException e) - { - GameAnalyticsManager.AddErrorEventOnce( - "MapEntity.UpdateAll:ItemUpdateInvalidOperation", - GameAnalyticsManager.ErrorSeverity.Critical, - $"Error while updating item {lastUpdatedItem?.Name ?? "null"}: {e.Message}"); - throw new InvalidOperationException($"Error while updating item {lastUpdatedItem?.Name ?? "null"}", innerException: e); - } - UpdateAllProjSpecific(scaledDeltaTime); - Spawner?.Update(); + UpdateAllProjSpecific(scaledDeltaTime); + Spawner?.Update(); + } #if CLIENT sw.Stop(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 182873fc1..00bb104ba 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -7,7 +7,6 @@ using FarseerPhysics; using System.Threading.Tasks; using System.Linq; using System.Collections.Generic; -using System; #if DEBUG && CLIENT @@ -25,7 +24,7 @@ namespace Barotrauma private static readonly ParallelOptions parallelOptions = new ParallelOptions { - MaxDegreeOfParallelism = Environment.ProcessorCount * 2, + MaxDegreeOfParallelism = 16 }; #if CLIENT @@ -152,23 +151,31 @@ namespace Barotrauma var physicsBodies = PhysicsBody.List.ToList(); - Parallel.ForEach(physicsBodies, parallelOptions, body => - { - if ((body.Enabled || body.UserData is Character) && - body.BodyType != BodyType.Static) + Parallel.Invoke(parallelOptions, + () => { - body.Update(); + Parallel.ForEach(physicsBodies, parallelOptions, body => + { + if ((body.Enabled || body.UserData is Character) && + body.BodyType != BodyType.Static) + { + body.Update(); + } + }); + }, + () => + { + GameMain.GameSession?.Update((float)deltaTime); } - }); - GameMain.GameSession?.Update((float)deltaTime); + ); - Parallel.ForEach(physicsBodies, parallelOptions, body => + foreach (PhysicsBody body in physicsBodies) { if (body.Enabled && body.BodyType != BodyType.Static) { body.SetPrevTransform(body.SimPosition, body.Rotation); } - }); + } MapEntity.ClearHighlightedEntities(); @@ -245,14 +252,14 @@ namespace Barotrauma Character.Controlled?.UpdateLocalCursor(cam); #elif SERVER - Parallel.Invoke(parallelOptions, - () => { if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime, Camera.Instance); }, - () => Character.UpdateAll((float)deltaTime, Camera.Instance) - ); + if (Level.Loaded != null) + { + Level.Loaded.Update((float)deltaTime, Camera.Instance); + } + Character.UpdateAll((float)deltaTime, Camera.Instance); #endif var submarines = Submarine.Loaded.ToList(); - Parallel.ForEach(submarines, parallelOptions, sub => { sub.SetPrevTransform(sub.Position); @@ -270,8 +277,8 @@ namespace Barotrauma MapEntity.UpdateAll((float)deltaTime, cam, parallelOptions); #elif SERVER + MapEntity.UpdateAll((float)deltaTime, Camera.Instance, parallelOptions); - //StatusEffect.UpdateAll is not thread-safe and must be executed on the main thread StatusEffect.UpdateAll((float)deltaTime);