mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 17:05:44 +01:00
Core/Players: Improve setting ActivePlayerData::TransportServerTime by including TIME_SYNC and CMSG_QUEUED_MESSAGES_END values in its calculation
* This removes delay on nearby object visibility after login and teleport
(cherry picked from commit 821ecf8fa3)
# Conflicts:
# src/server/game/Server/Protocol/Opcodes.cpp
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -367,3 +367,8 @@ WorldPacket const* WorldPackets::Auth::EnterEncryptedMode::Write()
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void WorldPackets::Auth::QueuedMessagesEnd::Read()
|
||||
{
|
||||
_worldPacket >> Timestamp;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user