WIP position syncing
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user