Skip to content

Commit

Permalink
fix(982): expire dashes based on end time in case packets are delayed (
Browse files Browse the repository at this point in the history
…#2508)

* add logging to Options.LoadFromServer

* fix(982): expire dashes based on end time in case packets are delayed
  • Loading branch information
lodicolo authored Jan 25, 2025
1 parent 4f348c2 commit cd40256
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 61 deletions.
10 changes: 9 additions & 1 deletion Framework/Intersect.Framework.Core/Config/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,15 @@ public static void SaveToDisk()

public static void LoadFromServer(string data)
{
Instance = JsonConvert.DeserializeObject<Options>(data);
try
{
Instance = JsonConvert.DeserializeObject<Options>(data);
}
catch (Exception exception)
{
ApplicationContext.CurrentContext.Logger.LogError(exception, "Failed to load options from server");
throw;
}
}

// ReSharper disable once UnusedMember.Global
Expand Down
14 changes: 9 additions & 5 deletions Intersect (Core)/Network/Packets/Server/EntityDashPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ public EntityDashPacket()
{
}

public EntityDashPacket(Guid entityId, Guid endMapId, byte endX, byte endY, int dashTime, Direction direction)
public EntityDashPacket(Guid entityId, Guid endMapId, int endX, int endY, long dashEndMilliseconds, int dashLengthMilliseconds, Direction direction)
{
EntityId = entityId;
EndMapId = endMapId;
EndX = endX;
EndY = endY;
DashTime = dashTime;
EndX = (byte)endX;
EndY = (byte)endY;
DashEndMilliseconds = dashEndMilliseconds;
DashLengthMilliseconds = dashLengthMilliseconds;
Direction = direction;
}

Expand All @@ -34,9 +35,12 @@ public EntityDashPacket(Guid entityId, Guid endMapId, byte endX, byte endY, int
public byte EndY { get; set; }

[Key(4)]
public int DashTime { get; set; }
public long DashEndMilliseconds { get; set; }

[Key(5)]
public int DashLengthMilliseconds { get; set; }

[Key(6)]
public Direction Direction { get; set; }

}
108 changes: 69 additions & 39 deletions Intersect.Client.Core/Entities/Dash.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
using Intersect.Client.Framework.Entities;
using Intersect.Client.Maps;
using Intersect.Core;
using Intersect.Enums;
using Intersect.Utilities;
using Microsoft.Extensions.Logging;

namespace Intersect.Client.Entities;

public partial class Dash : IDash
{
private readonly Direction mChangeDirection = Direction.None;

private readonly int mDashTime;
private readonly long _serverDashEndMilliseconds;

private readonly long _dashLengthMilliseconds;

private long _dashEndMilliseconds;

private readonly Guid mEndMapId;

Expand All @@ -31,75 +37,99 @@ public partial class Dash : IDash

public float OffsetY => GetYOffset();

public Dash(Guid endMapId, byte endX, byte endY, int dashTime, Direction changeDirection = Direction.None)
public Dash(
Guid endMapId,
byte endX,
byte endY,
long dashEndMilliseconds,
long dashLengthMilliseconds,
Direction changeDirection = Direction.None
)
{
mChangeDirection = changeDirection;
mEndMapId = endMapId;
mEndX = endX;
mEndY = endY;
mDashTime = dashTime;
_serverDashEndMilliseconds = dashEndMilliseconds;
_dashLengthMilliseconds = dashLengthMilliseconds;
}

public void Start(Entity en)
public void Start(Entity entity)
{
if (MapInstance.Get(en.MapId) == null ||
MapInstance.Get(mEndMapId) == null ||
mEndMapId == en.MapId && mEndX == en.X && mEndY == en.Y)
var now = Timing.Global.Milliseconds;

if (_serverDashEndMilliseconds < now)
{
ApplicationContext.CurrentContext.Logger.LogDebug("Skipping already-expired dash");
entity.Dashing = null;
return;
}

if (mEndMapId == entity.MapId && mEndX == entity.X && mEndY == entity.Y)
{
entity.Dashing = null;
return;
}

if (!MapInstance.TryGet(entity.MapId, out var currentMap) || !MapInstance.TryGet(mEndMapId, out var targetMap))
{
en.Dashing = null;
entity.Dashing = null;
return;
}
else

mStartTime = now;
_dashEndMilliseconds = Math.Min(_serverDashEndMilliseconds, mStartTime + _dashLengthMilliseconds);

ApplicationContext.CurrentContext.Logger.LogDebug(
"Starting dash that is {DashLength}ms long, and there are {RemainingTime}ms before it is completed on the server",
_dashLengthMilliseconds,
_serverDashEndMilliseconds - now
);

mStartXCoord = entity.X;
mStartYCoord = entity.Y;
mEndXCoord = targetMap.X + mEndX * Options.Instance.Map.TileWidth - (currentMap.X + entity.X * Options.Instance.Map.TileWidth);
mEndYCoord = targetMap.Y + mEndY * Options.Instance.Map.TileHeight - (currentMap.Y + entity.Y * Options.Instance.Map.TileHeight);
if (mChangeDirection > Direction.None)
{
var startMap = MapInstance.Get(en.MapId);
var endMap = MapInstance.Get(mEndMapId);
mStartTime = Timing.Global.Milliseconds;
mStartXCoord = en.OffsetX;
mStartYCoord = en.OffsetY;
mEndXCoord = endMap.X + mEndX * Options.Instance.Map.TileWidth - (startMap.X + en.X * Options.Instance.Map.TileWidth);
mEndYCoord = endMap.Y + mEndY * Options.Instance.Map.TileHeight - (startMap.Y + en.Y * Options.Instance.Map.TileHeight);
if (mChangeDirection > Direction.None)
{
en.Dir = mChangeDirection;
}
entity.Dir = mChangeDirection;
}
}

public float GetXOffset()
{
if (Timing.Global.Milliseconds > mStartTime + mDashTime)
if (Timing.Global.Milliseconds > mStartTime + _dashLengthMilliseconds)
{
return mEndXCoord;
}
else
{
return (mEndXCoord - mStartXCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime);
}

return (mEndXCoord - mStartXCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)_dashLengthMilliseconds);
}

public float GetYOffset()
{
if (Timing.Global.Milliseconds > mStartTime + mDashTime)
if (Timing.Global.Milliseconds > mStartTime + _dashLengthMilliseconds)
{
return mEndYCoord;
}
else
{
return (mEndYCoord - mStartYCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime);
}

return (mEndYCoord - mStartYCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)_dashLengthMilliseconds);
}

