diff --git a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs index f295160c6..8dc7700f0 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs @@ -1,14 +1,13 @@ using Barotrauma.Networking; using Barotrauma.Particles; using Barotrauma.Sounds; +using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; -using Microsoft.Xna.Framework.Input; using System.Linq; -using Lidgren.Network; namespace Barotrauma { @@ -19,6 +18,8 @@ namespace Barotrauma private List decals = new List(); private float serverUpdateDelay; + private float remoteWaterVolume, remoteOxygenPercentage; + private List remoteFireSources; private bool networkUpdatePending; private float networkUpdateTimer; @@ -139,6 +140,10 @@ namespace Barotrauma partial void UpdateProjSpecific(float deltaTime, Camera cam) { serverUpdateDelay -= deltaTime; + if (serverUpdateDelay <= 0.0f) + { + ApplyRemoteState(); + } if (networkUpdatePending) { @@ -547,18 +552,18 @@ namespace Barotrauma public void ClientRead(ServerNetObject type, NetBuffer message, float sendingTime) { - float newWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume; - float newOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8); + remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume; + remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8); bool hasFireSources = message.ReadBoolean(); int fireSourceCount = 0; - List newFireSources = new List(); + remoteFireSources = new List(); if (hasFireSources) { fireSourceCount = message.ReadRangedInteger(0, 16); for (int i = 0; i < fireSourceCount; i++) { - newFireSources.Add(new Vector3( + remoteFireSources.Add(new Vector3( MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f), MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f), message.ReadRangedSingle(0.0f, 1.0f, 8))); @@ -567,41 +572,6 @@ namespace Barotrauma if (serverUpdateDelay > 0.0f) { return; } - WaterVolume = newWaterVolume; - OxygenPercentage = newOxygenPercentage; - - for (int i = 0; i < fireSourceCount; i++) - { - Vector2 pos = new Vector2( - rect.X + rect.Width * newFireSources[i].X, - rect.Y - rect.Height + (rect.Height * newFireSources[i].Y)); - float size = newFireSources[i].Z * rect.Width; - - var newFire = i < FireSources.Count ? - FireSources[i] : - new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true); - newFire.Position = pos; - newFire.Size = new Vector2(size, newFire.Size.Y); - - //ignore if the fire wasn't added to this room (invalid position)? - if (!FireSources.Contains(newFire)) - { - newFire.Remove(); - continue; - } - } - - for (int i = FireSources.Count - 1; i >= fireSourceCount; i--) - { - FireSources[i].Remove(); - if (i < FireSources.Count) - { - FireSources.RemoveAt(i); - } - } - - if (serverUpdateDelay > 0.0f) { return; } - ApplyRemoteState(); } diff --git a/Barotrauma/BarotraumaServer/Source/Map/Hull.cs b/Barotrauma/BarotraumaServer/Source/Map/Hull.cs index 907ba6f45..3b10a7a24 100644 --- a/Barotrauma/BarotraumaServer/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaServer/Source/Map/Hull.cs @@ -20,6 +20,16 @@ namespace Barotrauma partial void UpdateProjSpecific(float deltaTime, Camera cam) { if (IdFreed) { return; } + + //don't create updates if all clients are very far from the hull + float hullUpdateDistanceSqr = NetConfig.HullUpdateDistance * NetConfig.HullUpdateDistance; + if (!GameMain.Server.ConnectedClients.Any(c => + c.Character != null && + Vector2.DistanceSquared(c.Character.WorldPosition, WorldPosition) < hullUpdateDistanceSqr)) + { + return; + } + //update client hulls if the amount of water has changed by >10% //or if oxygen percentage has changed by 5% if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f || @@ -31,8 +41,8 @@ namespace Barotrauma GameMain.NetworkMember.CreateEntityEvent(this); lastSentVolume = waterVolume; lastSentOxygen = OxygenPercentage; - sendUpdateTimer = NetworkUpdateInterval; - } + sendUpdateTimer = NetConfig.HullUpdateInterval; + } } } diff --git a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index a4be15f3c..f09171b13 100644 --- a/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Barotrauma/BarotraumaServer/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -332,7 +332,8 @@ namespace Barotrauma.Networking } } - foreach (NetEntityEvent entityEvent in sentEvents) + //too many events for one packet + if (eventsToSync.Count > 200) { msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL); msg.Write(client.UnreceivedEntityEventCount); diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs index d5778c9cc..ffe7cf9d3 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameSession.cs @@ -208,7 +208,7 @@ namespace Barotrauma DockingPort myPort = null, outPostPort = null; foreach (DockingPort port in DockingPort.List) { - if (port.IsHorizontal) { continue; } + if (port.IsHorizontal || port.Docked) { continue; } if (port.Item.Submarine == level.StartOutpost) { outPostPort = port; diff --git a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs index 83ea002c0..c252c399a 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/FireSource.cs @@ -175,12 +175,11 @@ namespace Barotrauma LimitSize(); UpdateProjSpecific(growModifier); - -#if CLIENT - if (GameMain.Client != null) return; -#endif - - if (size.X < 1.0f) Remove(); + + if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)) + { + Remove(); + } } partial void UpdateProjSpecific(float growModifier); @@ -293,10 +292,6 @@ namespace Barotrauma //evaporate some of the water hull.WaterVolume -= extinguishAmount; -#if CLIENT - if (GameMain.Client != null) return; -#endif - if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)) { Remove(); @@ -325,12 +320,11 @@ namespace Barotrauma size.X -= extinguishAmount; hull.WaterVolume -= extinguishAmount; - -#if CLIENT - if (GameMain.Client != null) return; -#endif - - if (size.X < 1.0f) Remove(); + + if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)) + { + Remove(); + } } public void Extinguish(float deltaTime, float amount, Vector2 worldPosition) diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 6f537c2c7..0bb9df3e9 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -1522,14 +1522,40 @@ namespace Barotrauma outpost.MakeOutpost(); Point? minSize = null; + DockingPort subPort = null; if (Submarine.MainSub != null) { Point subSize = Submarine.MainSub.GetDockedBorders().Size; Point outpostSize = outpost.GetDockedBorders().Size; minSize = new Point(Math.Max(subSize.X, outpostSize.X), subSize.Y + outpostSize.Y); + + float closestDistance = float.MaxValue; + foreach (DockingPort port in DockingPort.List) + { + if (port.IsHorizontal || port.Docked) { continue; } + if (port.Item.Submarine != Submarine.MainSub) { continue; } + //the submarine port has to be at the top of the sub + if (port.Item.WorldPosition.Y < Submarine.MainSub.WorldPosition.Y) { continue; } + float dist = Math.Abs(port.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X); + if (dist < closestDistance) + { + subPort = port; + closestDistance = dist; + } + } } - outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize)); + float subDockingPortOffset = subPort == null ? 0.0f : subPort.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X; + //don't try to compensate if the port is very far from the sub's center of mass + if (Math.Abs(subDockingPortOffset) > 2000.0f) + { + subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -2000.0f, 2000.0f); + string warningMsg = "Docking port very far from the sub's center of mass (submarine: " + Submarine.MainSub.Name + ", dist: " + subDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible."; + DebugConsole.NewMessage(warningMsg, Color.Orange); + GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg); + } + + outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset)); if ((i == 0) == !Mirrored) { StartOutpost = outpost; diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs index 83033e604..1c3ec2339 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/LevelObjects/LevelTrigger.cs @@ -432,12 +432,16 @@ namespace Barotrauma { if (ForceFluctuationStrength > 0.0f) { - forceFluctuationTimer += deltaTime; - if (forceFluctuationTimer > ForceFluctuationInterval) + //no need for force fluctuation (or network updates) if the trigger limits velocity and there are no triggerers + if (forceMode != TriggerForceMode.LimitVelocity || triggerers.Any()) { - NeedsNetworkSyncing = true; - currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f); - forceFluctuationTimer = 0.0f; + forceFluctuationTimer += deltaTime; + if (forceFluctuationTimer > ForceFluctuationInterval) + { + NeedsNetworkSyncing = true; + currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f); + forceFluctuationTimer = 0.0f; + } } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index 4e71afd3b..66456de83 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -494,7 +494,7 @@ namespace Barotrauma } } - public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null) + public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null, float subDockingPortOffset = 0.0f) { Rectangle dockedBorders = GetDockedBorders(); Vector2 diffFromDockedBorders = @@ -542,17 +542,17 @@ namespace Barotrauma else if (minX < 0) { //no wall found at the left side, spawn to the left from the right-side wall - spawnPos.X = maxX - minWidth - 100.0f; + spawnPos.X = maxX - minWidth - 100.0f + subDockingPortOffset; } else if (maxX > Level.Loaded.Size.X) { //no wall found at right side, spawn to the right from the left-side wall - spawnPos.X = minX + minWidth + 100.0f; + spawnPos.X = minX + minWidth + 100.0f + subDockingPortOffset; } else { //walls found at both sides, use their midpoint - spawnPos.X = (minX + maxX) / 2; + spawnPos.X = (minX + maxX) / 2 + subDockingPortOffset; } spawnPos.Y = Math.Min(spawnPos.Y, Level.Loaded.Size.Y - dockedBorders.Height / 2 - 10); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs index 2e2d01dc0..74b6afcb2 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/NetConfig.cs @@ -35,8 +35,9 @@ namespace Barotrauma.Networking public const float DeleteDisconnectedTime = 20.0f; public const float ItemConditionUpdateInterval = 0.15f; - public const float LevelObjectUpdateInterval = 0.5f; + public const float HullUpdateInterval = 0.5f; + public const float HullUpdateDistance = 20000.0f; public const int MaxEventPacketsPerUpdate = 4;