- WIP attempt at syncing item positions
- Some changes to item floating logic (lift is also applied to items outside the sub, forcefactor is clamped to 1 if the item is fully submerged)
This commit is contained in:
@@ -38,6 +38,14 @@ namespace Barotrauma
|
|||||||
//components that determine the functionality of the item
|
//components that determine the functionality of the item
|
||||||
public List<ItemComponent> components;
|
public List<ItemComponent> components;
|
||||||
|
|
||||||
|
public PhysicsBody body;
|
||||||
|
|
||||||
|
private float condition;
|
||||||
|
|
||||||
|
private bool inWater;
|
||||||
|
|
||||||
|
private Inventory parentInventory;
|
||||||
|
|
||||||
public readonly Dictionary<string, ObjectProperty> properties;
|
public readonly Dictionary<string, ObjectProperty> properties;
|
||||||
public Dictionary<string, ObjectProperty> ObjectProperties
|
public Dictionary<string, ObjectProperty> ObjectProperties
|
||||||
{
|
{
|
||||||
@@ -57,14 +65,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicsBody body;
|
|
||||||
|
|
||||||
private float condition;
|
|
||||||
|
|
||||||
private bool inWater;
|
|
||||||
|
|
||||||
private Inventory parentInventory;
|
|
||||||
|
|
||||||
//the inventory in which the item is contained in
|
//the inventory in which the item is contained in
|
||||||
public Inventory ParentInventory
|
public Inventory ParentInventory
|
||||||
{
|
{
|
||||||
@@ -618,34 +618,61 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
FindHull();
|
FindHull();
|
||||||
|
|
||||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
Vector2 moveAmount = body.SimPosition - body.LastSentPosition;
|
||||||
|
if (moveAmount != Vector2.Zero && moveAmount.Length() > NetConfig.ItemPosUpdateDistance)
|
||||||
|
{
|
||||||
|
new NetworkEvent(NetworkEventType.PhysicsBodyPosition, ID, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition);
|
||||||
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
rect.X = (int)(displayPos.X - rect.Width / 2.0f);
|
||||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.SetToTargetPosition();
|
body.MoveToTargetPosition();
|
||||||
|
|
||||||
inWater = IsInWater();
|
inWater = IsInWater();
|
||||||
|
|
||||||
if (!inWater) return;
|
if (!inWater || Container != null || body == null) return;
|
||||||
|
|
||||||
//calculate (a rough approximation of) buoyancy
|
|
||||||
float volume = body.Mass / body.Density;
|
|
||||||
Vector2 buoyancy = new Vector2(0, volume * 10.0f);
|
|
||||||
|
|
||||||
//apply buoyancy and drag
|
|
||||||
|
|
||||||
//if ((buoyancy - body.LinearVelocity * volume) == Vector2.Zero) DebugConsole.ThrowError("v.zero ");
|
|
||||||
if (body.LinearVelocity != Vector2.Zero && body.LinearVelocity.Length() > 1000.0f)
|
if (body.LinearVelocity != Vector2.Zero && body.LinearVelocity.Length() > 1000.0f)
|
||||||
{
|
{
|
||||||
body.ResetDynamics();
|
body.ResetDynamics();
|
||||||
}
|
}
|
||||||
body.ApplyForce(buoyancy - body.LinearVelocity * volume);
|
|
||||||
|
ApplyWaterForces();
|
||||||
|
|
||||||
//TODO: make sure items stay in sync between clients before letting flowing water move items
|
//TODO: make sure items stay in sync between clients before letting flowing water move items
|
||||||
//if(CurrentHull != null)
|
if(CurrentHull != null) CurrentHull.ApplyFlowForces(deltaTime, this);
|
||||||
// CurrentHull.HandleItems(deltaTime, this);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies buoyancy, drag and angular drag caused by water
|
||||||
|
/// </summary>
|
||||||
|
private void ApplyWaterForces()
|
||||||
|
{
|
||||||
|
if (!InWater || body == null || Container != null) return;
|
||||||
|
|
||||||
|
float forceFactor = 1.0f;
|
||||||
|
if (CurrentHull != null)
|
||||||
|
{
|
||||||
|
float floor = CurrentHull.Rect.Y - CurrentHull.Rect.Height;
|
||||||
|
float waterLevel = (floor + CurrentHull.Volume / CurrentHull.Rect.Width);
|
||||||
|
|
||||||
|
//forceFactor is 1.0f if the item is completely submerged,
|
||||||
|
//and goes to 0.0f as the item goes through the surface
|
||||||
|
forceFactor = Math.Min((waterLevel - Position.Y) / rect.Height, 1.0f);
|
||||||
|
if (forceFactor <= 0.0f) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float volume = body.Mass / body.Density;
|
||||||
|
|
||||||
|
var uplift = -GameMain.World.Gravity * forceFactor * volume;
|
||||||
|
|
||||||
|
Vector2 drag = body.LinearVelocity * volume;
|
||||||
|
|
||||||
|
body.ApplyForce((uplift - drag) * 10.0f);
|
||||||
|
|
||||||
//apply simple angular drag
|
//apply simple angular drag
|
||||||
body.ApplyTorque(body.AngularVelocity * volume * -0.05f);
|
body.ApplyTorque(body.AngularVelocity * volume * -0.05f);
|
||||||
@@ -1374,11 +1401,11 @@ namespace Barotrauma
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case NetworkEventType.DropItem:
|
case NetworkEventType.DropItem:
|
||||||
if (body != null)
|
if (body != null) body.FillNetworkData(message);
|
||||||
{
|
break;
|
||||||
message.Write(body.SimPosition.X);
|
case NetworkEventType.PhysicsBodyPosition:
|
||||||
message.Write(body.SimPosition.Y);
|
System.Diagnostics.Debug.Assert(body != null, "Tried to send a PhysicsBodyPosition message for an item that has no physics body");
|
||||||
}
|
body.FillNetworkData(message);
|
||||||
break;
|
break;
|
||||||
case NetworkEventType.ItemFixed:
|
case NetworkEventType.ItemFixed:
|
||||||
byte requirementIndex = (byte)data;
|
byte requirementIndex = (byte)data;
|
||||||
@@ -1456,10 +1483,15 @@ namespace Barotrauma
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case NetworkEventType.DropItem:
|
case NetworkEventType.DropItem:
|
||||||
Vector2 newSimPos = Vector2.Zero;
|
|
||||||
newSimPos = new Vector2(message.ReadFloat(), message.ReadFloat());
|
|
||||||
SetTransform(newSimPos, body.Rotation);
|
|
||||||
Drop(null, false);
|
Drop(null, false);
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
body.ReadNetworkData(message, sendingTime);
|
||||||
|
body.MoveToTargetPosition(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NetworkEventType.PhysicsBodyPosition:
|
||||||
|
if (body != null) body.ReadNetworkData(message, sendingTime);
|
||||||
break;
|
break;
|
||||||
case NetworkEventType.ItemFixed:
|
case NetworkEventType.ItemFixed:
|
||||||
|
|
||||||
|
|||||||
@@ -453,29 +453,15 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void HandleItems(float deltaTime, Item body)
|
public void ApplyFlowForces(float deltaTime, Item item)
|
||||||
{
|
{
|
||||||
if (!body.InWater || body.body == null || body.Container != null)
|
|
||||||
return;
|
|
||||||
float floor = rect.Y - rect.Height;
|
|
||||||
float waterLevel = (floor + Volume/rect.Width);
|
|
||||||
|
|
||||||
|
|
||||||
var actionPoint = new Vector2(body.Rect.X, body.Rect.Y);
|
|
||||||
var forceFactor = 1f - ((actionPoint.Y - waterLevel)/Math.Max(body.body.Density - 10, 1));
|
|
||||||
|
|
||||||
if (!(forceFactor > 0f)) return;
|
|
||||||
|
|
||||||
var uplift = -GameMain.World.Gravity*(forceFactor - body.body.LinearVelocity.Y*5);
|
|
||||||
body.body.FarseerBody.ApplyForce(uplift*deltaTime);
|
|
||||||
|
|
||||||
foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0))
|
foreach (var gap in ConnectedGaps.Where(gap => gap.Open > 0))
|
||||||
{
|
{
|
||||||
var pos = gap.Position - body.Position;
|
//var pos = gap.Position - body.Position;
|
||||||
var distance = MathHelper.Max(Vector2.DistanceSquared(body.Position, gap.Position)/1000,1f);
|
var distance = MathHelper.Max(Vector2.DistanceSquared(item.Position, gap.Position)/1000, 1f);
|
||||||
|
|
||||||
pos.Normalize();
|
//pos.Normalize();
|
||||||
body.body.ApplyForce((pos * (gap.LerpedFlowForce/distance)) * deltaTime);
|
item.body.ApplyForce((gap.LerpedFlowForce/distance) * deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ namespace Barotrauma.Networking
|
|||||||
//if the ragdoll is closer than this, don't try to correct its position
|
//if the ragdoll is closer than this, don't try to correct its position
|
||||||
public const float AllowedRagdollDistance = 0.1f;
|
public const float AllowedRagdollDistance = 0.1f;
|
||||||
|
|
||||||
|
//how much the physics body of an item has to move until the server
|
||||||
|
//send a position update to clients (in sim units)
|
||||||
|
public const float ItemPosUpdateDistance = 2.0f;
|
||||||
|
|
||||||
public const float LargeCharacterUpdateInterval = 5.0f;
|
public const float LargeCharacterUpdateInterval = 5.0f;
|
||||||
|
|
||||||
public const float DeleteDisconnectedTime = 10.0f;
|
public const float DeleteDisconnectedTime = 10.0f;
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ namespace Barotrauma.Networking
|
|||||||
ItemFixed = 9,
|
ItemFixed = 9,
|
||||||
|
|
||||||
UpdateProperty = 10,
|
UpdateProperty = 10,
|
||||||
WallDamage = 11
|
WallDamage = 11,
|
||||||
|
|
||||||
|
PhysicsBodyPosition = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
class NetworkEvent
|
class NetworkEvent
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ namespace Barotrauma
|
|||||||
private float drawRotation;
|
private float drawRotation;
|
||||||
|
|
||||||
|
|
||||||
|
private float lastNetworkUpdateTime;
|
||||||
|
public Vector2 LastSentPosition
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly Shape bodyShape;
|
public readonly Shape bodyShape;
|
||||||
public readonly float height, width, radius;
|
public readonly float height, width, radius;
|
||||||
|
|
||||||
@@ -191,6 +198,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
dir = 1.0f;
|
dir = 1.0f;
|
||||||
|
|
||||||
|
LastSentPosition = body.Position;
|
||||||
|
|
||||||
list.Add(this);
|
list.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +250,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
SetTransform(position, 0.0f);
|
SetTransform(position, 0.0f);
|
||||||
|
|
||||||
//prevPosition = ConvertUnits.ToDisplayUnits(position);
|
LastSentPosition = position;
|
||||||
|
|
||||||
list.Add(this);
|
list.Add(this);
|
||||||
}
|
}
|
||||||
@@ -288,23 +297,42 @@ namespace Barotrauma
|
|||||||
prevRotation = rotation;
|
prevRotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetToTargetPosition()
|
public void MoveToTargetPosition(bool lerp = true)
|
||||||
{
|
{
|
||||||
if (targetPosition != Vector2.Zero)
|
if (targetPosition == Vector2.Zero)
|
||||||
{
|
{
|
||||||
body.SetTransform(targetPosition, targetRotation);
|
diffToTargetPos = Vector2.Zero;
|
||||||
body.LinearVelocity = targetVelocity;
|
return;
|
||||||
body.AngularVelocity = targetAngularVelocity;
|
|
||||||
targetPosition = Vector2.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lerp) diffToTargetPos = targetPosition - body.Position;
|
||||||
|
|
||||||
|
body.SetTransform(targetPosition, targetRotation);
|
||||||
|
body.LinearVelocity = targetVelocity;
|
||||||
|
body.AngularVelocity = targetAngularVelocity;
|
||||||
|
targetPosition = Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 diffToTargetPos;
|
||||||
|
|
||||||
public void UpdateDrawPosition()
|
public void UpdateDrawPosition()
|
||||||
{
|
{
|
||||||
drawPosition = Physics.Interpolate(prevPosition, body.Position);
|
drawPosition = Physics.Interpolate(prevPosition, body.Position) - diffToTargetPos;
|
||||||
drawPosition = ConvertUnits.ToDisplayUnits(drawPosition);
|
drawPosition = ConvertUnits.ToDisplayUnits(drawPosition);
|
||||||
|
|
||||||
drawRotation = Physics.Interpolate(prevRotation, body.Rotation);
|
drawRotation = Physics.Interpolate(prevRotation, body.Rotation);
|
||||||
|
|
||||||
|
if (diffToTargetPos == Vector2.Zero) return;
|
||||||
|
|
||||||
|
float diff = diffToTargetPos.Length();
|
||||||
|
if (diff < 0.05f)
|
||||||
|
{
|
||||||
|
diffToTargetPos = Vector2.Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diffToTargetPos -= (diffToTargetPos / diff) * 0.05f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, Sprite sprite, Color color, float? depth = null, float scale = 1.0f)
|
public void Draw(SpriteBatch spriteBatch, Sprite sprite, Color color, float? depth = null, float scale = 1.0f)
|
||||||
@@ -339,6 +367,58 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void FillNetworkData(NetBuffer message)
|
||||||
|
{
|
||||||
|
message.Write(body.Position.X);
|
||||||
|
message.Write(body.Position.Y);
|
||||||
|
message.Write(body.LinearVelocity.X);
|
||||||
|
message.Write(body.LinearVelocity.Y);
|
||||||
|
|
||||||
|
message.Write(body.Rotation);
|
||||||
|
message.Write(body.AngularVelocity);
|
||||||
|
|
||||||
|
LastSentPosition = body.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadNetworkData(NetIncomingMessage message, float sendingTime)
|
||||||
|
{
|
||||||
|
if (sendingTime < lastNetworkUpdateTime) return;
|
||||||
|
|
||||||
|
Vector2 newTargetPos = Vector2.Zero;
|
||||||
|
Vector2 newTargetVel = Vector2.Zero;
|
||||||
|
|
||||||
|
float newTargetRotation = 0.0f, newTargetAngularVel = 0.0f;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
newTargetPos = new Vector2(message.ReadFloat(), message.ReadFloat());
|
||||||
|
newTargetVel = new Vector2(message.ReadFloat(), message.ReadFloat());
|
||||||
|
|
||||||
|
newTargetRotation = message.ReadFloat();
|
||||||
|
newTargetAngularVel = message.ReadFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
DebugConsole.ThrowError("invalid network message", e);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MathUtils.IsValid(newTargetPos) || !MathUtils.IsValid(newTargetVel) ||
|
||||||
|
!MathUtils.IsValid(newTargetRotation) || !MathUtils.IsValid(newTargetAngularVel))
|
||||||
|
return;
|
||||||
|
|
||||||
|
targetPosition = newTargetPos;
|
||||||
|
targetVelocity = newTargetVel;
|
||||||
|
|
||||||
|
targetRotation = newTargetRotation;
|
||||||
|
targetAngularVelocity = newTargetAngularVel;
|
||||||
|
|
||||||
|
lastNetworkUpdateTime = sendingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Remove()
|
public void Remove()
|
||||||
{
|
{
|
||||||
list.Remove(this);
|
list.Remove(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user