diff options
Diffstat (limited to 'src/server/game/Handlers/MovementHandler.cpp')
| -rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 534 |
1 files changed, 260 insertions, 274 deletions
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 77b5bb43bd..8e7e6c1f35 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -1,14 +1,14 @@ /* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by the - * Free Software Foundation; either version 3 of the License, or (at your - * option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along @@ -105,6 +105,13 @@ void WorldSession::HandleMoveWorldportAck() GetPlayer()->UpdatePositionData(); GetPlayer()->SendInitialPacketsBeforeAddToMap(); + + if (GetPlayer()->GetPendingFlightChange() <= GetPlayer()->GetMapChangeOrderCounter()) + { + if (!GetPlayer()->HasIncreaseMountedFlightSpeedAura() && !GetPlayer()->HasFlyAura()) + GetPlayer()->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_CAN_FLY); + } + if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer())) { LOG_ERROR("network.opcode", "WORLD: failed to teleport player {} ({}) to map {} because of unknown reason!", @@ -370,82 +377,46 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - // Stop emote on move - if (Player* plrMover = mover->ToPlayer()) - { - if (plrMover->GetUInt32Value(UNIT_NPC_EMOTESTATE) != EMOTE_ONESHOT_NONE && movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) - { - plrMover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - } - } - - if (!movementInfo.pos.IsPositionValid()) + if (!ProcessMovementInfo(movementInfo, mover, plrMover, recvData)) { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } - recvData.rfinish(); // prevent warnings spam return; } - if (!mover->movespline->Finalized()) - { - recvData.rfinish(); // prevent warnings spam + if (opcode == CMSG_MOVE_FALL_RESET || opcode == CMSG_MOVE_CHNG_TRANSPORT) return; - } - // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE - if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) - { - // Xinef: skip moving packets - if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } - return; - } - movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ()); + /* process position-change */ + WorldPacket data(opcode, recvData.size()); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); +} - if (mover->IsCreature()) - { - movementInfo.transport.guid = mover->m_movementInfo.transport.guid; - movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ()); - movementInfo.transport.seat = mover->m_movementInfo.transport.seat; - } +void WorldSession::SynchronizeMovement(MovementInfo& movementInfo) +{ + int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; + if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + { + LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); + movementInfo.time = getMSTime(); } - - if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + else { - // We were teleported, skip packets that were broadcast before teleport - if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - //LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport"); - } - recvData.rfinish(); // prevent warnings spam - return; - } + movementInfo.time = (uint32)movementTime; + } +} - if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), - movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } +void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo, Unit* mover) +{ + SynchronizeMovement(movementInfo); - recvData.rfinish(); // prevent warnings spam - return; - } + mover->UpdatePosition(movementInfo.pos); + mover->m_movementInfo = movementInfo; + if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { // if we boarded a transport, add us to it - if (plrMover) + if (Player* plrMover = mover->ToPlayer()) { if (!plrMover->GetTransport()) { @@ -483,44 +454,95 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) } } } - else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave + else if (mover->IsPlayer()) { - sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe + if (Player* plrMover = mover->ToPlayer()) + { + if (plrMover->GetTransport()) // if we were on a transport, leave + { + sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe - plrMover->m_transport->RemovePassenger(plrMover); - plrMover->m_transport = nullptr; - movementInfo.transport.Reset(); + plrMover->m_transport->RemovePassenger(plrMover); + plrMover->m_transport = nullptr; + movementInfo.transport.Reset(); + } + } } - // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) + // Some vehicles allow the passenger to turn by himself + if (Vehicle* vehicle = mover->GetVehicle()) { - plrMover->HandleFall(movementInfo); - - sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + { + if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation()) + { + mover->SetOrientation(movementInfo.pos.GetOrientation()); + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + } + } } - // interrupt parachutes upon falling or landing in water - if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) + if (Player* plrMover = mover->ToPlayer()) // nothing is charmed, or player charmed { - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes + if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) + plrMover->SetStandState(UNIT_STAND_STATE_STAND); + + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) + { + if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) + { + if (plrMover->IsAlive()) + { + plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS); + plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // player can be alive if GM + if (plrMover->IsAlive()) + plrMover->KillPlayer(); + } + else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS)) + { + GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId()); + if (grave) + { + plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation()); + plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation()); + } + } + } + } + } +} +bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, Player* plrMover, Unit* mover, Opcodes opcode) const +{ + if (!movementInfo.pos.IsPositionValid()) + { if (plrMover) { - sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); } + + return false; } - if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) + if (!mover->movespline->Finalized()) { - // now client not include swimming flag in case jumping under water - plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetMap()->IsUnderWater(plrMover->GetPhaseMask(), movementInfo.pos.GetPositionX(), - movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ(), plrMover->GetCollisionHeight())); + if (!mover->movespline->isBoarding() || (opcode != CMSG_FORCE_MOVE_UNROOT_ACK && opcode != CMSG_FORCE_MOVE_ROOT_ACK)) + return false; } - if (plrMover)//Hook for OnPlayerMove + // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE + if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) { - sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode); + // Xinef: skip moving packets + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + return false; + } } bool jumpopcode = false; @@ -530,7 +552,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover)) { plrMover->GetSession()->KickPlayer(); - return; + return false; } } @@ -538,74 +560,104 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover && !sScriptMgr->AnticheatCheckMovementInfo(plrMover, movementInfo, mover, jumpopcode)) { plrMover->GetSession()->KickPlayer(); - return; + return false; } - /* process position-change */ - WorldPacket data(opcode, recvData.size()); - int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); + // We were teleported, skip packets that were broadcast before teleport + if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + //LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport"); + } + return false; + } + + if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), + movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + + return false; + } } - else + + // rooted mover sent packet without root or moving AND root - ignore, due to client crash possibility + if (opcode != CMSG_FORCE_MOVE_UNROOT_ACK) + if (mover->IsRooted() && (!movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT) || movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))) + return false; + + return true; +} + +bool WorldSession::ProcessMovementInfo(MovementInfo& movementInfo, Unit* mover, Player* plrMover, WorldPacket& recvData) +{ + Opcodes opcode = (Opcodes)recvData.GetOpcode(); + if (!VerifyMovementInfo(movementInfo, plrMover, mover, opcode)) + return false; + + if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) { - movementInfo.time = (uint32) movementTime; + movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ()); + + if (mover->IsCreature()) + { + movementInfo.transport.guid = mover->m_movementInfo.transport.guid; + movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ()); + movementInfo.transport.seat = mover->m_movementInfo.transport.seat; + } } - movementInfo.guid = mover->GetGUID(); - WriteMovementInfo(&data, &movementInfo); - mover->SendMessageToSet(&data, _player); + // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). + if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) + { + plrMover->HandleFall(movementInfo); - mover->m_movementInfo = movementInfo; + sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + } - // Some vehicles allow the passenger to turn by himself - if (Vehicle* vehicle = mover->GetVehicle()) + // interrupt parachutes upon falling or landing in water + if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) { - if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes + + if (plrMover) { - if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation()) - { - mover->SetOrientation(movementInfo.pos.GetOrientation()); - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); - } + sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); } + } - return; + if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) + { + // now client not include swimming flag in case jumping under water + plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetMap()->IsUnderWater(plrMover->GetPhaseMask(), movementInfo.pos.GetPositionX(), + movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ(), plrMover->GetCollisionHeight())); } - mover->UpdatePosition(movementInfo.pos); + if (plrMover)//Hook for OnPlayerMove + { + sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode); + } - if (plrMover) // nothing is charmed, or player charmed + if (movementInfo.GetMovementFlags() & MOVEMENTFLAG_MASK_MOVING_OR_TURN) { - if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) - plrMover->SetStandState(UNIT_STAND_STATE_STAND); + if (mover->IsStandState()) + mover->SetStandState(UNIT_STAND_STATE_STAND); + mover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + } + + HandleMoverRelocation(movementInfo, mover); + if (plrMover && opcode != CMSG_MOVE_KNOCK_BACK_ACK) plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); - if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) - if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) - { - if (plrMover->IsAlive()) - { - plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS); - plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // player can be alive if GM - if (plrMover->IsAlive()) - plrMover->KillPlayer(); - } - else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS)) - { - GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId()); - if (grave) - { - plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation()); - plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation()); - } - } - } - } + return true; } void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) @@ -615,26 +667,43 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) /* extract packet */ ObjectGuid guid; - uint32 unk1; + uint32 counter; + MovementInfo movementInfo; float newspeed; recvData >> guid.ReadAsPacked(); + recvData >> counter; // counter or moveEvent + movementInfo.guid = guid; + ReadMovementInfo(recvData, &movementInfo); + recvData >> newspeed; + + Unit* mover = _player->m_mover; // pussywizard: special check, only player mover allowed here - if (guid != _player->m_mover->GetGUID() || guid != _player->GetGUID()) + if (guid != mover->GetGUID() || guid != _player->GetGUID()) { recvData.rfinish(); // prevent warnings spam return; } - // continue parse packet - recvData >> unk1; // counter or moveEvent + // old map - async processing, ignore + if (counter <= _player->GetMapChangeOrderCounter()) + return; - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); + if (!ProcessMovementInfo(movementInfo, mover, _player, recvData)) + { + recvData.rfinish(); // prevent warnings spam + return; + } - recvData >> newspeed; + if (opcode == CMSG_MOVE_SET_COLLISION_HGT_ACK) + { + WorldPacket data(MSG_MOVE_SET_COLLISION_HGT, 18); + WriteMovementInfo(&data, &movementInfo); + data << newspeed; // new collision height + mover->SendMessageToSet(&data, _player); + return; + } // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case @@ -645,42 +714,15 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) switch (opcode) { - case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: - move_type = MOVE_WALK; - force_move_type = MOVE_WALK; - break; - case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: - move_type = MOVE_RUN; - force_move_type = MOVE_RUN; - break; - case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_RUN_BACK; - force_move_type = MOVE_RUN_BACK; - break; - case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: - move_type = MOVE_SWIM; - force_move_type = MOVE_SWIM; - break; - case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_SWIM_BACK; - force_move_type = MOVE_SWIM_BACK; - break; - case CMSG_FORCE_TURN_RATE_CHANGE_ACK: - move_type = MOVE_TURN_RATE; - force_move_type = MOVE_TURN_RATE; - break; - case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: - move_type = MOVE_FLIGHT; - force_move_type = MOVE_FLIGHT; - break; - case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_FLIGHT_BACK; - force_move_type = MOVE_FLIGHT_BACK; - break; - case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: - move_type = MOVE_PITCH_RATE; - force_move_type = MOVE_PITCH_RATE; - break; + case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; + case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; + case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; + case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; + case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; + case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; default: LOG_ERROR("network.opcode", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", opcode); return; @@ -688,6 +730,12 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) sScriptMgr->AnticheatSetUnderACKmount(_player); + SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[move_type]; + WorldPacket data(speedOpcodes[static_cast<size_t>(SpeedOpcodeIndex::ACK_RESPONSE)], 18); + WriteMovementInfo(&data, &movementInfo); + data << newspeed; + mover->SendMessageToSet(&data, _player); + // 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[force_move_type] > 0) @@ -762,11 +810,13 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) { LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK"); + Unit* mover = _player->m_mover; + ObjectGuid guid; recvData >> guid.ReadAsPacked(); // pussywizard: typical check for incomming movement packets - if (!_player->m_mover || !_player->m_mover->IsInWorld() || _player->m_mover->IsDuringRemoveFromWorld() || guid != _player->m_mover->GetGUID()) + if (!mover || !mover->IsInWorld() || mover->IsDuringRemoveFromWorld() || guid != mover->GetGUID()) { recvData.rfinish(); // prevent warnings spam return; @@ -778,7 +828,10 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - _player->m_mover->m_movementInfo = movementInfo; + mover->m_movementInfo = movementInfo; + + if (mover->IsPlayer() && static_cast<Player*>(mover)->IsFreeFlying()) + mover->SetCanFly(true); WorldPacket data(MSG_MOVE_KNOCK_BACK, 66); data << guid.WriteAsPacked(); @@ -793,38 +846,6 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) _player->SendMessageToSet(&data, false); } -void WorldSession::HandleMoveHoverAck(WorldPacket& recvData) -{ - LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK"); - - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - - recvData.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - recvData.read_skip<uint32>(); // unk2 -} - -void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData) -{ - LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK"); - - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - - recvData.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - recvData.read_skip<uint32>(); // unk2 -} - void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData) { if (!_player->IsAlive() || _player->IsInCombat()) @@ -954,79 +975,44 @@ void WorldSession::ComputeNewClockDelta() void WorldSession::HandleMoveRootAck(WorldPacket& recvData) { - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - - Unit* mover = _player->m_mover; - if (!mover || guid != mover->GetGUID()) - { - recvData.rfinish(); // prevent warnings spam - return; - } - - uint32 movementCounter; - recvData >> movementCounter; + Opcodes opcode = (Opcodes)recvData.GetOpcode(); + LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging(opcode)); + ObjectGuid guid; + uint32 counter; MovementInfo movementInfo; + recvData >> guid.ReadAsPacked(); + recvData >> counter; movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - /* process position-change */ - int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) - { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); - } - else - { - movementInfo.time = (uint32)movementTime; - } - - movementInfo.guid = mover->GetGUID(); - mover->m_movementInfo = movementInfo; - mover->UpdatePosition(movementInfo.pos); - -} - -void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData) -{ - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - Unit* mover = _player->m_mover; - if (!mover || guid != mover->GetGUID()) - { - recvData.rfinish(); // prevent warnings spam - return; - } - uint32 movementCounter; - recvData >> movementCounter; - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); + if (mover->GetGUID() != guid) + return; - /* process position-change */ - int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + if (opcode == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); + if (!mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT)) + return; } - else + else // root case { - movementInfo.time = (uint32)movementTime; + if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT)) + return; } - if (G3D::fuzzyEq(movementInfo.fallTime, 0.f)) - { - movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FALLING); - } + // old map - async processing, ignore + if (counter <= _player->GetMapChangeOrderCounter()) + return; - movementInfo.guid = mover->GetGUID(); - mover->m_movementInfo = movementInfo; - mover->UpdatePosition(movementInfo.pos); + if (!ProcessMovementInfo(movementInfo, mover, _player, recvData)) + return; + + if (_player->IsExpectingChangeTransport()) + return; + WorldPacket data(opcode == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); } |
