Core/Players: Improve setting ActivePlayerData::TransportServerTime by including TIME_SYNC and CMSG_QUEUED_MESSAGES_END values in its calculation
Port From (https://github.com/TrinityCore/TrinityCore/commit/821ecf8fa3b6b922ba178cde7593ef5d84ef734b)
This commit is contained in:
@@ -2195,9 +2195,6 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
SendPacket(transferPending);
|
SendPacket(transferPending);
|
||||||
|
|
||||||
RemovePlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime);
|
|
||||||
SetTransportServerTime(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove from old map now
|
// remove from old map now
|
||||||
|
|||||||
@@ -783,6 +783,9 @@ namespace Game
|
|||||||
|
|
||||||
SendPacket(new ResumeComms(ConnectionType.Instance));
|
SendPacket(new ResumeComms(ConnectionType.Instance));
|
||||||
|
|
||||||
|
// client will respond to SMSG_RESUME_COMMS with CMSG_QUEUED_MESSAGES_END
|
||||||
|
RegisterTimeSync(SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER);
|
||||||
|
|
||||||
AddQueryHolderCallback(DB.Characters.DelayQueryHolder(holder)).AfterComplete(holder => HandlePlayerLogin((LoginQueryHolder)holder));
|
AddQueryHolderCallback(DB.Characters.DelayQueryHolder(holder)).AfterComplete(holder => HandlePlayerLogin((LoginQueryHolder)holder));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,6 +802,12 @@ namespace Game
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_timeSyncClockDeltaQueue.IsEmpty)
|
||||||
|
{
|
||||||
|
pCurrChar.SetPlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime);
|
||||||
|
pCurrChar.SetTransportServerTime((int)_timeSyncClockDelta);
|
||||||
|
}
|
||||||
|
|
||||||
pCurrChar.SetVirtualPlayerRealm(Global.WorldMgr.GetVirtualRealmAddress());
|
pCurrChar.SetVirtualPlayerRealm(Global.WorldMgr.GetVirtualRealmAddress());
|
||||||
|
|
||||||
SendAccountDataTimes(ObjectGuid.Empty, AccountDataTypes.GlobalCacheMask);
|
SendAccountDataTimes(ObjectGuid.Empty, AccountDataTypes.GlobalCacheMask);
|
||||||
|
|||||||
@@ -854,21 +854,20 @@ namespace Game
|
|||||||
GetPlayer().CastSpell(GetPlayer(), 2479, true);
|
GetPlayer().CastSpell(GetPlayer(), 2479, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[WorldPacketHandler(ClientOpcodes.TimeSyncResponse, Processing = PacketProcessing.ThreadSafe)]
|
void HandleTimeSync(uint counter, long clientTime, DateTime responseReceiveTime)
|
||||||
void HandleTimeSyncResponse(TimeSyncResponse timeSyncResponse)
|
|
||||||
{
|
{
|
||||||
if (!_pendingTimeSyncRequests.ContainsKey(timeSyncResponse.SequenceIndex))
|
var serverTimeAtSent = _pendingTimeSyncRequests.LookupByKey(counter);
|
||||||
|
if (serverTimeAtSent == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint serverTimeAtSent = _pendingTimeSyncRequests.LookupByKey(timeSyncResponse.SequenceIndex);
|
_pendingTimeSyncRequests.Remove(counter);
|
||||||
_pendingTimeSyncRequests.Remove(timeSyncResponse.SequenceIndex);
|
|
||||||
|
|
||||||
// time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
|
// time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
|
||||||
// we are going to make 2 assumptions:
|
// we are going to make 2 assumptions:
|
||||||
// 1) we assume that the request processing time equals 0.
|
// 1) we assume that the request processing time equals 0.
|
||||||
// 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
|
// 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
|
||||||
uint roundTripDuration = Time.GetMSTimeDiff(serverTimeAtSent, timeSyncResponse.GetReceivedTime());
|
uint roundTripDuration = Time.GetMSTimeDiff((uint)serverTimeAtSent, responseReceiveTime);
|
||||||
uint lagDelay = roundTripDuration / 2;
|
long lagDelay = roundTripDuration / 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
clockDelta = serverTime - clientTime
|
clockDelta = serverTime - clientTime
|
||||||
@@ -880,11 +879,31 @@ namespace Game
|
|||||||
using the following relation:
|
using the following relation:
|
||||||
serverTime = clockDelta + clientTime
|
serverTime = clockDelta + clientTime
|
||||||
*/
|
*/
|
||||||
long clockDelta = (long)(serverTimeAtSent + lagDelay) - (long)timeSyncResponse.ClientTime;
|
long clockDelta = serverTimeAtSent + lagDelay - clientTime;
|
||||||
_timeSyncClockDeltaQueue.PushFront(Tuple.Create(clockDelta, roundTripDuration));
|
_timeSyncClockDeltaQueue.PushFront(Tuple.Create(clockDelta, roundTripDuration));
|
||||||
ComputeNewClockDelta();
|
ComputeNewClockDelta();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[WorldPacketHandler(ClientOpcodes.TimeSyncResponse, Processing = PacketProcessing.ThreadSafe)]
|
||||||
|
void HandleTimeSyncResponse(TimeSyncResponse timeSyncResponse)
|
||||||
|
{
|
||||||
|
HandleTimeSync(timeSyncResponse.SequenceIndex, timeSyncResponse.ClientTime, timeSyncResponse.GetReceivedTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
[WorldPacketHandler(ClientOpcodes.QueuedMessagesEnd, Status = SessionStatus.Authed, Processing = PacketProcessing.Inplace)]
|
||||||
|
void HandleQueuedMessagesEnd(QueuedMessagesEnd queuedMessagesEnd)
|
||||||
|
{
|
||||||
|
HandleTimeSync(SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER, queuedMessagesEnd.Timestamp, queuedMessagesEnd.GetWorldPacket().GetReceivedTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
[WorldPacketHandler(ClientOpcodes.MoveInitActiveMoverComplete, Processing = PacketProcessing.ThreadSafe)]
|
||||||
|
void HandleMoveInitActiveMoverComplete(MoveInitActiveMoverComplete moveInitActiveMoverComplete)
|
||||||
|
{
|
||||||
|
HandleTimeSync(SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER, moveInitActiveMoverComplete.Ticks, moveInitActiveMoverComplete.GetWorldPacket().GetReceivedTime());
|
||||||
|
|
||||||
|
_player.UpdateObjectVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
void ComputeNewClockDelta()
|
void ComputeNewClockDelta()
|
||||||
{
|
{
|
||||||
// implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
|
// implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
|
||||||
@@ -921,15 +940,12 @@ namespace Game
|
|||||||
var back = _timeSyncClockDeltaQueue.Back();
|
var back = _timeSyncClockDeltaQueue.Back();
|
||||||
_timeSyncClockDelta = back.Item1;
|
_timeSyncClockDelta = back.Item1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[WorldPacketHandler(ClientOpcodes.MoveInitActiveMoverComplete, Processing = PacketProcessing.ThreadSafe)]
|
if (_player != null)
|
||||||
void HandleMoveInitActiveMoverComplete(MoveInitActiveMoverComplete moveInitActiveMoverComplete)
|
{
|
||||||
{
|
_player.SetPlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime);
|
||||||
_player.SetPlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime);
|
_player.SetTransportServerTime((int)_timeSyncClockDelta);
|
||||||
_player.SetTransportServerTime((int)(GameTime.GetGameTimeMS() - moveInitActiveMoverComplete.Ticks));
|
}
|
||||||
|
|
||||||
_player.UpdateObjectVisibility(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1767,6 +1767,9 @@ namespace Game.Maps
|
|||||||
UpdateObject packet;
|
UpdateObject packet;
|
||||||
data.BuildPacket(out packet);
|
data.BuildPacket(out packet);
|
||||||
player.SendPacket(packet);
|
player.SendPacket(packet);
|
||||||
|
|
||||||
|
// client will respond to SMSG_UPDATE_OBJECT that contains ThisIsYou = true with CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE
|
||||||
|
player.GetSession().RegisterTimeSync(WorldSession.SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendInitTransports(Player player)
|
void SendInitTransports(Player player)
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ namespace Game.Networking
|
|||||||
Log.outDebug(LogFilter.Network, "Received ClientOpcode: {0} From: {1}", GetOpcode(), session != null ? session.GetPlayerInfo() : "Unknown IP");
|
Log.outDebug(LogFilter.Network, "Received ClientOpcode: {0} From: {1}", GetOpcode(), session != null ? session.GetPlayerInfo() : "Unknown IP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WorldPacket GetWorldPacket()
|
||||||
|
{
|
||||||
|
return _worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
protected WorldPacket _worldPacket;
|
protected WorldPacket _worldPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -411,6 +411,18 @@ namespace Game.Networking.Packets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QueuedMessagesEnd : ClientPacket
|
||||||
|
{
|
||||||
|
public uint Timestamp;
|
||||||
|
|
||||||
|
public QueuedMessagesEnd(WorldPacket packet) : base(packet) { }
|
||||||
|
|
||||||
|
public override void Read()
|
||||||
|
{
|
||||||
|
Timestamp = _worldPacket.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Structs
|
//Structs
|
||||||
public struct AuthWaitInfo
|
public struct AuthWaitInfo
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ namespace Game
|
|||||||
{
|
{
|
||||||
public partial class WorldSession : IDisposable
|
public partial class WorldSession : IDisposable
|
||||||
{
|
{
|
||||||
|
public static uint SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER = 0xFFFFFFFF;
|
||||||
|
public static uint SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER = 0xFFFFFFFE;
|
||||||
|
|
||||||
public WorldSession(uint id, string name, uint battlenetAccountId, WorldSocket sock, AccountTypes sec, Expansion expansion, long mute_time, string os, TimeSpan timezoneOffset, uint build, Framework.ClientBuild.ClientBuildVariantId clientBuildVariant, Locale locale, uint recruiter, bool isARecruiter)
|
public WorldSession(uint id, string name, uint battlenetAccountId, WorldSocket sock, AccountTypes sec, Expansion expansion, long mute_time, string os, TimeSpan timezoneOffset, uint build, Framework.ClientBuild.ClientBuildVariantId clientBuildVariant, Locale locale, uint recruiter, bool isARecruiter)
|
||||||
{
|
{
|
||||||
m_muteTime = mute_time;
|
m_muteTime = mute_time;
|
||||||
@@ -888,13 +891,18 @@ namespace Game
|
|||||||
timeSyncRequest.SequenceIndex = _timeSyncNextCounter;
|
timeSyncRequest.SequenceIndex = _timeSyncNextCounter;
|
||||||
SendPacket(timeSyncRequest);
|
SendPacket(timeSyncRequest);
|
||||||
|
|
||||||
_pendingTimeSyncRequests[_timeSyncNextCounter] = Time.GetMSTime();
|
RegisterTimeSync(_timeSyncNextCounter);
|
||||||
|
|
||||||
// Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s)
|
// Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s)
|
||||||
_timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000u;
|
_timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000u;
|
||||||
_timeSyncNextCounter++;
|
_timeSyncNextCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RegisterTimeSync(uint counter)
|
||||||
|
{
|
||||||
|
_pendingTimeSyncRequests[counter] = Time.GetMSTime();
|
||||||
|
}
|
||||||
|
|
||||||
uint AdjustClientMovementTime(uint time)
|
uint AdjustClientMovementTime(uint time)
|
||||||
{
|
{
|
||||||
long movementTime = (long)time + _timeSyncClockDelta;
|
long movementTime = (long)time + _timeSyncClockDelta;
|
||||||
@@ -998,7 +1006,7 @@ namespace Game
|
|||||||
CircularBuffer<Tuple<long, uint>> _timeSyncClockDeltaQueue = new(6); // first member: clockDelta. Second member: latency of the packet exchange that was used to compute that clockDelta.
|
CircularBuffer<Tuple<long, uint>> _timeSyncClockDeltaQueue = new(6); // first member: clockDelta. Second member: latency of the packet exchange that was used to compute that clockDelta.
|
||||||
long _timeSyncClockDelta;
|
long _timeSyncClockDelta;
|
||||||
|
|
||||||
Dictionary<uint, uint> _pendingTimeSyncRequests = new(); // key: counter. value: server time when packet with that counter was sent.
|
Dictionary<uint, long> _pendingTimeSyncRequests = new(); // key: counter. value: server time when packet with that counter was sent.
|
||||||
uint _timeSyncNextCounter;
|
uint _timeSyncNextCounter;
|
||||||
uint _timeSyncTimer;
|
uint _timeSyncTimer;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user