aboutsummaryrefslogtreecommitdiff
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.cpp311
1 files changed, 255 insertions, 56 deletions
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 7b7ccf8771c..a292db59548 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -15,23 +15,25 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "Battleground.h"
#include "Common.h"
-#include "WorldPacket.h"
-#include "WorldSession.h"
-#include "Opcodes.h"
-#include "Log.h"
#include "Corpse.h"
-#include "Player.h"
+#include "GameTime.h"
+#include "GameClient.h"
+#include "InstanceSaveMgr.h"
+#include "Log.h"
#include "MapManager.h"
#include "MotionMaster.h"
#include "MovementGenerator.h"
#include "MoveSpline.h"
-#include "Transport.h"
-#include "Battleground.h"
-#include "InstanceSaveMgr.h"
+#include "ObjectAccessor.h"
#include "ObjectMgr.h"
+#include "Opcodes.h"
+#include "Player.h"
+#include "Transport.h"
#include "Vehicle.h"
-#include "GameTime.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
#include <boost/accumulators/statistics/variance.hpp>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
@@ -212,17 +214,22 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
recvData >> guid.ReadAsPacked();
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
uint32 sequenceIndex, time;
recvData >> sequenceIndex >> time;
- Player* plMover = _player->GetUnitBeingMoved()->ToPlayer();
+ GameClient* client = GetGameClient();
+ Unit* mover = client->GetActivelyMovedUnit();
+ Player* plMover = mover->ToPlayer();
if (!plMover || !plMover->IsBeingTeleportedNear())
return;
- if (guid != plMover->GetGUID())
- return;
-
plMover->SetSemaphoreTeleportNear(false);
uint32 old_zone = plMover->GetZoneId();
@@ -259,10 +266,17 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
{
uint16 opcode = recvData.GetOpcode();
- Unit* mover = _player->GetUnitBeingMoved();
+ ObjectGuid guid;
+ recvData >> guid.ReadAsPacked();
- ASSERT(mover != nullptr); // there must always be a mover
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+ GameClient* client = GetGameClient();
+ Unit* mover = client->GetActivelyMovedUnit();
Player* plrMover = mover->ToPlayer();
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
@@ -273,9 +287,6 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
}
/* extract packet */
- ObjectGuid guid;
-
- recvData >> guid.ReadAsPacked();
MovementInfo movementInfo;
movementInfo.guid = guid;
@@ -283,10 +294,6 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
recvData.rfinish(); // prevent warnings spam
- // prevent tampered movement data
- if (guid != mover->GetGUID())
- return;
-
if (!movementInfo.pos.IsPositionValid())
{
recvData.rfinish(); // prevent warnings spam
@@ -416,7 +423,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
{
- if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
+ if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(plrMover)))
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
@@ -448,13 +455,15 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
recvData >> guid.ReadAsPacked();
- // now can skip not our packet
- if (_player->GetGUID() != guid)
+ if (!IsRightUnitBeingMoved(guid))
{
- recvData.rfinish(); // prevent warnings spam
+ recvData.rfinish(); // prevent warnings spam
return;
}
+ GameClient* client = GetGameClient();
+ Unit* mover = client->GetActivelyMovedUnit();
+
// continue parse packet
recvData >> unk1; // counter or moveEvent
@@ -491,25 +500,25 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
// 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)
+ if (mover->m_forced_speed_changes[force_move_type] > 0)
{
- --_player->m_forced_speed_changes[force_move_type];
- if (_player->m_forced_speed_changes[force_move_type] > 0)
+ --mover->m_forced_speed_changes[force_move_type];
+ if (mover->m_forced_speed_changes[force_move_type] > 0)
return;
}
- if (!_player->GetTransport() && std::fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f)
+ if (!mover->GetTransport() && std::fabs(mover->GetSpeed(move_type) - newspeed) > 0.01f)
{
- if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct
+ if (mover->GetSpeed(move_type) > newspeed) // must be greater - just correct
{
TC_LOG_ERROR("network", "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value",
- move_type_name[move_type], _player->GetName().c_str(), _player->GetSpeed(move_type), newspeed);
- _player->SetSpeedRate(move_type, _player->GetSpeedRate(move_type));
+ move_type_name[move_type], _player->GetName().c_str(), mover->GetSpeed(move_type), newspeed);
+ mover->SetSpeedRate(move_type, mover->GetSpeedRate(move_type));
}
else // must be lesser - cheating
{
TC_LOG_DEBUG("misc", "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)",
- _player->GetName().c_str(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), newspeed);
+ _player->GetName().c_str(), _player->GetSession()->GetAccountId(), mover->GetSpeed(move_type), newspeed);
_player->GetSession()->KickPlayer("WorldSession::HandleForceSpeedChangeAck Incorrect speed");
}
}
@@ -522,9 +531,21 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recvData)
ObjectGuid guid;
recvData >> guid;
- if (GetPlayer()->IsInWorld())
- if (_player->GetUnitBeingMoved()->GetGUID() != guid)
- TC_LOG_DEBUG("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is %s and should be %s" , guid.ToString().c_str(), _player->GetUnitBeingMoved()->GetGUID().ToString().c_str());
+ GameClient* client = GetGameClient();
+
+ // step 1: look at the list of units that this client is allowed to move. check if the client is allowed to even move the
+ // unit that is mentioned in the packet. if not, either silently ignore, log this event or kick the client.
+ if (!client->IsAllowedToMove(guid))
+ {
+ // @todo log or kick or do nothing depending on configuration
+ TC_LOG_DEBUG("entities.unit", "set active mover FAILED for client of player %s. GUID %s.", _player->GetName().c_str(), guid.ToString().c_str());
+ return;
+ }
+
+ // step 2:
+ TC_LOG_DEBUG("entities.unit", "set active mover OK for client of player %s. GUID %s.", _player->GetName().c_str(), guid.ToString().c_str());
+ Unit* newActivelyMovedUnit = ObjectAccessor::GetUnit(*_player, guid);
+ client->SetActivelyMovedUnit(newActivelyMovedUnit);
}
void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData)
@@ -533,13 +554,20 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData)
ObjectGuid old_mover_guid;
recvData >> old_mover_guid.ReadAsPacked();
+ recvData.rfinish(); // prevent warnings spam.
+ // the movement info in this kind of packet is ignored for now. It's unclear if it should be used.
- MovementInfo mi;
- ReadMovementInfo(recvData, &mi);
+ GameClient* client = GetGameClient();
- mi.guid = old_mover_guid;
+ if (client->GetActivelyMovedUnit() == nullptr || client->GetActivelyMovedUnit()->GetGUID() != old_mover_guid)
+ {
+ // this shouldn't never happen in theory
+ TC_LOG_WARN("entities.unit", "unset active mover FAILED for client of player %s. GUID %s.", _player->GetName().c_str(), old_mover_guid.ToString().c_str());
+ return;
+ }
- _player->m_movementInfo = mi;
+ TC_LOG_DEBUG("entities.unit", "unset active mover OK for client of player %s. GUID %s.", _player->GetName().c_str(), old_mover_guid.ToString().c_str());
+ client->SetActivelyMovedUnit(nullptr);
}
void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvData*/)
@@ -557,19 +585,25 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
ObjectGuid guid;
recvData >> guid.ReadAsPacked();
- if (_player->GetUnitBeingMoved()->GetGUID() != guid)
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
return;
+ }
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
ReadMovementInfo(recvData, &movementInfo);
- _player->m_movementInfo = movementInfo;
+ GameClient* client = GetGameClient();
+ Unit* mover = client->GetActivelyMovedUnit();
+
+ mover->m_movementInfo = movementInfo;
WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
data << guid.WriteAsPacked();
- _player->BuildMovementPacket(&data);
+ mover->BuildMovementPacket(&data);
// knockback specific info
data << movementInfo.jump.sinAngle;
@@ -577,7 +611,7 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
data << movementInfo.jump.xyspeed;
data << movementInfo.jump.zspeed;
- _player->SendMessageToSet(&data, false);
+ client->GetBasePlayer()->SendMessageToSet(&data, false);
}
void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
@@ -587,6 +621,12 @@ void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
ObjectGuid guid; // guid - unused
recvData >> guid.ReadAsPacked();
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -602,6 +642,113 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
ObjectGuid guid; // guid - unused
recvData >> guid.ReadAsPacked();
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+
+ recvData.read_skip<uint32>(); // unk2
+}
+
+void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "CMSG_FORCE_MOVE_ROOT_ACK");
+
+ ObjectGuid guid; // guid - unused
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+}
+
+void WorldSession::HandleFeatherFallAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_FEATHER_FALL_ACK");
+
+ ObjectGuid guid; // guid - unused
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+
+ recvData.read_skip<uint32>(); // unk2
+}
+
+void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK");
+
+ ObjectGuid guid; // guid - unused
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+}
+
+void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
+
+ ObjectGuid guid; // guid - unused
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+
+ recvData.read_skip<uint32>(); // unk2
+}
+
+void WorldSession::HandleMoveSetCanTransitionBetweenSwinAndFlyAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK");
+
+ ObjectGuid guid;
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
recvData.read_skip<uint32>(); // unk
MovementInfo movementInfo;
@@ -610,6 +757,65 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
recvData.read_skip<uint32>(); // unk2
}
+void WorldSession::HandleMoveGravityDisableAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_DISABLE_ACK");
+
+ ObjectGuid guid;
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+}
+
+void WorldSession::HandleMoveGravityEnableAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_ENABLE_ACK");
+
+ ObjectGuid guid;
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // unk
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+}
+
+void WorldSession::HandleMoveSetCollisionHgtAck(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_COLLISION_HGT_ACK");
+
+ ObjectGuid guid;
+ float newValue;
+ recvData >> guid.ReadAsPacked();
+
+ if (!IsRightUnitBeingMoved(guid))
+ {
+ recvData.rfinish(); // prevent warnings spam
+ return;
+ }
+
+ recvData.read_skip<uint32>(); // movement counter
+ recvData >> newValue;
+
+ MovementInfo movementInfo;
+ ReadMovementInfo(recvData, &movementInfo);
+}
+
void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData)
{
if (!_player->IsAlive() || _player->IsInCombat())
@@ -632,21 +838,14 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
recvData >> guid.ReadAsPacked();
recvData >> timeSkipped;
- Unit* mover = GetPlayer()->m_unitMovedByMe;
-
- if (!mover)
- {
- TC_LOG_WARN("entities.player", "WorldSession::HandleMoveTimeSkippedOpcode wrong mover state from the unit moved by the player %s", GetPlayer()->GetGUID().ToString().c_str());
- return;
- }
-
- // prevent tampered movement data
- if (guid != mover->GetGUID())
+ if (!IsRightUnitBeingMoved(guid))
{
- TC_LOG_WARN("entities.player", "WorldSession::HandleMoveTimeSkippedOpcode wrong guid from the unit moved by the player %s", GetPlayer()->GetGUID().ToString().c_str());
+ recvData.rfinish(); // prevent warnings spam
return;
}
+ GameClient* client = GetGameClient();
+ Unit* mover = client->GetActivelyMovedUnit();
mover->m_movementInfo.time += timeSkipped;
WorldPacket data(MSG_MOVE_TIME_SKIPPED, recvData.size());