diff options
Diffstat (limited to 'src/server/game/Handlers/MovementHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 341 |
1 files changed, 174 insertions, 167 deletions
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 77b5bb43bd..443ac946c0 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -370,82 +370,44 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - // Stop emote on move - if (Player* plrMover = mover->ToPlayer()) + if (!ProcessMovementInfo(movementInfo, mover, plrMover, recvData)) { - 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 (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } - recvData.rfinish(); // prevent warnings spam return; } - if (!mover->movespline->Finalized()) - { - recvData.rfinish(); // prevent warnings spam - return; - } + /* process position-change */ + WorldPacket data(opcode, recvData.size()); + movementInfo.guid = mover->GetGUID(); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); +} - // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE - if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) +void WorldSession::SynchronizeMovement(MovementInfo& movementInfo) +{ + int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; + if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) { - // 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()); - - 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; - } + 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 +445,92 @@ 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 (plrMover) + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) { - sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + 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()); + } + } + } } } +} - if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) +bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, Player* plrMover, Unit* mover, Opcodes opcode) const +{ + if (!movementInfo.pos.IsPositionValid()) { - // 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 (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + + return false; } - if (plrMover)//Hook for OnPlayerMove + if (!mover->movespline->Finalized()) + return false; + + // 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 +540,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover)) { plrMover->GetSession()->KickPlayer(); - return; + return false; } } @@ -538,74 +548,98 @@ 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 + 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) @@ -762,11 +796,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 +814,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 +832,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()) |