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;