From a7ebacfe7b08711356fa8b6a2649ad265e38bb4f Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Wed, 13 Nov 2019 10:25:58 +0100 Subject: [PATCH] Core/Movement: * fixed packet structure field order of MSG_MOVE_TIME_SKIPPED * send move_update opcodes to players after the target player's client has confirmed the speed change via ack opcode *todo: implement anti-cheat checks --- src/server/game/Entities/Player/Player.cpp | 5 +- src/server/game/Entities/Unit/Unit.cpp | 22 ++++---- src/server/game/Handlers/MovementHandler.cpp | 57 ++++++++++++++++---- src/server/game/Server/WorldSession.cpp | 6 +-- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4fff7b0a2c..c1943f447f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -27997,7 +27997,7 @@ void Player::SendMovementSetCollisionHeight(float height) static MovementStatusElements const heightElement = MSEExtraFloat; Movement::ExtraMovementStatusElement extra(&heightElement); extra.Data.floatData = height; - Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_SET_COLLISION_HEIGHT, SMSG_MOVE_UPDATE_COLLISION_HEIGHT, &extra).Send(); + Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_SET_COLLISION_HEIGHT, NULL_OPCODE, &extra).Send(); } std::string Player::GetMapAreaAndZoneString() const @@ -28436,8 +28436,7 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING) && (!hasFallData || !hasFallDirection), MOVEMENTFLAG_FALLING); - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) && - (!hasSplineElevation || G3D::fuzzyEq(mi->splineElevation, 0.0f)), MOVEMENTFLAG_SPLINE_ELEVATION); + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) && G3D::fuzzyEq(mi->splineElevation, 0.0f), MOVEMENTFLAG_SPLINE_ELEVATION); // Client first checks if spline elevation != 0, then verifies flag presence if (hasSplineElevation) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9ae316a99f..d80ea35f9c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9100,17 +9100,17 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) PropagateSpeedChange(); - static OpcodeServer const moveTypeToOpcode[MAX_MOVE_TYPE][3] = + static OpcodeServer const moveTypeToOpcode[MAX_MOVE_TYPE][2] = { - {SMSG_SPLINE_MOVE_SET_WALK_SPEED, SMSG_MOVE_SET_WALK_SPEED, SMSG_MOVE_UPDATE_WALK_SPEED }, - {SMSG_SPLINE_MOVE_SET_RUN_SPEED, SMSG_MOVE_SET_RUN_SPEED, SMSG_MOVE_UPDATE_RUN_SPEED }, - {SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_UPDATE_RUN_BACK_SPEED }, - {SMSG_SPLINE_MOVE_SET_SWIM_SPEED, SMSG_MOVE_SET_SWIM_SPEED, SMSG_MOVE_UPDATE_SWIM_SPEED }, - {SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_UPDATE_SWIM_BACK_SPEED }, - {SMSG_SPLINE_MOVE_SET_TURN_RATE, SMSG_MOVE_SET_TURN_RATE, SMSG_MOVE_UPDATE_TURN_RATE }, - {SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_UPDATE_FLIGHT_SPEED }, - {SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED}, - {SMSG_SPLINE_MOVE_SET_PITCH_RATE, SMSG_MOVE_SET_PITCH_RATE, SMSG_MOVE_UPDATE_PITCH_RATE }, + {SMSG_SPLINE_MOVE_SET_WALK_SPEED, SMSG_MOVE_SET_WALK_SPEED }, + {SMSG_SPLINE_MOVE_SET_RUN_SPEED, SMSG_MOVE_SET_RUN_SPEED }, + {SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, SMSG_MOVE_SET_RUN_BACK_SPEED }, + {SMSG_SPLINE_MOVE_SET_SWIM_SPEED, SMSG_MOVE_SET_SWIM_SPEED }, + {SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, SMSG_MOVE_SET_SWIM_BACK_SPEED }, + {SMSG_SPLINE_MOVE_SET_TURN_RATE, SMSG_MOVE_SET_TURN_RATE, }, + {SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, SMSG_MOVE_SET_FLIGHT_SPEED, }, + {SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, SMSG_MOVE_SET_FLIGHT_BACK_SPEED, }, + {SMSG_SPLINE_MOVE_SET_PITCH_RATE, SMSG_MOVE_SET_PITCH_RATE, } }; if (GetTypeId() == TYPEID_PLAYER) @@ -9128,7 +9128,7 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) Movement::ExtraMovementStatusElement extra(&speedVal); extra.Data.floatData = GetSpeed(mtype); - Movement::PacketSender(this, moveTypeToOpcode[mtype][0], moveTypeToOpcode[mtype][1], moveTypeToOpcode[mtype][2], &extra).Send(); + Movement::PacketSender(this, moveTypeToOpcode[mtype][0], moveTypeToOpcode[mtype][1], NULL_OPCODE, &extra).Send(); } void Unit::RemoveAllFollowers() diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index ce1ce418c1..1432c73b1a 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -393,7 +393,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) { TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = GameTime::GetGameTimeMS(); + movementInfo.time = getMSTime(); } else { @@ -490,22 +490,55 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData) "PitchRate" }; + OpcodeServer moveUpdateOpcode = OpcodeServer(NULL_OPCODE); switch (recvData.GetOpcode()) { - case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break; - case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break; - case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; break; - case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break; - case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; break; - case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break; - case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break; - case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; break; - case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break; + case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: + move_type = MOVE_WALK; + moveUpdateOpcode = SMSG_MOVE_UPDATE_WALK_SPEED; + break; + case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: + move_type = MOVE_RUN; + moveUpdateOpcode = SMSG_MOVE_UPDATE_RUN_SPEED; + break; + case CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK: + move_type = MOVE_RUN_BACK; + moveUpdateOpcode = SMSG_MOVE_UPDATE_RUN_BACK_SPEED; + break; + case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: + move_type = MOVE_SWIM; + moveUpdateOpcode = SMSG_MOVE_UPDATE_SWIM_SPEED; + break; + case CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: + move_type = MOVE_SWIM_BACK; + moveUpdateOpcode = SMSG_MOVE_UPDATE_SWIM_BACK_SPEED; + break; + case CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK: + move_type = MOVE_TURN_RATE; + moveUpdateOpcode = SMSG_MOVE_UPDATE_TURN_RATE; + break; + case CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK: + move_type = MOVE_FLIGHT; + moveUpdateOpcode = SMSG_MOVE_UPDATE_FLIGHT_SPEED; + break; + case CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: + move_type = MOVE_FLIGHT_BACK; + moveUpdateOpcode = SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED; + break; + case CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK: + move_type = MOVE_PITCH_RATE; + moveUpdateOpcode = SMSG_MOVE_UPDATE_PITCH_RATE; + break; default: TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", recvData.GetOpcode()); return; } + static MovementStatusElements const speedVal = MSEExtraFloat; + Movement::ExtraMovementStatusElement extra(&speedVal); + extra.Data.floatData = newspeed; + Movement::PacketSender(_player, NULL_OPCODE, NULL_OPCODE, moveUpdateOpcode, &extra).Send(); + // skip all forced speed changes except last and unexpected // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both. if (_player->m_forced_speed_changes[move_type] > 0) @@ -639,6 +672,8 @@ void WorldSession::HandleSetCollisionHeightAck(WorldPacket& recvPacket) Movement::ExtraMovementStatusElement extra(&heightElement); MovementInfo movementInfo; GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo, &extra); + + Movement::PacketSender(_player, NULL_OPCODE, NULL_OPCODE, SMSG_MOVE_UPDATE_COLLISION_HEIGHT, &extra).Send(); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData) @@ -685,8 +720,8 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData) mover->m_movementInfo.time += time; WorldPacket data(MSG_MOVE_TIME_SKIPPED, recvData.size()); - data << guid.WriteAsPacked(); data << time; + data << guid.WriteAsPacked(); GetPlayer()->SendMessageToSet(&data, false); } diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index ad9efaf91b..ee08e86350 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -467,7 +467,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter { - // Send time sync packet every 10s. + // Send time sync packet every 5s. if (_timeSyncTimer > 0) { if (diff >= _timeSyncTimer) @@ -1604,7 +1604,7 @@ void WorldSession::SendTimeSync() _pendingTimeSyncRequests[_timeSyncNextCounter] = getMSTime(); - // Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s) - _timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000; + // Schedule next sync in 5 sec (sniffs sometimes vary between 5 and 6 seconds. Probably due to their 400 batch interval) + _timeSyncTimer = 5000; _timeSyncNextCounter++; }