diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index 6f6c7aa6d..dc04f3e7f 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -188,7 +188,7 @@ namespace Barotrauma if (Screen.Selected == GameMain.GameScreen) { - var closestSub = Submarine.GetClosest(WorldViewCenter); + var closestSub = Submarine.FindClosest(WorldViewCenter); if (closestSub != null) { moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime); diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 7bb6ed201..ab555a31a 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -1206,6 +1206,23 @@ namespace Barotrauma { if (GameMain.NetworkMember == null) return; + for (int i = 0; i < character.MemPos.Count; i++ ) + { + if (character.Submarine == null) + { + //transform in-sub coordinates to outside coordinates + if (character.MemPos[i].Position.Y > ConvertUnits.ToSimUnits(Level.Loaded.Size.Y)) + character.MemPos[i] = PosInfo.TransformInToOutside(character.MemPos[i]); + } + else if (currentHull != null) + { + //transform outside coordinates to in-sub coordinates + if (character.MemPos[i].Position.Y < ConvertUnits.ToSimUnits(Level.Loaded.Size.Y)) + character.MemPos[i] = PosInfo.TransformOutToInside(character.MemPos[i], currentHull.Submarine); + } + } + + if (character != GameMain.NetworkMember.Character || !character.AllowMovement) { //use simple interpolation for other players' characters and characters that can't move @@ -1227,6 +1244,22 @@ namespace Barotrauma } else { + for (int i = 0; i < character.MemLocalPos.Count; i++) + { + if (character.Submarine == null) + { + //transform in-sub coordinates to outside coordinates + if (character.MemLocalPos[i].Position.Y > ConvertUnits.ToSimUnits(Level.Loaded.Size.Y)) + character.MemLocalPos[i] = PosInfo.TransformInToOutside(character.MemLocalPos[i]); + } + else if (currentHull != null) + { + //transform outside coordinates to in-sub coordinates + if (character.MemLocalPos[i].Position.Y < ConvertUnits.ToSimUnits(Level.Loaded.Size.Y)) + character.MemLocalPos[i] = PosInfo.TransformOutToInside(character.MemLocalPos[i], currentHull.Submarine); + } + } + if (character.MemPos.Count < 1) return; overrideTargetMovement = Vector2.Zero; @@ -1245,7 +1278,7 @@ namespace Barotrauma if (errorMagnitude > 2.0f) { //predicted position was way off, reset completely - Collider.SetTransform(serverPos.Position, Collider.Rotation); + SetPosition(serverPos.Position, false); //local positions are incorrect now -> just clear the list character.MemLocalPos.Clear(); } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 1579ba01d..ad7757fd5 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -1101,6 +1101,27 @@ namespace Barotrauma return closestCharacter; } + private void TransformCursorPos() + { + if (Submarine == null) + { + //character is outside but cursor position inside + if (cursorPosition.Y > Level.Loaded.Size.Y) + { + var sub = Submarine.FindContaining(cursorPosition); + if (sub != null) cursorPosition += sub.Position; + } + } + else + { + //character is inside but cursor position is outside + if (cursorPosition.Y < Level.Loaded.Size.Y) + { + cursorPosition -= Submarine.Position; + } + } + } + private void SelectCharacter(Character character) { if (character == null) return; @@ -1315,41 +1336,46 @@ namespace Barotrauma { if (GameMain.Server != null && !(this is AICharacter) && AllowMovement) { - if (memInput.Count > 0) + if (memInput.Count == 0) { - AnimController.Frozen = false; - prevDequeuedInput = dequeuedInput; - dequeuedInput = memInput[memInput.Count - 1]; - cursorPosition = memMousePos[memMousePos.Count - 1]; - memInput.RemoveAt(memInput.Count - 1); - memMousePos.RemoveAt(memMousePos.Count - 1); - if (dequeuedInput == InputNetFlags.None) + + if (AllowMovement) AnimController.Frozen = true; + return; + } + + AnimController.Frozen = false; + prevDequeuedInput = dequeuedInput; + + dequeuedInput = memInput[memInput.Count - 1]; + memInput.RemoveAt(memInput.Count - 1); + + cursorPosition = memMousePos[memMousePos.Count - 1]; + memMousePos.RemoveAt(memMousePos.Count - 1); + + TransformCursorPos(); + + if (dequeuedInput == InputNetFlags.None) + { + if (isStillCountdown <= 0) { - if (isStillCountdown<=0) + while (memInput.Count > 5 && memInput[memInput.Count - 1] == 0) { - while (memInput.Count>5 && memInput[memInput.Count-1]==0) - { - //remove inputs where the player is not moving at all - //helps the server catch up, shouldn't affect final position - memInput.RemoveAt(memInput.Count - 1); - memMousePos.RemoveAt(memMousePos.Count - 1); - } - isStillCountdown = 15; + //remove inputs where the player is not moving at all + //helps the server catch up, shouldn't affect final position + memInput.RemoveAt(memInput.Count - 1); + memMousePos.RemoveAt(memMousePos.Count - 1); } - else - { - isStillCountdown--; - } - } else - { isStillCountdown = 15; } + else + { + isStillCountdown--; + } } else { - if (AllowMovement) AnimController.Frozen = true; - return; - } + isStillCountdown = 15; + } } } else if (GameMain.Client != null) @@ -2089,6 +2115,8 @@ namespace Barotrauma if (aiming) { //TODO: write this with less accuracy? + + msg.Write(cursorPosition.X); msg.Write(cursorPosition.Y); } @@ -2153,6 +2181,8 @@ namespace Barotrauma cursorPosition = new Vector2( msg.ReadFloat(), msg.ReadFloat()); + + TransformCursorPos(); } facingRight = msg.ReadBoolean(); } diff --git a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs index 5d26ecd4f..685d2ffde 100644 --- a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs +++ b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs @@ -163,7 +163,7 @@ namespace Barotrauma return null; } - Submarine closestSub = Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter); + Submarine closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter); if (closestSub != null && (closestSub.AtEndPosition || closestSub.AtStartPosition)) { return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index e48cb5169..24f3a1398 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -34,7 +34,7 @@ namespace Barotrauma { public static string SavePath = "Submarines"; - public static readonly Vector2 HiddenSubStartPosition = new Vector2(-50000.0f, 80000.0f); + public static readonly Vector2 HiddenSubStartPosition = new Vector2(-50000.0f, 10000.0f); //position of the "actual submarine" which is rendered wherever the SubmarineBody is //should be in an unreachable place public Vector2 HiddenSubPosition @@ -811,7 +811,7 @@ namespace Barotrauma //Level.Loaded.Move(-amount); } - public static Submarine GetClosest(Vector2 worldPosition) + public static Submarine FindClosest(Vector2 worldPosition) { Submarine closest = null; float closestDist = 0.0f; @@ -828,6 +828,24 @@ namespace Barotrauma return closest; } + /// + /// Finds the sub whose borders contain the position + /// + public static Submarine FindContaining(Vector2 position) + { + foreach (Submarine sub in Submarine.Loaded) + { + Rectangle subBorders = sub.Borders; + subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Microsoft.Xna.Framework.Point(0, sub.Borders.Height); + + subBorders.Inflate(500.0f, 500.0f); + + if (subBorders.Contains(position)) return sub; + } + + return null; + } + //saving/loading ---------------------------------------------------- public bool Save() @@ -1054,7 +1072,13 @@ namespace Barotrauma Description = ToolBox.GetAttributeString(submarineElement, "description", ""); Enum.TryParse(ToolBox.GetAttributeString(submarineElement, "tags", ""), out tags); + //place the sub above the top of the level HiddenSubPosition = HiddenSubStartPosition; + if (GameMain.GameSession != null && GameMain.GameSession.Level != null) + { + HiddenSubPosition += Vector2.UnitY * GameMain.GameSession.Level.Size.Y; + } + foreach (Submarine sub in Submarine.loaded) { HiddenSubPosition += Vector2.UnitY * (sub.Borders.Height + 5000.0f); diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index b882e5865..f540eadec 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -207,7 +207,7 @@ namespace Barotrauma Submarine closestSub = null; if (Character.Controlled == null) { - closestSub = Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter); + closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter); } else { diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 820bcc16e..fc72b5305 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -128,6 +128,8 @@ namespace Barotrauma.Networking config.SimulatedDuplicatesChance = 0.05f; config.SimulatedMinimumLatency = 0.1f; config.SimulatedRandomLatency = 0.05f; + + config.ConnectionTimeout = 600.0f; #endif config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 7bb5526dd..fcdce1f09 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -76,6 +76,8 @@ namespace Barotrauma.Networking config.SimulatedRandomLatency = 0.05f; config.SimulatedDuplicatesChance = 0.05f; config.SimulatedMinimumLatency = 0.1f; + + config.ConnectionTimeout = 600.0f; #endif config.Port = port; Port = port; @@ -472,16 +474,9 @@ namespace Barotrauma.Networking foreach (Client c in ConnectedClients) { - if (gameStarted) + if (gameStarted && c.inGame) { - if (c.inGame) - { - ClientWriteIngame(c); - } - else - { - ClientWriteLobby(c); - } + ClientWriteIngame(c); } else { @@ -606,7 +601,6 @@ namespace Barotrauma.Networking //break; } } - } private void ClientReadIngame(NetIncomingMessage inc) @@ -617,6 +611,8 @@ namespace Barotrauma.Networking inc.SenderConnection.Disconnect("You're not a connected client."); return; } + + if (gameStarted) c.inGame = true; ClientNetObject objHeader; while ((objHeader = (ClientNetObject)inc.ReadByte()) != ClientNetObject.END_OF_MESSAGE) @@ -924,7 +920,6 @@ namespace Barotrauma.Networking List characterInfos = new List(); foreach (Client client in connectedClients) { - client.inGame = true; if (client.characterInfo == null) { client.characterInfo = new CharacterInfo(Character.HumanConfigFile, client.name); diff --git a/Subsurface/Source/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index 67f2422eb..15067520b 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -37,6 +37,28 @@ namespace Barotrauma Timestamp = time; } + + public static PosInfo TransformOutToInside(PosInfo posInfo, Submarine submarine) + { + //transform outside coordinates to in-sub coordinates + return new PosInfo( + posInfo.Position - ConvertUnits.ToSimUnits(submarine.Position), + posInfo.Direction, + posInfo.ID, + posInfo.Timestamp); + } + + public static PosInfo TransformInToOutside(PosInfo posInfo) + { + var sub = Submarine.FindContaining(ConvertUnits.ToDisplayUnits(posInfo.Position)); + if (sub == null) return posInfo; + + return new PosInfo( + posInfo.Position + ConvertUnits.ToSimUnits(sub.Position), + posInfo.Direction, + posInfo.ID, + posInfo.Timestamp); + } } class PhysicsBody diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 9a4f81cdb..b4269a619 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -118,7 +118,7 @@ namespace Barotrauma if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null && !DebugConsole.IsOpen) { - var closestSub = Submarine.GetClosest(cam.WorldViewCenter); + var closestSub = Submarine.FindClosest(cam.WorldViewCenter); if (closestSub == null) closestSub = GameMain.GameSession.Submarine; Vector2 targetMovement = Vector2.Zero;