summaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/MovementHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/MovementHandler.cpp')
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp534
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);
}