WIP position syncing

This commit is contained in:
Regalis
2016-10-17 22:28:55 +03:00
parent 0cafc674dd
commit b68eeda8a8
5 changed files with 207 additions and 79 deletions

View File

@@ -75,19 +75,6 @@ namespace Barotrauma
return;
}
//re-enable collider
if (!collider.FarseerBody.Enabled)
{
var lowestLimb = FindLowestLimb();
collider.SetTransform(new Vector2(
collider.SimPosition.X,
Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)),
0.0f);
collider.FarseerBody.Enabled = true;
}
//stun (= disable the animations) if the ragdoll receives a large enough impact
if (strongestImpact > 0.0f)
{
@@ -95,26 +82,47 @@ namespace Barotrauma
strongestImpact = 0.0f;
return;
}
if (!character.IsNetworkPlayer || true)
{
//re-enable collider
if (!collider.FarseerBody.Enabled)
{
var lowestLimb = FindLowestLimb();
collider.SetTransform(new Vector2(
collider.SimPosition.X,
Math.Max(lowestLimb.SimPosition.Y + (collider.radius + collider.height / 2), collider.SimPosition.Y)),
0.0f);
collider.FarseerBody.Enabled = true;
}
if (swimming)
{
collider.FarseerBody.FixedRotation = false;
}
else if (!collider.FarseerBody.FixedRotation)
{
if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f)
if (swimming)
{
//rotate collider back upright
collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f;
collider.FarseerBody.FixedRotation = false;
collider.FarseerBody.FixedRotation = false;
}
else
else if (!collider.FarseerBody.FixedRotation)
{
collider.FarseerBody.FixedRotation = true;
if (Math.Abs(MathUtils.GetShortestAngle(collider.Rotation, 0.0f)) > 0.001f)
{
//rotate collider back upright
collider.AngularVelocity = MathUtils.GetShortestAngle(collider.Rotation, 0.0f) * 60.0f;
collider.FarseerBody.FixedRotation = false;
}
else
{
collider.FarseerBody.FixedRotation = true;
}
}
}
else
{
collider.FarseerBody.Enabled = false;
}
if (character.LockHands)
{
@@ -207,6 +215,7 @@ namespace Barotrauma
}
aiming = false;
if (character.IsNetworkPlayer) collider.LinearVelocity = Vector2.Zero;
}
@@ -231,7 +240,7 @@ namespace Barotrauma
Limb rightLeg = GetLimb(LimbType.RightLeg);
float getUpSpeed = 0.3f;
float walkCycleSpeed = collider.LinearVelocity.X * walkAnimSpeed;
float walkCycleSpeed = movement.X * walkAnimSpeed;
if (stairs != null)
{
TargetMovement = new Vector2(MathHelper.Clamp(TargetMovement.X, -1.5f, 1.5f), TargetMovement.Y);
@@ -240,12 +249,7 @@ namespace Barotrauma
TargetMovement.X < 0.0f && stairs.StairDirection == Direction.Left)
{
TargetMovement *= 1.7f;
walkCycleSpeed *= 2.0f;
}
else
{
TargetMovement /= 1.0f;
walkCycleSpeed *= 2.0f;
//walkCycleSpeed *= 1.0f;
}
}
@@ -278,7 +282,10 @@ namespace Barotrauma
float footMid = colliderPos.X;// (leftFoot.SimPosition.X + rightFoot.SimPosition.X) / 2.0f;
movement = MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp);
movement = overrideTargetMovement == Vector2.Zero ?
MathUtils.SmoothStep(movement, TargetMovement * walkSpeed, movementLerp) :
overrideTargetMovement;
movement.Y = 0.0f;
for (int i = 0; i < 2; i++)
@@ -305,7 +312,7 @@ namespace Barotrauma
//if (LowestLimb == null) return;
if (onGround)
if (onGround && !character.IsNetworkPlayer)
{
collider.LinearVelocity = new Vector2(
movement.X,
@@ -511,11 +518,6 @@ namespace Barotrauma
Limb head = GetLimb(LimbType.Head);
Limb torso = GetLimb(LimbType.Torso);
//collider.FarseerBody.Enabled = false;
//collider.SetTransform(torso.SimPosition, 0.0f);
// float colliderTop = collider.SimPosition.Y + (float)Math.Cos(collider.Rotation) * (collider.radius + collider.height / 2);
if (currentHull != null && (currentHull.Rect.Y - currentHull.Surface > 50.0f))
{
surfaceLimiter = (ConvertUnits.ToDisplayUnits(collider.SimPosition.Y + 0.4f) - surfaceY);
@@ -606,7 +608,10 @@ namespace Barotrauma
movement.Y = movement.Y - (surfaceLimiter - 1.0f) * 0.01f;
}
collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement * swimSpeed, movementLerp);
if (!character.IsNetworkPlayer)
{
collider.LinearVelocity = Vector2.Lerp(collider.LinearVelocity, movement * swimSpeed, movementLerp);
}
walkPos += movement.Length() * 0.15f;
footPos = collider.SimPosition - new Vector2((float)Math.Sin(-collider.Rotation), (float)Math.Cos(-collider.Rotation)) * 0.4f;
@@ -725,7 +730,10 @@ namespace Barotrauma
MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, collider.SimPosition.Y+0.5f), 10.5f);
MoveLimb(waist, new Vector2(ladderSimPos.X - 0.35f * Dir, collider.SimPosition.Y+0.4f), 10.5f);
collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, collider.SimPosition.Y), 10.5f);
if (!character.IsNetworkPlayer)
{
collider.MoveToPos(new Vector2(ladderSimPos.X - 0.2f * Dir, collider.SimPosition.Y), 10.5f);
}
bool slide = targetMovement.Y < -1.1f;

