Using update IDs instead of timestamps to correct client-side movement predictions
This commit is contained in:
@@ -1055,32 +1055,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
PosInfo serverPos = character.MemPos.Last();
|
PosInfo serverPos = character.MemPos.Last();
|
||||||
|
|
||||||
//this doesn't work correctly, because the delay caused by the 150ms update interval isn't taken into account
|
int localPosIndex = character.MemLocalPos.FindIndex(m => m.ID == serverPos.ID);
|
||||||
//and the server may have unprocessed inputs in memInput (causing a 0-1s delay)
|
if (localPosIndex == -1) return;
|
||||||
float localizedTimestamp = serverPos.Timestamp - GameMain.Client.ServerConnection.AverageRoundtripTime / 2;
|
|
||||||
|
|
||||||
int index = 0;
|
PosInfo localPos = character.MemLocalPos[localPosIndex];
|
||||||
for (index = 0; index < character.MemLocalPos.Count; index++)
|
|
||||||
{
|
|
||||||
if (character.MemLocalPos[index].Timestamp > localizedTimestamp)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index > character.MemLocalPos.Count-1 || index < 1) return;
|
if (Vector2.Distance(localPos.Position, serverPos.Position) > 0.1f)
|
||||||
|
|
||||||
//local positions before and after the timestamp
|
|
||||||
PosInfo prevLocalPos = character.MemLocalPos[index - 1];
|
|
||||||
PosInfo nextLocalPos = character.MemLocalPos[index];
|
|
||||||
|
|
||||||
Vector2 localPos = Vector2.Lerp(
|
|
||||||
prevLocalPos.Position,
|
|
||||||
nextLocalPos.Position,
|
|
||||||
(localizedTimestamp - prevLocalPos.Timestamp) / (nextLocalPos.Timestamp - prevLocalPos.Timestamp));
|
|
||||||
|
|
||||||
|
|
||||||
if (Vector2.Distance(localPos, serverPos.Position) > 0.5f)
|
|
||||||
{
|
{
|
||||||
//collider.SetTransform(collider.SimPosition + (pos.Position - remotePos), collider.Rotation);
|
//collider.SetTransform(collider.SimPosition + (pos.Position - remotePos), collider.Rotation);
|
||||||
collider.SetTransform(serverPos.Position, collider.Rotation);
|
collider.SetTransform(serverPos.Position, collider.Rotation);
|
||||||
|
|||||||
@@ -17,14 +17,27 @@ namespace Barotrauma
|
|||||||
struct PosInfo
|
struct PosInfo
|
||||||
{
|
{
|
||||||
public readonly Vector2 Position;
|
public readonly Vector2 Position;
|
||||||
public Direction Direction;
|
public readonly Direction Direction;
|
||||||
|
|
||||||
public readonly float Timestamp;
|
public readonly float Timestamp;
|
||||||
|
public readonly UInt32 ID;
|
||||||
|
|
||||||
public PosInfo(Vector2 pos, Direction dir, float time)
|
public PosInfo(Vector2 pos, Direction dir, float time)
|
||||||
{
|
{
|
||||||
Position = pos;
|
Position = pos;
|
||||||
Direction = dir;
|
Direction = dir;
|
||||||
Timestamp = time;
|
Timestamp = time;
|
||||||
|
|
||||||
|
ID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PosInfo(Vector2 pos, Direction dir, UInt32 ID)
|
||||||
|
{
|
||||||
|
Position = pos;
|
||||||
|
Direction = dir;
|
||||||
|
this.ID = ID;
|
||||||
|
|
||||||
|
Timestamp = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1133,18 +1146,6 @@ namespace Barotrauma
|
|||||||
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (Submarine == null ? 400.0f : 250.0f)+pressureEffect, 0.05f);
|
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (Submarine == null ? 400.0f : 250.0f)+pressureEffect, 0.05f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == this)
|
|
||||||
{
|
|
||||||
if (memLocalPos.Count == 0 || NetTime.Now > memLocalPos.Last().Timestamp + 0.1f)
|
|
||||||
{
|
|
||||||
memLocalPos.Add(
|
|
||||||
new PosInfo(
|
|
||||||
SimPosition,
|
|
||||||
AnimController.Dir > 0.0f ? Direction.Right : Direction.Left,
|
|
||||||
(float)NetTime.Now));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
|
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null)
|
if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null)
|
||||||
{
|
{
|
||||||
@@ -1310,6 +1311,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
|
memLocalPos.Add(new PosInfo(SimPosition, AnimController.TargetDir, LastNetworkUpdateID));
|
||||||
|
|
||||||
byte newInput = 0;
|
byte newInput = 0;
|
||||||
newInput |= IsKeyDown(InputType.Left) ? (byte)0x1 : (byte)0;
|
newInput |= IsKeyDown(InputType.Left) ? (byte)0x1 : (byte)0;
|
||||||
newInput |= IsKeyDown(InputType.Right) ? (byte)0x2 : (byte)0;
|
newInput |= IsKeyDown(InputType.Right) ? (byte)0x2 : (byte)0;
|
||||||
@@ -1842,6 +1845,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
msg.Write(ID);
|
msg.Write(ID);
|
||||||
|
|
||||||
|
//todo: only write this if sending for the client who's controlling the character?
|
||||||
|
msg.Write((UInt32)(LastNetworkUpdateID - memInput.Count));
|
||||||
|
|
||||||
msg.Write(AnimController.Dir > 0.0f);
|
msg.Write(AnimController.Dir > 0.0f);
|
||||||
|
|
||||||
msg.Write(SimPosition.X);
|
msg.Write(SimPosition.X);
|
||||||
@@ -1857,7 +1863,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
//skip through the rest of the message
|
//skip through the rest of the message
|
||||||
//todo: a better way to skip through the message?
|
//todo: a better way to skip through the message?
|
||||||
msg.Position += 1 + 32 + 32;
|
msg.Position += 32 + 1 + 32 + 32;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1867,14 +1873,17 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public virtual void ClientRead(NetIncomingMessage msg, float sendingTime)
|
public virtual void ClientRead(NetIncomingMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
|
UInt32 networkUpdateID = msg.ReadUInt32();
|
||||||
|
|
||||||
//float sendingTime = msg.ReadSingle();
|
//float sendingTime = msg.ReadSingle();
|
||||||
bool facingRight = msg.ReadBoolean();
|
bool facingRight = msg.ReadBoolean();
|
||||||
Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat());
|
||||||
|
|
||||||
var posInfo = new PosInfo(
|
|
||||||
pos,
|
var posInfo =
|
||||||
facingRight ? Direction.Right : Direction.Left,
|
GameMain.NetworkMember.Character == this ?
|
||||||
sendingTime);
|
new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, networkUpdateID) :
|
||||||
|
new PosInfo(pos, facingRight ? Direction.Right : Direction.Left, sendingTime);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp)
|
while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp)
|
||||||
|
|||||||
Reference in New Issue
Block a user