aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp10
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp44
-rw-r--r--src/server/game/Maps/Map.cpp3
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp5
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h10
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/WorldSession.cpp7
-rw-r--r--src/server/game/Server/WorldSession.h13
-rw-r--r--src/server/game/Server/WorldSocket.cpp2
10 files changed, 75 insertions, 24 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 1f068a0ef96..d117f3739e7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1426,9 +1426,6 @@ bool Player::TeleportTo(TeleportLocation const& teleportLocation, TeleportToOpti
}
SendDirectMessage(transferPending.Write());
-
- RemovePlayerLocalFlag(PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME);
- SetTransportServerTime(0);
}
// remove from old map now
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 9c9d751f3c1..013584e9793 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -64,6 +64,7 @@
#include "SystemPackets.h"
#include "Util.h"
#include "World.h"
+#include <boost/circular_buffer.hpp>
#include <sstream>
class LoginQueryHolder : public CharacterDatabaseQueryHolder
@@ -964,6 +965,9 @@ void WorldSession::HandleContinuePlayerLogin()
SendPacket(WorldPackets::Auth::ResumeComms(CONNECTION_TYPE_INSTANCE).Write());
+ // client will respond to SMSG_RESUME_COMMS with CMSG_QUEUED_MESSAGES_END
+ RegisterTimeSync(SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER);
+
AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder)
{
HandlePlayerLogin(static_cast<LoginQueryHolder const&>(holder));
@@ -1005,6 +1009,12 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder const& holder)
return;
}
+ if (!_timeSyncClockDeltaQueue->empty())
+ {
+ pCurrChar->SetPlayerLocalFlag(PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME);
+ pCurrChar->SetTransportServerTime(_timeSyncClockDelta);
+ }
+
pCurrChar->SetVirtualPlayerRealm(GetVirtualRealmAddress());
SendAccountDataTimes(ObjectGuid::Empty, GLOBAL_CACHE_MASK);
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 5f2ab41c856..3ec02d2ad20 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "AuthenticationPackets.h"
#include "WorldSession.h"
#include "Battleground.h"
#include "Corpse.h"
@@ -783,20 +784,18 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeS
mover->SendMessageToSet(moveSkipTime.Write(), _player);
}
-void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& timeSyncResponse)
+void WorldSession::HandleTimeSync(uint32 counter, int64 clientTime, TimePoint responseReceiveTime)
{
- if (_pendingTimeSyncRequests.count(timeSyncResponse.SequenceIndex) == 0)
+ auto serverTimeAtSent = _pendingTimeSyncRequests.extract(counter);
+ if (!serverTimeAtSent)
return;
- uint32 serverTimeAtSent = _pendingTimeSyncRequests.at(timeSyncResponse.SequenceIndex);
- _pendingTimeSyncRequests.erase(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.
// we are going to make 2 assumptions:
// 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.
- uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent, timeSyncResponse.GetReceivedTime());
- uint32 lagDelay = roundTripDuration / 2;
+ uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent.mapped(), responseReceiveTime);
+ int64 lagDelay = roundTripDuration / 2;
/*
clockDelta = serverTime - clientTime
@@ -808,11 +807,28 @@ void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse&
using the following relation:
serverTime = clockDelta + clientTime
*/
- int64 clockDelta = (int64)serverTimeAtSent + (int64)lagDelay - (int64)timeSyncResponse.ClientTime;
+ int64 clockDelta = serverTimeAtSent.mapped() + lagDelay - clientTime;
_timeSyncClockDeltaQueue->push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
ComputeNewClockDelta();
}
+void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse const& timeSyncResponse)
+{
+ HandleTimeSync(timeSyncResponse.SequenceIndex, timeSyncResponse.ClientTime, timeSyncResponse.GetReceivedTime());
+}
+
+void WorldSession::HandleQueuedMessagesEnd(WorldPackets::Auth::QueuedMessagesEnd const& queuedMessagesEnd)
+{
+ HandleTimeSync(SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER, queuedMessagesEnd.Timestamp, queuedMessagesEnd.GetRawPacket()->GetReceivedTime());
+}
+
+void WorldSession::HandleMoveInitActiveMoverComplete(WorldPackets::Movement::MoveInitActiveMoverComplete const& moveInitActiveMoverComplete)
+{
+ HandleTimeSync(SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER, moveInitActiveMoverComplete.Ticks, moveInitActiveMoverComplete.GetRawPacket()->GetReceivedTime());
+
+ _player->UpdateObjectVisibility(false);
+}
+
void WorldSession::ComputeNewClockDelta()
{
// implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
@@ -846,12 +862,10 @@ void WorldSession::ComputeNewClockDelta()
}
else if (_timeSyncClockDelta == 0)
_timeSyncClockDelta = _timeSyncClockDeltaQueue->back().first;
-}
-void WorldSession::HandleMoveInitActiveMoverComplete(WorldPackets::Movement::MoveInitActiveMoverComplete& moveInitActiveMoverComplete)
-{
- _player->SetPlayerLocalFlag(PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME);
- _player->SetTransportServerTime(GameTime::GetGameTimeMS() - moveInitActiveMoverComplete.Ticks);
-
- _player->UpdateObjectVisibility(false);
+ if (_player)
+ {
+ _player->SetPlayerLocalFlag(PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME);
+ _player->SetTransportServerTime(int32(_timeSyncClockDelta));
+ }
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index a30111070a5..242a18ac88b 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1853,6 +1853,9 @@ void Map::SendInitSelf(Player* player)
WorldPacket packet;
data.BuildPacket(&packet);
player->SendDirectMessage(&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 Map::SendInitTransports(Player* player)
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index c0bda4a873b..8854232466f 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -367,3 +367,8 @@ WorldPacket const* WorldPackets::Auth::EnterEncryptedMode::Write()
return &_worldPacket;
}
+
+void WorldPackets::Auth::QueuedMessagesEnd::Read()
+{
+ _worldPacket >> Timestamp;
+}
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h
index 35007251366..bb838b972f8 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.h
+++ b/src/server/game/Server/Packets/AuthenticationPackets.h
@@ -310,6 +310,16 @@ namespace WorldPackets
std::array<uint8, 32> const& EncryptionKey;
bool Enabled = false;
};
+
+ class QueuedMessagesEnd final : public ClientPacket
+ {
+ public:
+ QueuedMessagesEnd(WorldPacket&& packet) : ClientPacket(CMSG_QUEUED_MESSAGES_END, std::move(packet)) { }
+
+ void Read() override;
+
+ uint32 Timestamp = 0;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 7828e297085..e1a1213359f 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -652,7 +652,7 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_QUEST_LOG_REMOVE_QUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestLogRemoveQuest);
DEFINE_HANDLER(CMSG_QUEST_POI_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleQuestPOIQuery);
DEFINE_HANDLER(CMSG_QUEST_PUSH_RESULT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult);
- DEFINE_HANDLER(CMSG_QUEUED_MESSAGES_END, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_QUEUED_MESSAGES_END, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleQueuedMessagesEnd);
DEFINE_HANDLER(CMSG_QUICK_JOIN_AUTO_ACCEPT_REQUESTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_QUICK_JOIN_REQUEST_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_QUICK_JOIN_RESPOND_TO_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index dedb76379ed..aa44170eac5 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1566,13 +1566,18 @@ void WorldSession::SendTimeSync()
timeSyncRequest.SequenceIndex = _timeSyncNextCounter;
SendPacket(timeSyncRequest.Write());
- _pendingTimeSyncRequests[_timeSyncNextCounter] = getMSTime();
+ RegisterTimeSync(_timeSyncNextCounter);
// Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s)
_timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000;
_timeSyncNextCounter++;
}
+void WorldSession::RegisterTimeSync(uint32 counter)
+{
+ _pendingTimeSyncRequests[counter] = getMSTime();
+}
+
uint32 WorldSession::AdjustClientMovementTime(uint32 time) const
{
int64 movementTime = int64(time) + _timeSyncClockDelta;
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 9f2815750eb..750bdb7a9cf 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -141,6 +141,7 @@ namespace WorldPackets
namespace Auth
{
enum class ConnectToSerial : uint32;
+ class QueuedMessagesEnd;
}
namespace Bank
@@ -1105,8 +1106,12 @@ class TC_GAME_API WorldSession
// Time Synchronisation
void ResetTimeSync();
void SendTimeSync();
+ void RegisterTimeSync(uint32 counter);
uint32 AdjustClientMovementTime(uint32 time) const;
+ static constexpr uint32 SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER = 0xFFFFFFFF;
+ static constexpr uint32 SPECIAL_RESUME_COMMS_TIME_SYNC_COUNTER = 0xFFFFFFFE;
+
// Packets cooldown
time_t GetCalendarEventCreationCooldown() const { return _calendarEventCreationCooldown; }
void SetCalendarEventCreationCooldown(time_t cooldown) { _calendarEventCreationCooldown = cooldown; }
@@ -1265,7 +1270,7 @@ class TC_GAME_API WorldSession
void HandleMoveSetVehicleRecAck(WorldPackets::Vehicle::MoveSetVehicleRecIdAck& setVehicleRecIdAck);
void HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& moveTimeSkipped);
void HandleMovementAckMessage(WorldPackets::Movement::MovementAckMessage& movementAck);
- void HandleMoveInitActiveMoverComplete(WorldPackets::Movement::MoveInitActiveMoverComplete& moveInitActiveMoverComplete);
+ void HandleMoveInitActiveMoverComplete(WorldPackets::Movement::MoveInitActiveMoverComplete const& moveInitActiveMoverComplete);
void HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& packet);
@@ -1544,7 +1549,9 @@ class TC_GAME_API WorldSession
void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty);
void HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty);
void HandleSetTitleOpcode(WorldPackets::Character::SetTitle& packet);
- void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& timeSyncResponse);
+ void HandleTimeSync(uint32 counter, int64 clientTime, TimePoint responseReceiveTime);
+ void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse const& timeSyncResponse);
+ void HandleQueuedMessagesEnd(WorldPackets::Auth::QueuedMessagesEnd const& queuedMessagesEnd);
void HandleWhoIsOpcode(WorldPackets::Who::WhoIsRequest& packet);
void HandleResetInstancesOpcode(WorldPackets::Instance::ResetInstances& packet);
void HandleInstanceLockResponse(WorldPackets::Instance::InstanceLockResponse& packet);
@@ -1847,7 +1854,7 @@ class TC_GAME_API WorldSession
int64 _timeSyncClockDelta;
void ComputeNewClockDelta();
- std::map<uint32, uint32> _pendingTimeSyncRequests; // key: counter. value: server time when packet with that counter was sent.
+ std::map<uint32, int64> _pendingTimeSyncRequests; // key: counter. value: server time when packet with that counter was sent.
uint32 _timeSyncNextCounter;
uint32 _timeSyncTimer;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 2b868ff3884..7f2bd595776 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -478,7 +478,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
[[fallthrough]];
default:
{
- if (opcode == CMSG_TIME_SYNC_RESPONSE)
+ if (opcode == CMSG_TIME_SYNC_RESPONSE || opcode == CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE || opcode == CMSG_QUEUED_MESSAGES_END)
packet.SetReceiveTime(std::chrono::steady_clock::now());
sessionGuard.lock();