View File

@@ -9,6 +9,7 @@ using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Networking;
using Lidgren.Network;
namespace Barotrauma
{
@@ -61,7 +62,7 @@ namespace Barotrauma
//a movement vector that overrides targetmovement if trying to steer
//a Character to the position sent by server in multiplayer mode
protected Vector2 correctionMovement;
protected Vector2 overrideTargetMovement;
protected float floorY;
protected float surfaceY;
@@ -140,7 +141,7 @@ namespace Barotrauma
{
get
{
return (correctionMovement == Vector2.Zero) ? targetMovement : correctionMovement;
return (overrideTargetMovement == Vector2.Zero) ? targetMovement : overrideTargetMovement;
}
set
{
@@ -465,9 +466,7 @@ namespace Barotrauma
SoundPlayer.PlayDamageSound(DamageSoundType.LimbBlunt, strongestImpact, collider);
strongestImpact = Math.Max(strongestImpact, impact - 8.0f);
}
}
}
if (Character.Controlled == character) GameMain.GameScreen.Cam.Shake = strongestImpact;
}
@@ -528,6 +527,25 @@ namespace Barotrauma
}
}
if (character.MemPos.Count > 1)
{
Vector2 prevPos = ConvertUnits.ToDisplayUnits(character.MemPos[0].Position);
if (currentHull != null) prevPos += currentHull.Submarine.DrawPosition;
prevPos.Y = -prevPos.Y;
for (int i = 1; i < character.MemPos.Count; i++ )
{
Vector2 currPos = ConvertUnits.ToDisplayUnits(character.MemPos[i].Position);
if (currentHull != null) currPos += currentHull.Submarine.DrawPosition;
currPos.Y = -currPos.Y;
GUI.DrawRectangle(spriteBatch, new Rectangle((int)currPos.X - 3, (int)currPos.Y - 3, 6, 6), Color.Cyan*0.6f, true, 0.01f);
GUI.DrawLine(spriteBatch, prevPos, currPos, Color.Cyan*0.6f, 0, 3);
prevPos = currPos;
}
}
if (ignorePlatforms)
{
GUI.DrawLine(spriteBatch,
@@ -718,7 +736,7 @@ namespace Barotrauma
if (Frozen) return;
UpdateNetPlayerPosition();
UpdateNetPlayerPosition(deltaTime);
Vector2 flowForce = Vector2.Zero;
@@ -1027,8 +1045,46 @@ namespace Barotrauma
// }
//}
private void UpdateNetPlayerPosition()
float t = 0.0f;
private void UpdateNetPlayerPosition(float deltaTime)
{
if (character.MemPos.Count < 2) return;
PosInfo prev = character.MemPos[0];
PosInfo next = character.MemPos[1];
Vector2 currPos = collider.SimPosition;
//interpolate the position of the collider from the first position in the buffer towards the second
if (prev.Timestamp < next.Timestamp)
{
//if there are more than 2 positions in the buffer,
//increase the interpolation speed to catch up with the server
float speedMultiplier = 1.0f + (float)Math.Pow((character.MemPos.Count - 2) / 2.0f, 2.0f);
t += (deltaTime * speedMultiplier) / (next.Timestamp - prev.Timestamp);
currPos = Vector2.Lerp(prev.Position, next.Position, t);
//override the targetMovement to make the character play the walking/running animation
overrideTargetMovement = (next.Position - prev.Position) / (next.Timestamp - prev.Timestamp);
}
else
{
currPos = next.Position;
t = 1.0f;
return;
}
collider.SetTransform(currPos, collider.Rotation);
if (t >= 1.0f)
{
t = 0.0f;
character.MemPos.RemoveAt(0);
}
//if (refLimb.body.TargetPosition == Vector2.Zero)
//{
// correctionMovement = Vector2.Zero;
@@ -1051,7 +1107,7 @@ namespace Barotrauma
//}
//float dist = Vector2.Distance(refLimb.body.SimPosition, refLimb.body.TargetPosition);
//float dist = Vector2.Distance(collider.SimPosition, character.MemPos[0].Position);
////if the limb is further away than resetdistance, all limbs are immediately snapped to their targetpositions
//bool resetAll = dist > NetConfig.ResetRagdollDistance;

View File

@@ -14,7 +14,20 @@ using System.Xml.Linq;
namespace Barotrauma
{
struct PosInfo
{
public readonly Vector2 Position;
public Direction Direction;
public readonly float Timestamp;
public PosInfo(Vector2 pos, Direction dir, float time)
{
Position = pos;
Direction = dir;
Timestamp = time;
}
}
class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable
{
public static List<Character> CharacterList = new List<Character>();
@@ -29,12 +42,10 @@ namespace Barotrauma
byte dequeuedInput = 0; byte prevDequeuedInput = 0;
List<byte> memInput = new List<byte>();
List<float> memMouseX = new List<float>();
List<float> memMouseY = new List<float>();
List<float> memPosX = new List<float>();
List<float> memPosY = new List<float>();
List<Vector2> memMousePos = new List<Vector2>();
List<PosInfo> memPos = new List<PosInfo>();
//the Character that the player is currently controlling
private static Character controlled;
@@ -75,8 +86,6 @@ namespace Barotrauma
public readonly bool IsNetworkPlayer;
private bool networkUpdateSent;
private CharacterInventory inventory;
private UInt32 LastNetworkUpdateID = 0;
@@ -211,6 +220,11 @@ namespace Barotrauma
get { return Submarine == null ? cursorPosition : cursorPosition + Submarine.Position; }
}
public List<PosInfo> MemPos
{
get { return memPos; }
}
public Character ClosestCharacter
{
get { return closestCharacter; }
@@ -301,6 +315,7 @@ namespace Barotrauma
set
{
if (!MathUtils.IsValid(value)) return;
health = MathHelper.Clamp(value, minHealth, maxHealth);
}
}
@@ -761,8 +776,13 @@ namespace Barotrauma
if (length > 0.0f) targetMovement = targetMovement / length;
}
if (Math.Sign(targetMovement.X) != -Math.Sign(AnimController.Dir) && IsKeyDown(InputType.Run))
if (AnimController is HumanoidAnimController &&
!((HumanoidAnimController)AnimController).Crouching &&
Math.Sign(targetMovement.X) != -Math.Sign(AnimController.Dir) &&
IsKeyDown(InputType.Run))
{
targetMovement *= 3.0f;
}
targetMovement *= SpeedMultiplier;
SpeedMultiplier = 1.0f;
@@ -812,6 +832,13 @@ namespace Barotrauma
AnimController.TargetDir = Direction.Right;
}
}
else if (GameMain.Client != null && Character.controlled != this)
{
if (memPos.Count > 0)
{
AnimController.TargetDir = memPos[0].Direction;
}
}
if (attackCoolDown >0.0f)
{
@@ -1770,10 +1797,10 @@ namespace Barotrauma
UInt32 networkUpdateID = msg.ReadUInt32();
byte inputCount = msg.ReadByte();
for (int i=0;i<inputCount;i++)
for (int i = 0; i < inputCount; i++)
{
byte newInput = msg.ReadByte();
if ((i < ((long)networkUpdateID-(long)LastNetworkUpdateID)) && (i<60))
if ((i < ((long)networkUpdateID - (long)LastNetworkUpdateID)) && (i < 60))
{
memInput.Insert(i, newInput);
}
@@ -1792,12 +1819,52 @@ namespace Barotrauma
public virtual void ServerWrite(NetOutgoingMessage msg, Client c)
{
//TODO: write position, health, etc
msg.Write(ID);
//todo: only write this once in each packet, not for each character
msg.Write((float)NetTime.Now);
msg.Write(AnimController.Dir > 0.0f);
msg.Write(SimPosition.X);
msg.Write(SimPosition.Y);
}
public static void ClientReadStatic(NetIncomingMessage msg)
{
UInt16 id = msg.ReadUInt16();
var character = Entity.FindEntityByID(id) as Character;
if (character == null)
{
//skip through the rest of the message
//todo: a better way to skip through the message?
msg.Position += 32 + 1 + 32 + 32;
}
else
{
character.ClientRead(msg);
}
}
public virtual void ClientRead(NetIncomingMessage msg)
{
//TODO: read positions health, etc
{
float sendingTime = msg.ReadSingle();
bool facingRight = msg.ReadBoolean();
Vector2 pos = new Vector2(msg.ReadFloat(), msg.ReadFloat());
var posInfo = new PosInfo(
pos,
facingRight ? Direction.Right : Direction.Left,
sendingTime - msg.SenderConnection.RemoteTimeOffset);
int index = 0;
while (index < memPos.Count && posInfo.Timestamp > memPos[index].Timestamp)
{
index++;
}
memPos.Insert(index, posInfo);
}
public void WriteSpawnData(NetOutgoingMessage msg)

View File

@@ -705,13 +705,14 @@ namespace Barotrauma.Networking
lastSentChatMsgID = inc.ReadUInt32();
break;
case ServerNetObject.CHARACTER_POSITION:
bool dead = inc.ReadBoolean();
//bool dead = inc.ReadBoolean();
Character.ClientReadStatic(inc);
inc.ReadPadBits();
if (Character.Controlled != null)
{
if (dead && !Character.Controlled.IsDead)
Character.Controlled.Kill(CauseOfDeath.Damage);
}
//if (Character.Controlled != null)
//{
// if (dead && !Character.Controlled.IsDead)
// Character.Controlled.Kill(CauseOfDeath.Damage);
//}
break;
case ServerNetObject.CHAT_MESSAGE:
ChatMessage.ClientRead(inc);

View File

@@ -644,16 +644,12 @@ namespace Barotrauma.Networking
}
}
foreach (Character character in Character.CharacterList)
{
if (character is AICharacter || character == c.Character) continue;
outmsg.Write((byte)ServerNetObject.CHARACTER_POSITION);
if (c.Character != null && !c.Character.IsDead)
{
outmsg.Write(false); //not dead
outmsg.WritePadBits();
}
else
{
outmsg.Write(true); //dead
outmsg.Write((byte)ServerNetObject.CHARACTER_POSITION);
character.ServerWrite(outmsg, c);
outmsg.WritePadBits();
}