public bool Update(Entity en)
public bool Update(Entity entity)
{
if (Timing.Global.Milliseconds > mStartTime + mDashTime)
if (Timing.Global.Milliseconds <= _dashEndMilliseconds)
{
en.Dashing = null;
en.OffsetX = 0;
en.OffsetY = 0;
en.MapId = mEndMapId;
en.X = mEndX;
en.Y = mEndY;
return entity.Dashing != null;
}

return en.Dashing != null;
ApplicationContext.CurrentContext.Logger.LogDebug("Dash finished");
entity.Dashing = null;
entity.OffsetX = 0;
entity.OffsetY = 0;
entity.MapId = mEndMapId;
entity.X = mEndX;
entity.Y = mEndY;
return false;
}
}
21 changes: 13 additions & 8 deletions Intersect.Client.Core/Networking/PacketHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1838,16 +1838,21 @@ public void HandlePacket(IPacketSender packetSender, GameObjectPacket packet)
//EntityDashPacket
public void HandlePacket(IPacketSender packetSender, EntityDashPacket packet)
{
if (Globals.Entities.ContainsKey(packet.EntityId))
if (!Globals.Entities.TryGetValue(packet.EntityId, out var value))
{
Globals.Entities[packet.EntityId]
.DashQueue.Enqueue(
new Dash(
packet.EndMapId, packet.EndX, packet.EndY,
packet.DashTime, packet.Direction
)
);
return;
}

value.DashQueue.Enqueue(
new Dash(
packet.EndMapId,
packet.EndX,
packet.EndY,
packet.DashEndMilliseconds,
packet.DashLengthMilliseconds,
packet.Direction
)
);
}

//MapGridPacket
Expand Down
22 changes: 16 additions & 6 deletions Intersect.Server.Core/Entities/Combat/Dash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public partial class Dash
public int Range;

public Dash(
Entity en,
Entity entity,
int range,
Direction direction,
bool blockPass = false,
Expand All @@ -27,20 +27,30 @@ public Dash(
)
{
Direction = direction;
Facing = en.Dir;
Facing = entity.Dir;

CalculateRange(en, range, blockPass, activeResourcePass, deadResourcePass, zdimensionPass);
CalculateRange(entity, range, blockPass, activeResourcePass, deadResourcePass, zdimensionPass);
if (Range <= 0)
{
return;
} //Remove dash instance if no where to dash

var endX = entity.X;
var endY = entity.Y;

var dashLengthMilliseconds = (int)(Options.Instance.Combat.MaxDashSpeed);// * (Range / 10f));
var dashEndMilliseconds = Timing.Global.Milliseconds + dashLengthMilliseconds;
entity.MoveTimer = dashEndMilliseconds;

PacketSender.SendEntityDash(
en, en.MapId, (byte) en.X, (byte) en.Y, (int) (Options.Instance.Combat.MaxDashSpeed * (Range / 10f)),
entity,
entity.MapId,
endX,
endY,
dashEndMilliseconds,
dashLengthMilliseconds,
Direction == Facing ? Direction : Direction.None
);

en.MoveTimer = Timing.Global.Milliseconds + Options.Instance.Combat.MaxDashSpeed;
}

public void CalculateRange(
Expand Down
24 changes: 22 additions & 2 deletions Intersect.Server.Core/Networking/PacketSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1922,9 +1922,29 @@ public static void SendOpenEditor(Client client, GameObjectType type)
}

//EntityDashPacket
public static void SendEntityDash(Entity en, Guid endMapId, byte endX, byte endY, int dashTime, Direction direction)
public static void SendEntityDash(
Entity en,
Guid endMapId,
int endX,
int endY,
long dashEndMilliseconds,
int dashLengthMilliseconds,
Direction direction
)
{
SendDataToProximityOnMapInstance(en.MapId, en.MapInstanceId, new EntityDashPacket(en.Id, endMapId, endX, endY, dashTime, direction));
SendDataToProximityOnMapInstance(
en.MapId,
en.MapInstanceId,
new EntityDashPacket(
en.Id,
endMapId,
endX,
endY,
dashEndMilliseconds,
dashLengthMilliseconds,
direction
)
);
}

/// <summary>
Expand Down

0 comments on commit cd40256

Please sign in to comment.