From b35eee55616526fc008d12539c653bd89b985359 Mon Sep 17 00:00:00 2001 From: NotAlwaysTrue <77662224+NotAlwaysTrue@users.noreply.github.com> Date: Sat, 27 Dec 2025 15:32:16 +0800 Subject: [PATCH 1/3] Revert "OBT/1.0.4" --- .../ServerSource/PerformenceMonitor.cs | 5 -- .../BarotraumaServer/ServerSource/Program.cs | 2 +- .../Map/Levels/LevelObjects/LevelTrigger.cs | 2 +- .../SharedSource/Map/MapEntity.cs | 85 ++++++++++++------- .../SharedSource/Screens/GameScreen.cs | 41 +++++---- 5 files changed, 78 insertions(+), 57 deletions(-) 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); From 3aadff7a3c8f63a824ebe4c4ef3cb63444332ae6 Mon Sep 17 00:00:00 2001 From: NotAlwaysTrue <2136846186@qq.com> Date: Sat, 27 Dec 2025 15:51:04 +0800 Subject: [PATCH 2/3] Improved thread safety for Gap.update() --- Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs index 94b8bd03e..3fe156958 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs @@ -3,11 +3,12 @@ using Barotrauma.Items.Components; using FarseerPhysics; using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; +using MoonSharp.Interpreter; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; -using MoonSharp.Interpreter; namespace Barotrauma { @@ -745,7 +746,7 @@ namespace Barotrauma waterFlowThisFrame = 0.0f; } - private static readonly HashSet checkedHulls = new HashSet(); + private static readonly ConcurrentBag checkedHulls = new ConcurrentBag(); /// /// Simulates water flow from the source to all the hulls it's connected to across the sub, as if the water was coming directly from outside. @@ -764,7 +765,7 @@ namespace Barotrauma } } - static void SimulateWaterFlowFromOutsideToConnectedHullsRecursive(Hull targetHull, Gap gap, HashSet checkedHulls, Hull originHull, float maxFlow, float deltaTime) + static void SimulateWaterFlowFromOutsideToConnectedHullsRecursive(Hull targetHull, Gap gap, ConcurrentBag checkedHulls, Hull originHull, float maxFlow, float deltaTime) { const float decay = 0.95f; From a44d89f9539729a5c25fe2f0b37285e2923e6ec8 Mon Sep 17 00:00:00 2001 From: NotAlwaysTrue <77662224+NotAlwaysTrue@users.noreply.github.com> Date: Sat, 27 Dec 2025 16:05:20 +0800 Subject: [PATCH 3/3] Revert "Revert back to 1.0.3" --- .../ServerSource/PerformenceMonitor.cs | 5 ++ .../BarotraumaServer/ServerSource/Program.cs | 2 +- .../Map/Levels/LevelObjects/LevelTrigger.cs | 2 +- .../SharedSource/Map/MapEntity.cs | 85 +++++++------------ .../SharedSource/Screens/GameScreen.cs | 41 ++++----- 5 files changed, 57 insertions(+), 78 deletions(-) diff --git a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs index d6d4c5d8d..9186bd504 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/PerformenceMonitor.cs @@ -37,6 +37,10 @@ namespace Barotrauma { get { return PhysicsBody.List.Count; } } + public int ConnectClients + { + get { return Client.ClientList.Count; } + } public double RealTickRate { @@ -160,6 +164,7 @@ 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 35e2503ef..1f5a9727b 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 " + GameMain.Version + + Console.WriteLine("Barotrauma Dedicated Server(EP) " + 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 b05cc6be7..261a21706 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.CreateCopy(); + ContactEdge contactEdge = fixture.Body.ContactList == null ? null: 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 48ea30861..2634f9560 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/MapEntity.cs @@ -642,44 +642,34 @@ 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 = shouldUpdateMapEntities ? Hull.HullList.ToList() : null; - var structureList = shouldUpdateMapEntities ? Structure.WallList.ToList() : null; + var hullList = Hull.HullList.ToList(); + var structureList = Structure.WallList.ToList(); var gapList = Gap.GapList.ToList(); - var itemList = shouldUpdateMapEntities ? Item.ItemList.ToList() : null; + var itemList = Item.ItemList.ToList(); // First phase: parallel updates that have no order dependencies Parallel.Invoke(parallelOptions, // Hull parallel update () => { - if (shouldUpdateMapEntities && hullList != null) + Parallel.ForEach(hullList, parallelOptions, hull => { - Parallel.ForEach(hullList, parallelOptions, hull => - { - hull.Update(deltaTime * MapEntityUpdateInterval, cam); - }); - } + hull.Update(deltaTime, cam); + }); }, // Structure parallel update () => { - if (shouldUpdateMapEntities && structureList != null) + Parallel.ForEach(structureList, parallelOptions, structure => { - Parallel.ForEach(structureList, parallelOptions, structure => - { - structure.Update(deltaTime * MapEntityUpdateInterval, cam); - }); - } + structure.Update(deltaTime, cam); + }); }, // Gap reset (must be done before update) () => @@ -692,27 +682,21 @@ namespace Barotrauma // Powered components update () => { - if (shouldUpdatePower) - { - Powered.UpdatePower(deltaTime * PoweredUpdateInterval); - } + Powered.UpdatePower(deltaTime); } ); #if CLIENT // Hull Cheats need to be executed after Hull update - if (shouldUpdateMapEntities) - { - Hull.UpdateCheats(deltaTime * MapEntityUpdateInterval, cam); - } + Hull.UpdateCheats(deltaTime, cam); #endif // Gap update (has order dependencies, keep random order but execute sequentially) var shuffledGaps = gapList.OrderBy(g => Rand.Int(int.MaxValue)).ToList(); - foreach (Gap gap in shuffledGaps) + Parallel.ForEach(gapList, parallelOptions, gap => { gap.Update(deltaTime, cam); - } + }); #if CLIENT sw.Stop(); @@ -721,33 +705,30 @@ namespace Barotrauma #endif // Item update (Item.Update() is not thread-safe and must be executed on the main thread) - if (shouldUpdateMapEntities && itemList != null) + Item.UpdatePendingConditionUpdates(deltaTime); + + float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; + Item lastUpdatedItem = null; + + try { - Item.UpdatePendingConditionUpdates(deltaTime); - - float scaledDeltaTime = deltaTime * MapEntityUpdateInterval; - Item lastUpdatedItem = null; - - try + foreach (Item item in itemList) { - foreach (Item item in itemList) - { - lastUpdatedItem = item; - item.Update(scaledDeltaTime, cam); - } + 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); - } - - UpdateAllProjSpecific(scaledDeltaTime); - Spawner?.Update(); } + 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(); #if CLIENT sw.Stop(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index 00bb104ba..182873fc1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -7,6 +7,7 @@ using FarseerPhysics; using System.Threading.Tasks; using System.Linq; using System.Collections.Generic; +using System; #if DEBUG && CLIENT @@ -24,7 +25,7 @@ namespace Barotrauma private static readonly ParallelOptions parallelOptions = new ParallelOptions { - MaxDegreeOfParallelism = 16 + MaxDegreeOfParallelism = Environment.ProcessorCount * 2, }; #if CLIENT @@ -151,31 +152,23 @@ namespace Barotrauma var physicsBodies = PhysicsBody.List.ToList(); - Parallel.Invoke(parallelOptions, - () => + Parallel.ForEach(physicsBodies, parallelOptions, body => + { + if ((body.Enabled || body.UserData is Character) && + body.BodyType != BodyType.Static) { - Parallel.ForEach(physicsBodies, parallelOptions, body => - { - if ((body.Enabled || body.UserData is Character) && - body.BodyType != BodyType.Static) - { - body.Update(); - } - }); - }, - () => - { - GameMain.GameSession?.Update((float)deltaTime); + body.Update(); } - ); + }); + GameMain.GameSession?.Update((float)deltaTime); - foreach (PhysicsBody body in physicsBodies) + Parallel.ForEach(physicsBodies, parallelOptions, body => { if (body.Enabled && body.BodyType != BodyType.Static) { body.SetPrevTransform(body.SimPosition, body.Rotation); } - } + }); MapEntity.ClearHighlightedEntities(); @@ -252,14 +245,14 @@ namespace Barotrauma Character.Controlled?.UpdateLocalCursor(cam); #elif SERVER - if (Level.Loaded != null) - { - Level.Loaded.Update((float)deltaTime, Camera.Instance); - } - Character.UpdateAll((float)deltaTime, Camera.Instance); + Parallel.Invoke(parallelOptions, + () => { 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); @@ -277,8 +270,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);