From 518eea746e4c4169f42aeea029c6c76860a51064 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 5 Jan 2017 18:16:58 +0200 Subject: [PATCH 1/2] Transforming in-sub MemPos/MemLocalPos coordinates to outside coordinates if the character is outside and vice versa, server doesn't start sending ingame updates until they receive the first ingame update message from the client (no need to send updates while the client is loading or if they fail to start the round) --- .../Source/Characters/Animation/Ragdoll.cs | 35 +++++++++++++++++- Subsurface/Source/Map/Submarine.cs | 5 ++- Subsurface/Source/Networking/GameClient.cs | 2 ++ Subsurface/Source/Networking/GameServer.cs | 17 ++++----- Subsurface/Source/Physics/PhysicsBody.cs | 36 +++++++++++++++++++ 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index 3f966bc69..7fef49a41 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -1205,6 +1205,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 @@ -1226,6 +1243,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; @@ -1244,7 +1277,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/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index e48cb5169..4b39d0af5 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 @@ -1054,7 +1054,10 @@ 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 (Level.Loaded != null) HiddenSubPosition += Vector2.UnitY * Level.Loaded.Size.Y; + foreach (Submarine sub in Submarine.loaded) { HiddenSubPosition += Vector2.UnitY * (sub.Borders.Height + 5000.0f); 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 79ff44613..d3a27c786 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -37,6 +37,42 @@ 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) + { + Submarine closestSub = null; + foreach (Submarine sub in Submarine.Loaded) + { + Rectangle subBorders = sub.Borders; + subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height); + + subBorders.Inflate(500.0f, 500.0f); + + if (subBorders.Contains(ConvertUnits.ToDisplayUnits(posInfo.Position))) + { + closestSub = sub; + break; + } + } + + if (closestSub == null) return posInfo; + + return new PosInfo( + posInfo.Position + ConvertUnits.ToSimUnits(closestSub.Position), + posInfo.Direction, + posInfo.ID, + posInfo.Timestamp); + } } class PhysicsBody From beac45458e1486a5dcf5e9dd78ca56da94c9d835 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 5 Jan 2017 19:07:18 +0200 Subject: [PATCH 2/2] Transforming received in-sub mouse coordinates to outside coordinates if the character is outside and vice versa, HiddenSubPosition fix (can't use Level.Loaded to find the top of the level because the level isn't loaded yet) --- Subsurface/Source/Camera.cs | 2 +- Subsurface/Source/Characters/Character.cs | 82 +++++++++++++------ .../GameSession/GameModes/SinglePlayerMode.cs | 2 +- Subsurface/Source/Map/Submarine.cs | 25 +++++- Subsurface/Source/Map/SubmarineBody.cs | 2 +- Subsurface/Source/Physics/PhysicsBody.cs | 20 +---- Subsurface/Source/Screens/GameScreen.cs | 2 +- 7 files changed, 86 insertions(+), 49 deletions(-) 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/Character.cs b/Subsurface/Source/Characters/Character.cs index 171691ede..13798aaa1 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) @@ -2077,6 +2103,8 @@ namespace Barotrauma if (aiming) { //TODO: write this with less accuracy? + + msg.Write(cursorPosition.X); msg.Write(cursorPosition.Y); } @@ -2141,6 +2169,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 4b39d0af5..24f3a1398 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -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() @@ -1056,7 +1074,10 @@ namespace Barotrauma //place the sub above the top of the level HiddenSubPosition = HiddenSubStartPosition; - if (Level.Loaded != null) HiddenSubPosition += Vector2.UnitY * Level.Loaded.Size.Y; + if (GameMain.GameSession != null && GameMain.GameSession.Level != null) + { + HiddenSubPosition += Vector2.UnitY * GameMain.GameSession.Level.Size.Y; + } foreach (Submarine sub in Submarine.loaded) { 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/Physics/PhysicsBody.cs b/Subsurface/Source/Physics/PhysicsBody.cs index d3a27c786..fc8b7f981 100644 --- a/Subsurface/Source/Physics/PhysicsBody.cs +++ b/Subsurface/Source/Physics/PhysicsBody.cs @@ -50,25 +50,11 @@ namespace Barotrauma public static PosInfo TransformInToOutside(PosInfo posInfo) { - Submarine closestSub = null; - foreach (Submarine sub in Submarine.Loaded) - { - Rectangle subBorders = sub.Borders; - subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height); - - subBorders.Inflate(500.0f, 500.0f); - - if (subBorders.Contains(ConvertUnits.ToDisplayUnits(posInfo.Position))) - { - closestSub = sub; - break; - } - } - - if (closestSub == null) return posInfo; + var sub = Submarine.FindContaining(ConvertUnits.ToDisplayUnits(posInfo.Position)); + if (sub == null) return posInfo; return new PosInfo( - posInfo.Position + ConvertUnits.ToSimUnits(closestSub.Position), + posInfo.Position + ConvertUnits.ToSimUnits(sub.Position), posInfo.Direction, posInfo.ID, posInfo.Timestamp); 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;