mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Entities/Movement: Correctly send MSG_MOVE_TELEPORT to the player when it is teleported, send MSG_MOVE_UPDATE_TELEPORT to nearby players when such thing happens.
Allow the usage of WriteMovementInfo on non-player units.
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#include "Vehicle.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "MovementStructures.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -16686,71 +16687,563 @@ void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool cas
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::ReadMovementInfo(WorldPacket& data, MovementInfo* mi)
|
||||
{
|
||||
if (GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
bool hasMovementFlags = false;
|
||||
bool hasMovementFlags2 = false;
|
||||
bool hasTimestamp = false;
|
||||
bool hasOrientation = false;
|
||||
bool hasTransportData = false;
|
||||
bool hasTransportTime2 = false;
|
||||
bool hasTransportTime3 = false;
|
||||
bool hasPitch = false;
|
||||
bool hasFallData = false;
|
||||
bool hasFallDirection = false;
|
||||
bool hasSplineElevation = false;
|
||||
bool hasSpline = false;
|
||||
|
||||
MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
|
||||
if (sequence == NULL)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::ReadMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectGuid guid;
|
||||
ObjectGuid tguid;
|
||||
|
||||
for (uint32 i = 0; i < MSE_COUNT; ++i)
|
||||
{
|
||||
MovementStatusElements element = sequence[i];
|
||||
if (element == MSEEnd)
|
||||
break;
|
||||
|
||||
if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7)
|
||||
{
|
||||
guid[element - MSEHasGuidByte0] = data.ReadBit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEHasTransportGuidByte0 &&
|
||||
element <= MSEHasTransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
tguid[element - MSEHasTransportGuidByte0] = data.ReadBit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEGuidByte0 && element <= MSEGuidByte7)
|
||||
{
|
||||
data.ReadByteSeq(guid[element - MSEGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSETransportGuidByte0 &&
|
||||
element <= MSETransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.ReadByteSeq(tguid[element - MSETransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case MSEHasMovementFlags:
|
||||
hasMovementFlags = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasMovementFlags2:
|
||||
hasMovementFlags2 = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasTimestamp:
|
||||
hasTimestamp = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasOrientation:
|
||||
hasOrientation = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportData:
|
||||
hasTransportData = data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportTime2:
|
||||
if (hasTransportData)
|
||||
hasTransportTime2 = data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportTime3:
|
||||
if (hasTransportData)
|
||||
hasTransportTime3 = data.ReadBit();
|
||||
break;
|
||||
case MSEHasPitch:
|
||||
hasPitch = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasFallData:
|
||||
hasFallData = data.ReadBit();
|
||||
break;
|
||||
case MSEHasFallDirection:
|
||||
if (hasFallData)
|
||||
hasFallDirection = data.ReadBit();
|
||||
break;
|
||||
case MSEHasSplineElevation:
|
||||
hasSplineElevation = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasSpline:
|
||||
hasSpline = data.ReadBit();
|
||||
break;
|
||||
case MSEMovementFlags:
|
||||
if (hasMovementFlags)
|
||||
mi->flags = data.ReadBits(30);
|
||||
break;
|
||||
case MSEMovementFlags2:
|
||||
if (hasMovementFlags2)
|
||||
mi->flags2 = data.ReadBits(12);
|
||||
break;
|
||||
case MSETimestamp:
|
||||
if (hasTimestamp)
|
||||
data >> mi->time;
|
||||
break;
|
||||
case MSEPositionX:
|
||||
data >> mi->pos.m_positionX;
|
||||
break;
|
||||
case MSEPositionY:
|
||||
data >> mi->pos.m_positionY;
|
||||
break;
|
||||
case MSEPositionZ:
|
||||
data >> mi->pos.m_positionZ;
|
||||
break;
|
||||
case MSEOrientation:
|
||||
if (hasOrientation)
|
||||
mi->pos.SetOrientation(data.read<float>());
|
||||
break;
|
||||
case MSETransportPositionX:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionX;
|
||||
break;
|
||||
case MSETransportPositionY:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionY;
|
||||
break;
|
||||
case MSETransportPositionZ:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionZ;
|
||||
break;
|
||||
case MSETransportOrientation:
|
||||
if (hasTransportData)
|
||||
mi->pos.SetOrientation(data.read<float>());
|
||||
break;
|
||||
case MSETransportSeat:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_seat;
|
||||
break;
|
||||
case MSETransportTime:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_time;
|
||||
break;
|
||||
case MSETransportTime2:
|
||||
if (hasTransportData && hasTransportTime2)
|
||||
data >> mi->t_time2;
|
||||
break;
|
||||
case MSETransportTime3:
|
||||
if (hasTransportData && hasTransportTime3)
|
||||
data >> mi->t_time3;
|
||||
break;
|
||||
case MSEPitch:
|
||||
if (hasPitch)
|
||||
data >> mi->pitch;
|
||||
break;
|
||||
case MSEFallTime:
|
||||
if (hasFallData)
|
||||
data >> mi->fallTime;
|
||||
break;
|
||||
case MSEFallVerticalSpeed:
|
||||
if (hasFallData)
|
||||
data >> mi->j_zspeed;
|
||||
break;
|
||||
case MSEFallCosAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_cosAngle;
|
||||
break;
|
||||
case MSEFallSinAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_sinAngle;
|
||||
break;
|
||||
case MSEFallHorizontalSpeed:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_xyspeed;
|
||||
break;
|
||||
case MSESplineElevation:
|
||||
if (hasSplineElevation)
|
||||
data >> mi->splineElevation;
|
||||
break;
|
||||
case MSEZeroBit:
|
||||
case MSEOneBit:
|
||||
data.ReadBit();
|
||||
break;
|
||||
default:
|
||||
ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mi->guid = guid;
|
||||
mi->t_guid = tguid;
|
||||
|
||||
if (hasTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX)
|
||||
if (GetTransport())
|
||||
GetTransport()->UpdatePosition(mi);
|
||||
|
||||
//! Anti-cheat checks. Please keep them in seperate if() blocks to maintain a clear overview.
|
||||
//! Might be subject to latency, so just remove improper flags.
|
||||
#ifdef TRINITY_DEBUG
|
||||
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
|
||||
{ \
|
||||
if (check) \
|
||||
{ \
|
||||
sLog->outDebug(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
|
||||
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
|
||||
STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetGUIDLow(), maskToRemove); \
|
||||
mi->RemoveMovementFlag((maskToRemove)); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
|
||||
if (check) \
|
||||
mi->RemoveMovementFlag((maskToRemove));
|
||||
#endif
|
||||
|
||||
|
||||
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
|
||||
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
|
||||
It will freeze clients that receive this player's movement info.
|
||||
*/
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
|
||||
MOVEMENTFLAG_ROOT);
|
||||
|
||||
//! Cannot hover without SPELL_AURA_HOVER
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !HasAuraType(SPELL_AURA_HOVER),
|
||||
MOVEMENTFLAG_HOVER);
|
||||
|
||||
//! Cannot ascend and descend at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
|
||||
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
|
||||
|
||||
//! Cannot move left and right at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
|
||||
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
|
||||
|
||||
//! Cannot strafe left and right at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
|
||||
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
|
||||
|
||||
//! Cannot pitch up and down at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
|
||||
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
|
||||
|
||||
//! Cannot move forwards and backwards at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
|
||||
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
|
||||
|
||||
//! Cannot walk on water without SPELL_AURA_WATER_WALK
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !HasAuraType(SPELL_AURA_WATER_WALK),
|
||||
MOVEMENTFLAG_WATERWALKING);
|
||||
|
||||
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !HasAuraType(SPELL_AURA_FEATHER_FALL),
|
||||
MOVEMENTFLAG_FALLING_SLOW);
|
||||
|
||||
/*! Cannot fly if no fly auras present. Exception is being a GM.
|
||||
Note that we check for account level instead of Player::IsGameMaster() because in some
|
||||
situations it may be feasable to use .gm fly on as a GM without having .gm on,
|
||||
e.g. aerial combat.
|
||||
*/
|
||||
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && ToPlayer()->GetSession()->GetSecurity() == SEC_PLAYER &&
|
||||
!ToPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
|
||||
!ToPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
|
||||
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
|
||||
|
||||
#undef REMOVE_VIOLATING_FLAGS
|
||||
}
|
||||
|
||||
void Unit::WriteMovementInfo(WorldPacket& data)
|
||||
{
|
||||
Unit* mover = GetCharmerGUID() ? GetCharmer() : this;
|
||||
|
||||
bool hasMovementFlags = mover->GetUnitMovementFlags() != 0;
|
||||
bool hasMovementFlags2 = mover->GetExtraUnitMovementFlags() != 0;
|
||||
bool hasTimestamp = GetTypeId() == TYPEID_PLAYER ? (mover->m_movementInfo.time != 0) : true;
|
||||
bool hasOrientation = !G3D::fuzzyEq(mover->GetOrientation(), 0.0f);
|
||||
bool hasTransportData = mover->GetTransport() != NULL;
|
||||
bool hasTransportTime2 = mover->HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT);
|
||||
bool hasTransportTime3 = false;
|
||||
bool hasPitch = mover->HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || mover->HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
|
||||
bool hasFallData = mover->HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_TURNING);
|
||||
bool hasFallDirection = mover->HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
bool hasSplineElevation = mover->HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
|
||||
bool hasSpline = false;
|
||||
|
||||
MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
|
||||
if (!sequence)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::WriteMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectGuid guid = mover->GetGUID();
|
||||
ObjectGuid tguid = hasTransportData ? GetTransport()->GetGUID() : 0;
|
||||
|
||||
for(uint32 i = 0; i < MSE_COUNT; ++i)
|
||||
{
|
||||
MovementStatusElements element = sequence[i];
|
||||
if (element == MSEEnd)
|
||||
break;
|
||||
|
||||
if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7)
|
||||
{
|
||||
data.WriteBit(guid[element - MSEHasGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEHasTransportGuidByte0 &&
|
||||
element <= MSEHasTransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.WriteBit(tguid[element - MSEHasTransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEGuidByte0 && element <= MSEGuidByte7)
|
||||
{
|
||||
data.WriteByteSeq(guid[element - MSEGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSETransportGuidByte0 &&
|
||||
element <= MSETransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.WriteByteSeq(tguid[element - MSETransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case MSEHasMovementFlags:
|
||||
data.WriteBit(!hasMovementFlags);
|
||||
break;
|
||||
case MSEHasMovementFlags2:
|
||||
data.WriteBit(!hasMovementFlags2);
|
||||
break;
|
||||
case MSEHasTimestamp:
|
||||
data.WriteBit(!hasTimestamp);
|
||||
break;
|
||||
case MSEHasOrientation:
|
||||
data.WriteBit(!hasOrientation);
|
||||
break;
|
||||
case MSEHasTransportData:
|
||||
data.WriteBit(hasTransportData);
|
||||
break;
|
||||
case MSEHasTransportTime2:
|
||||
if (hasTransportData)
|
||||
data.WriteBit(hasTransportTime2);
|
||||
break;
|
||||
case MSEHasTransportTime3:
|
||||
if (hasTransportData)
|
||||
data.WriteBit(hasTransportTime3);
|
||||
break;
|
||||
case MSEHasPitch:
|
||||
data.WriteBit(!hasPitch);
|
||||
break;
|
||||
case MSEHasFallData:
|
||||
data.WriteBit(hasFallData);
|
||||
break;
|
||||
case MSEHasFallDirection:
|
||||
if (hasFallData)
|
||||
data.WriteBit(hasFallDirection);
|
||||
break;
|
||||
case MSEHasSplineElevation:
|
||||
data.WriteBit(!hasSplineElevation);
|
||||
break;
|
||||
case MSEHasSpline:
|
||||
data.WriteBit(hasSpline);
|
||||
break;
|
||||
case MSEMovementFlags:
|
||||
if (hasMovementFlags)
|
||||
data.WriteBits(mover->GetUnitMovementFlags(), 30);
|
||||
break;
|
||||
case MSEMovementFlags2:
|
||||
if (hasMovementFlags2)
|
||||
data.WriteBits(mover->GetExtraUnitMovementFlags(), 12);
|
||||
break;
|
||||
case MSETimestamp:
|
||||
if (hasTimestamp)
|
||||
data << getMSTime();
|
||||
break;
|
||||
case MSEPositionX:
|
||||
data << mover->GetPositionX();
|
||||
break;
|
||||
case MSEPositionY:
|
||||
data << mover->GetPositionY();
|
||||
break;
|
||||
case MSEPositionZ:
|
||||
data << mover->GetPositionZ();
|
||||
break;
|
||||
case MSEOrientation:
|
||||
if (hasOrientation)
|
||||
data << mover->GetOrientation();
|
||||
break;
|
||||
case MSETransportPositionX:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransport()->GetPositionX();
|
||||
break;
|
||||
case MSETransportPositionY:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransport()->GetPositionY();
|
||||
break;
|
||||
case MSETransportPositionZ:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransport()->GetPositionZ();
|
||||
break;
|
||||
case MSETransportOrientation:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransport()->GetOrientation();
|
||||
break;
|
||||
case MSETransportSeat:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransSeat();
|
||||
break;
|
||||
case MSETransportTime:
|
||||
if (hasTransportData)
|
||||
data << mover->GetTransTime();
|
||||
break;
|
||||
case MSETransportTime2:
|
||||
if (hasTransportData && hasTransportTime2)
|
||||
data << mover->m_movementInfo.t_time2;
|
||||
break;
|
||||
case MSETransportTime3:
|
||||
if (hasTransportData && hasTransportTime3)
|
||||
data << mover->m_movementInfo.t_time3;
|
||||
break;
|
||||
case MSEPitch:
|
||||
if (hasPitch)
|
||||
data << mover->m_movementInfo.pitch;
|
||||
break;
|
||||
case MSEFallTime:
|
||||
if (hasFallData)
|
||||
data << mover->m_movementInfo.fallTime;
|
||||
break;
|
||||
case MSEFallVerticalSpeed:
|
||||
if (hasFallData)
|
||||
data << mover->m_movementInfo.j_zspeed;
|
||||
break;
|
||||
case MSEFallCosAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mover->m_movementInfo.j_cosAngle;
|
||||
break;
|
||||
case MSEFallSinAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mover->m_movementInfo.j_sinAngle;
|
||||
break;
|
||||
case MSEFallHorizontalSpeed:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mover->m_movementInfo.j_xyspeed;
|
||||
break;
|
||||
case MSESplineElevation:
|
||||
if (hasSplineElevation)
|
||||
data << mover->m_movementInfo.splineElevation;
|
||||
break;
|
||||
case MSEZeroBit:
|
||||
data.WriteBit(0);
|
||||
break;
|
||||
case MSEOneBit:
|
||||
data.WriteBit(1);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendTeleportPacket(Position& pos)
|
||||
{
|
||||
// MSG_MOVE_UPDATE_TELEPORT is sent to nearby players to signal the teleport
|
||||
// MSG_MOVE_TELEPORT is sent to self in order to trigger MSG_MOVE_TELEPORT_ACK and update the position server side
|
||||
|
||||
// This oldPos actually contains the destination position if the Unit is a Player.
|
||||
Position oldPos = {GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), GetOrientation()};
|
||||
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
Relocate(&pos);
|
||||
Relocate(&pos); // Relocate the unit to its new position in order to build the packets correctly.
|
||||
|
||||
ObjectGuid guid = GetGUID();
|
||||
ObjectGuid transGuid = GetTransGUID();
|
||||
|
||||
WorldPacket data(MSG_MOVE_TELEPORT, 38);
|
||||
data.WriteBit(guid[6]);
|
||||
data.WriteBit(guid[0]);
|
||||
data.WriteBit(guid[3]);
|
||||
data.WriteBit(guid[2]);
|
||||
data.WriteBit(0); // unknown
|
||||
data.WriteBit(uint64(transGuid));
|
||||
data.WriteBit(guid[1]);
|
||||
if (transGuid)
|
||||
{
|
||||
data.WriteBit(transGuid[1]);
|
||||
data.WriteBit(transGuid[3]);
|
||||
data.WriteBit(transGuid[2]);
|
||||
data.WriteBit(transGuid[5]);
|
||||
data.WriteBit(transGuid[0]);
|
||||
data.WriteBit(transGuid[7]);
|
||||
data.WriteBit(transGuid[6]);
|
||||
data.WriteBit(transGuid[4]);
|
||||
}
|
||||
data.WriteBit(guid[4]);
|
||||
data.WriteBit(guid[7]);
|
||||
data.WriteBit(guid[5]);
|
||||
data.FlushBits();
|
||||
|
||||
if (transGuid)
|
||||
{
|
||||
data.WriteByteSeq(transGuid[6]);
|
||||
data.WriteByteSeq(transGuid[5]);
|
||||
data.WriteByteSeq(transGuid[1]);
|
||||
data.WriteByteSeq(transGuid[7]);
|
||||
data.WriteByteSeq(transGuid[0]);
|
||||
data.WriteByteSeq(transGuid[2]);
|
||||
data.WriteByteSeq(transGuid[4]);
|
||||
data.WriteByteSeq(transGuid[3]);
|
||||
}
|
||||
|
||||
data << uint32(0); // counter
|
||||
data.WriteByteSeq(guid[1]);
|
||||
data.WriteByteSeq(guid[2]);
|
||||
data.WriteByteSeq(guid[3]);
|
||||
data.WriteByteSeq(guid[5]);
|
||||
data << float(GetPositionX());
|
||||
data.WriteByteSeq(guid[4]);
|
||||
data << float(GetOrientation());
|
||||
data.WriteByteSeq(guid[7]);
|
||||
data << float(GetPositionZMinusOffset());
|
||||
data.WriteByteSeq(guid[0]);
|
||||
data.WriteByteSeq(guid[6]);
|
||||
data << float(GetPositionY());
|
||||
WorldPacket data(MSG_MOVE_UPDATE_TELEPORT, 38);
|
||||
WriteMovementInfo(data);
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
Relocate(&pos);
|
||||
{
|
||||
WorldPacket data2(MSG_MOVE_TELEPORT, 38);
|
||||
data2.WriteBit(guid[6]);
|
||||
data2.WriteBit(guid[0]);
|
||||
data2.WriteBit(guid[3]);
|
||||
data2.WriteBit(guid[2]);
|
||||
data2.WriteBit(0); // unknown
|
||||
data2.WriteBit(uint64(transGuid));
|
||||
data2.WriteBit(guid[1]);
|
||||
if (transGuid)
|
||||
{
|
||||
data2.WriteBit(transGuid[1]);
|
||||
data2.WriteBit(transGuid[3]);
|
||||
data2.WriteBit(transGuid[2]);
|
||||
data2.WriteBit(transGuid[5]);
|
||||
data2.WriteBit(transGuid[0]);
|
||||
data2.WriteBit(transGuid[7]);
|
||||
data2.WriteBit(transGuid[6]);
|
||||
data2.WriteBit(transGuid[4]);
|
||||
}
|
||||
data2.WriteBit(guid[4]);
|
||||
data2.WriteBit(guid[7]);
|
||||
data2.WriteBit(guid[5]);
|
||||
data2.FlushBits();
|
||||
|
||||
if (transGuid)
|
||||
{
|
||||
data2.WriteByteSeq(transGuid[6]);
|
||||
data2.WriteByteSeq(transGuid[5]);
|
||||
data2.WriteByteSeq(transGuid[1]);
|
||||
data2.WriteByteSeq(transGuid[7]);
|
||||
data2.WriteByteSeq(transGuid[0]);
|
||||
data2.WriteByteSeq(transGuid[2]);
|
||||
data2.WriteByteSeq(transGuid[4]);
|
||||
data2.WriteByteSeq(transGuid[3]);
|
||||
}
|
||||
|
||||
data2 << uint32(0); // counter
|
||||
data2.WriteByteSeq(guid[1]);
|
||||
data2.WriteByteSeq(guid[2]);
|
||||
data2.WriteByteSeq(guid[3]);
|
||||
data2.WriteByteSeq(guid[5]);
|
||||
data2 << float(GetPositionX());
|
||||
data2.WriteByteSeq(guid[4]);
|
||||
data2 << float(GetOrientation());
|
||||
data2.WriteByteSeq(guid[7]);
|
||||
data2 << float(GetPositionZMinusOffset());
|
||||
data2.WriteByteSeq(guid[0]);
|
||||
data2.WriteByteSeq(guid[6]);
|
||||
data2 << float(GetPositionY());
|
||||
ToPlayer()->SendDirectMessage(&data2); // Send the MSG_MOVE_TELEPORT packet to self.
|
||||
}
|
||||
|
||||
// Relocate the player/creature to its old position, so we can broadcast to nearby players correctly
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
Relocate(&pos);
|
||||
else
|
||||
Relocate(&oldPos);
|
||||
SendMessageToSet(&data, true);
|
||||
|
||||
// Broadcast the packet to everyone except self.
|
||||
SendMessageToSet(&data, false);
|
||||
}
|
||||
|
||||
bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool teleport)
|
||||
|
||||
@@ -2169,6 +2169,8 @@ class Unit : public WorldObject
|
||||
void _EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp = NULL);
|
||||
|
||||
void BuildMovementPacket(ByteBuffer *data) const;
|
||||
void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
|
||||
void WriteMovementInfo(WorldPacket& data);
|
||||
|
||||
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING); }
|
||||
bool isTurning() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_TURNING); }
|
||||
|
||||
@@ -1666,7 +1666,7 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData)
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
_player->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData.read_skip<float>(); // unk2
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "MovementStructures.h"
|
||||
|
||||
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket& /*recvPacket*/)
|
||||
{
|
||||
@@ -276,7 +275,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
|
||||
|
||||
/* extract packet */
|
||||
MovementInfo movementInfo;
|
||||
ReadMovementInfo(recvPacket, &movementInfo);
|
||||
GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo);
|
||||
|
||||
// prevent tampered movement data
|
||||
if (movementInfo.guid != mover->GetGUID())
|
||||
@@ -375,17 +374,16 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
|
||||
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
|
||||
}
|
||||
|
||||
/*----------------------*/
|
||||
|
||||
/* process position-change */
|
||||
WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
|
||||
movementInfo.time = getMSTime();
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
WriteMovementInfo(data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
|
||||
mover->m_movementInfo = movementInfo;
|
||||
|
||||
/*----------------------*/
|
||||
/* process position-change */
|
||||
WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
|
||||
_player->WriteMovementInfo(data);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
|
||||
// this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
|
||||
if (mover->GetVehicle())
|
||||
{
|
||||
@@ -446,7 +444,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData >> newspeed;
|
||||
/*----------------*/
|
||||
@@ -536,7 +534,7 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recvData)
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
|
||||
|
||||
MovementInfo mi;
|
||||
ReadMovementInfo(recvData, &mi);
|
||||
GetPlayer()->ReadMovementInfo(recvData, &mi);
|
||||
_player->m_movementInfo = mi;
|
||||
}
|
||||
|
||||
@@ -553,7 +551,7 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
|
||||
sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_KNOCK_BACK_ACK");
|
||||
|
||||
MovementInfo movementInfo;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
if (_player->m_mover->GetGUID() != movementInfo.guid)
|
||||
return;
|
||||
@@ -583,7 +581,7 @@ void WorldSession::HandleMoveHoverAck(WorldPacket& recvData)
|
||||
recvData.read_skip<uint32>(); // unk
|
||||
|
||||
MovementInfo movementInfo;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData.read_skip<uint32>(); // unk2
|
||||
}
|
||||
@@ -598,7 +596,7 @@ void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData)
|
||||
recvData.read_skip<uint32>(); // unk
|
||||
|
||||
MovementInfo movementInfo;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData.read_skip<uint32>(); // unk2
|
||||
}
|
||||
@@ -614,477 +612,4 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData)
|
||||
recvData >> agree;
|
||||
|
||||
_player->SummonIfPossible(agree);
|
||||
}
|
||||
|
||||
void WorldSession::ReadMovementInfo(WorldPacket& data, MovementInfo* mi)
|
||||
{
|
||||
bool hasMovementFlags = false;
|
||||
bool hasMovementFlags2 = false;
|
||||
bool hasTimestamp = false;
|
||||
bool hasOrientation = false;
|
||||
bool hasTransportData = false;
|
||||
bool hasTransportTime2 = false;
|
||||
bool hasTransportTime3 = false;
|
||||
bool hasPitch = false;
|
||||
bool hasFallData = false;
|
||||
bool hasFallDirection = false;
|
||||
bool hasSplineElevation = false;
|
||||
bool hasSpline = false;
|
||||
|
||||
MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
|
||||
if (sequence == NULL)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::ReadMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectGuid guid;
|
||||
ObjectGuid tguid;
|
||||
|
||||
for (uint32 i = 0; i < MSE_COUNT; ++i)
|
||||
{
|
||||
MovementStatusElements element = sequence[i];
|
||||
if (element == MSEEnd)
|
||||
break;
|
||||
|
||||
if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7)
|
||||
{
|
||||
guid[element - MSEHasGuidByte0] = data.ReadBit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEHasTransportGuidByte0 &&
|
||||
element <= MSEHasTransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
tguid[element - MSEHasTransportGuidByte0] = data.ReadBit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEGuidByte0 && element <= MSEGuidByte7)
|
||||
{
|
||||
data.ReadByteSeq(guid[element - MSEGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSETransportGuidByte0 &&
|
||||
element <= MSETransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.ReadByteSeq(tguid[element - MSETransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case MSEHasMovementFlags:
|
||||
hasMovementFlags = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasMovementFlags2:
|
||||
hasMovementFlags2 = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasTimestamp:
|
||||
hasTimestamp = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasOrientation:
|
||||
hasOrientation = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportData:
|
||||
hasTransportData = data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportTime2:
|
||||
if (hasTransportData)
|
||||
hasTransportTime2 = data.ReadBit();
|
||||
break;
|
||||
case MSEHasTransportTime3:
|
||||
if (hasTransportData)
|
||||
hasTransportTime3 = data.ReadBit();
|
||||
break;
|
||||
case MSEHasPitch:
|
||||
hasPitch = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasFallData:
|
||||
hasFallData = data.ReadBit();
|
||||
break;
|
||||
case MSEHasFallDirection:
|
||||
if (hasFallData)
|
||||
hasFallDirection = data.ReadBit();
|
||||
break;
|
||||
case MSEHasSplineElevation:
|
||||
hasSplineElevation = !data.ReadBit();
|
||||
break;
|
||||
case MSEHasSpline:
|
||||
hasSpline = data.ReadBit();
|
||||
break;
|
||||
case MSEMovementFlags:
|
||||
if (hasMovementFlags)
|
||||
mi->flags = data.ReadBits(30);
|
||||
break;
|
||||
case MSEMovementFlags2:
|
||||
if (hasMovementFlags2)
|
||||
mi->flags2 = data.ReadBits(12);
|
||||
break;
|
||||
case MSETimestamp:
|
||||
if (hasTimestamp)
|
||||
data >> mi->time;
|
||||
break;
|
||||
case MSEPositionX:
|
||||
data >> mi->pos.m_positionX;
|
||||
break;
|
||||
case MSEPositionY:
|
||||
data >> mi->pos.m_positionY;
|
||||
break;
|
||||
case MSEPositionZ:
|
||||
data >> mi->pos.m_positionZ;
|
||||
break;
|
||||
case MSEOrientation:
|
||||
if (hasOrientation)
|
||||
mi->pos.SetOrientation(data.read<float>());
|
||||
break;
|
||||
case MSETransportPositionX:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionX;
|
||||
break;
|
||||
case MSETransportPositionY:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionY;
|
||||
break;
|
||||
case MSETransportPositionZ:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_pos.m_positionZ;
|
||||
break;
|
||||
case MSETransportOrientation:
|
||||
if (hasTransportData)
|
||||
mi->pos.SetOrientation(data.read<float>());
|
||||
break;
|
||||
case MSETransportSeat:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_seat;
|
||||
break;
|
||||
case MSETransportTime:
|
||||
if (hasTransportData)
|
||||
data >> mi->t_time;
|
||||
break;
|
||||
case MSETransportTime2:
|
||||
if (hasTransportData && hasTransportTime2)
|
||||
data >> mi->t_time2;
|
||||
break;
|
||||
case MSETransportTime3:
|
||||
if (hasTransportData && hasTransportTime3)
|
||||
data >> mi->t_time3;
|
||||
break;
|
||||
case MSEPitch:
|
||||
if (hasPitch)
|
||||
data >> mi->pitch;
|
||||
break;
|
||||
case MSEFallTime:
|
||||
if (hasFallData)
|
||||
data >> mi->fallTime;
|
||||
break;
|
||||
case MSEFallVerticalSpeed:
|
||||
if (hasFallData)
|
||||
data >> mi->j_zspeed;
|
||||
break;
|
||||
case MSEFallCosAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_cosAngle;
|
||||
break;
|
||||
case MSEFallSinAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_sinAngle;
|
||||
break;
|
||||
case MSEFallHorizontalSpeed:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data >> mi->j_xyspeed;
|
||||
break;
|
||||
case MSESplineElevation:
|
||||
if (hasSplineElevation)
|
||||
data >> mi->splineElevation;
|
||||
break;
|
||||
case MSEZeroBit:
|
||||
case MSEOneBit:
|
||||
data.ReadBit();
|
||||
break;
|
||||
default:
|
||||
ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mi->guid = guid;
|
||||
mi->t_guid = tguid;
|
||||
|
||||
if (hasTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX)
|
||||
if (GetPlayer()->GetTransport())
|
||||
GetPlayer()->GetTransport()->UpdatePosition(mi);
|
||||
|
||||
//! Anti-cheat checks. Please keep them in seperate if() blocks to maintain a clear overview.
|
||||
//! Might be subject to latency, so just remove improper flags.
|
||||
#ifdef TRINITY_DEBUG
|
||||
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
|
||||
{ \
|
||||
if (check) \
|
||||
{ \
|
||||
sLog->outDebug(LOG_FILTER_UNITS, "WorldSession::ReadMovementInfo: Violation of MovementFlags found (%s). " \
|
||||
"MovementFlags: %u, MovementFlags2: %u for player GUID: %u. Mask %u will be removed.", \
|
||||
STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUIDLow(), maskToRemove); \
|
||||
mi->RemoveMovementFlag((maskToRemove)); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \
|
||||
if (check) \
|
||||
mi->RemoveMovementFlag((maskToRemove));
|
||||
#endif
|
||||
|
||||
|
||||
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid
|
||||
in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD.
|
||||
It will freeze clients that receive this player's movement info.
|
||||
*/
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT),
|
||||
MOVEMENTFLAG_ROOT);
|
||||
|
||||
//! Cannot hover without SPELL_AURA_HOVER
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER),
|
||||
MOVEMENTFLAG_HOVER);
|
||||
|
||||
//! Cannot ascend and descend at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING),
|
||||
MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING);
|
||||
|
||||
//! Cannot move left and right at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT),
|
||||
MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT);
|
||||
|
||||
//! Cannot strafe left and right at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT),
|
||||
MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT);
|
||||
|
||||
//! Cannot pitch up and down at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN),
|
||||
MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN);
|
||||
|
||||
//! Cannot move forwards and backwards at the same time
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD),
|
||||
MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD);
|
||||
|
||||
//! Cannot walk on water without SPELL_AURA_WATER_WALK
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK),
|
||||
MOVEMENTFLAG_WATERWALKING);
|
||||
|
||||
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL),
|
||||
MOVEMENTFLAG_FALLING_SLOW);
|
||||
|
||||
/*! Cannot fly if no fly auras present. Exception is being a GM.
|
||||
Note that we check for account level instead of Player::IsGameMaster() because in some
|
||||
situations it may be feasable to use .gm fly on as a GM without having .gm on,
|
||||
e.g. aerial combat.
|
||||
*/
|
||||
|
||||
REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
|
||||
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
|
||||
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED),
|
||||
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY);
|
||||
|
||||
#undef REMOVE_VIOLATING_FLAGS
|
||||
}
|
||||
|
||||
void WorldSession::WriteMovementInfo(WorldPacket &data, MovementInfo* mi)
|
||||
{
|
||||
bool hasMovementFlags = mi->GetMovementFlags() != 0;
|
||||
bool hasMovementFlags2 = mi->GetExtraMovementFlags() != 0;
|
||||
bool hasTimestamp = mi->time != 0;
|
||||
bool hasOrientation = !G3D::fuzzyEq(mi->pos.GetOrientation(), 0.0f);
|
||||
bool hasTransportData = mi->t_guid != 0;
|
||||
bool hasTransportTime2 = mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT);
|
||||
bool hasTransportTime3 = false;
|
||||
bool hasPitch = mi->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || mi->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
|
||||
bool hasFallData = mi->HasExtraMovementFlag(MOVEMENTFLAG2_INTERPOLATED_TURNING);
|
||||
bool hasFallDirection = mi->HasMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
bool hasSplineElevation = mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION);
|
||||
bool hasSpline = false;
|
||||
|
||||
MovementStatusElements* sequence = GetMovementStatusElementsSequence(data.GetOpcode());
|
||||
if (!sequence)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_NETWORKIO, "WorldSession::WriteMovementInfo: No movement sequence found for opcode 0x%04X", uint32(data.GetOpcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectGuid guid = mi->guid;
|
||||
ObjectGuid tguid = mi->t_guid;
|
||||
|
||||
for(uint32 i = 0; i < MSE_COUNT; ++i)
|
||||
{
|
||||
MovementStatusElements element = sequence[i];
|
||||
if (element == MSEEnd)
|
||||
break;
|
||||
|
||||
if (element >= MSEHasGuidByte0 && element <= MSEHasGuidByte7)
|
||||
{
|
||||
data.WriteBit(guid[element - MSEHasGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEHasTransportGuidByte0 &&
|
||||
element <= MSEHasTransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.WriteBit(tguid[element - MSEHasTransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSEGuidByte0 && element <= MSEGuidByte7)
|
||||
{
|
||||
data.WriteByteSeq(guid[element - MSEGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element >= MSETransportGuidByte0 &&
|
||||
element <= MSETransportGuidByte7)
|
||||
{
|
||||
if (hasTransportData)
|
||||
data.WriteByteSeq(tguid[element - MSETransportGuidByte0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (element)
|
||||
{
|
||||
case MSEHasMovementFlags:
|
||||
data.WriteBit(!hasMovementFlags);
|
||||
break;
|
||||
case MSEHasMovementFlags2:
|
||||
data.WriteBit(!hasMovementFlags2);
|
||||
break;
|
||||
case MSEHasTimestamp:
|
||||
data.WriteBit(!hasTimestamp);
|
||||
break;
|
||||
case MSEHasOrientation:
|
||||
data.WriteBit(!hasOrientation);
|
||||
break;
|
||||
case MSEHasTransportData:
|
||||
data.WriteBit(hasTransportData);
|
||||
break;
|
||||
case MSEHasTransportTime2:
|
||||
if (hasTransportData)
|
||||
data.WriteBit(hasTransportTime2);
|
||||
break;
|
||||
case MSEHasTransportTime3:
|
||||
if (hasTransportData)
|
||||
data.WriteBit(hasTransportTime3);
|
||||
break;
|
||||
case MSEHasPitch:
|
||||
data.WriteBit(!hasPitch);
|
||||
break;
|
||||
case MSEHasFallData:
|
||||
data.WriteBit(hasFallData);
|
||||
break;
|
||||
case MSEHasFallDirection:
|
||||
if (hasFallData)
|
||||
data.WriteBit(hasFallDirection);
|
||||
break;
|
||||
case MSEHasSplineElevation:
|
||||
data.WriteBit(!hasSplineElevation);
|
||||
break;
|
||||
case MSEHasSpline:
|
||||
data.WriteBit(hasSpline);
|
||||
break;
|
||||
case MSEMovementFlags:
|
||||
if (hasMovementFlags)
|
||||
data.WriteBits(mi->flags, 30);
|
||||
break;
|
||||
case MSEMovementFlags2:
|
||||
if (hasMovementFlags2)
|
||||
data.WriteBits(mi->flags2, 12);
|
||||
break;
|
||||
case MSETimestamp:
|
||||
if (hasTimestamp)
|
||||
data << mi->time;
|
||||
break;
|
||||
case MSEPositionX:
|
||||
data << mi->pos.m_positionX;
|
||||
break;
|
||||
case MSEPositionY:
|
||||
data << mi->pos.m_positionY;
|
||||
break;
|
||||
case MSEPositionZ:
|
||||
data << mi->pos.m_positionZ;
|
||||
break;
|
||||
case MSEOrientation:
|
||||
if (hasOrientation)
|
||||
data << mi->pos.GetOrientation();
|
||||
break;
|
||||
case MSETransportPositionX:
|
||||
if (hasTransportData)
|
||||
data << mi->t_pos.m_positionX;
|
||||
break;
|
||||
case MSETransportPositionY:
|
||||
if (hasTransportData)
|
||||
data << mi->t_pos.m_positionY;
|
||||
break;
|
||||
case MSETransportPositionZ:
|
||||
if (hasTransportData)
|
||||
data << mi->t_pos.m_positionZ;
|
||||
break;
|
||||
case MSETransportOrientation:
|
||||
if (hasTransportData)
|
||||
data << mi->t_pos.GetOrientation();
|
||||
break;
|
||||
case MSETransportSeat:
|
||||
if (hasTransportData)
|
||||
data << mi->t_seat;
|
||||
break;
|
||||
case MSETransportTime:
|
||||
if (hasTransportData)
|
||||
data << mi->t_time;
|
||||
break;
|
||||
case MSETransportTime2:
|
||||
if (hasTransportData && hasTransportTime2)
|
||||
data << mi->t_time2;
|
||||
break;
|
||||
case MSETransportTime3:
|
||||
if (hasTransportData && hasTransportTime3)
|
||||
data << mi->t_time3;
|
||||
break;
|
||||
case MSEPitch:
|
||||
if (hasPitch)
|
||||
data << mi->pitch;
|
||||
break;
|
||||
case MSEFallTime:
|
||||
if (hasFallData)
|
||||
data << mi->fallTime;
|
||||
break;
|
||||
case MSEFallVerticalSpeed:
|
||||
if (hasFallData)
|
||||
data << mi->j_zspeed;
|
||||
break;
|
||||
case MSEFallCosAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mi->j_cosAngle;
|
||||
break;
|
||||
case MSEFallSinAngle:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mi->j_sinAngle;
|
||||
break;
|
||||
case MSEFallHorizontalSpeed:
|
||||
if (hasFallData && hasFallDirection)
|
||||
data << mi->j_xyspeed;
|
||||
break;
|
||||
case MSESplineElevation:
|
||||
if (hasSplineElevation)
|
||||
data << mi->splineElevation;
|
||||
break;
|
||||
case MSEZeroBit:
|
||||
data.WriteBit(0);
|
||||
break;
|
||||
case MSEOneBit:
|
||||
data.WriteBit(1);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false && "Incorrect sequence element detected at ReadMovementInfo");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +202,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
|
||||
recvData.read_skip<uint32>(); // unk
|
||||
|
||||
MovementInfo movementInfo; // used only for proper packet read
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
_player->ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
// in taxi flight packet received in 2 case:
|
||||
// 1) end taxi path in far (multi-node) flight
|
||||
|
||||
@@ -36,7 +36,7 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recvData)
|
||||
}
|
||||
|
||||
MovementInfo mi;
|
||||
ReadMovementInfo(recvData, &mi);
|
||||
_player->ReadMovementInfo(recvData, &mi);
|
||||
|
||||
_player->m_movementInfo = mi;
|
||||
|
||||
|
||||
@@ -2094,6 +2094,89 @@ MovementStatusElements DismissControlledVehicle[] =
|
||||
MSEEnd,
|
||||
};
|
||||
|
||||
// 4.3.4
|
||||
MovementStatusElements MoveUpdateTeleport[] =
|
||||
{
|
||||
MSEPositionZ,
|
||||
MSEPositionY,
|
||||
MSEPositionX,
|
||||
MSEHasOrientation,
|
||||
|
||||
MSEHasSpline,
|
||||
MSEHasMovementFlags,
|
||||
MSEHasGuidByte2,
|
||||
MSEHasGuidByte4,
|
||||
MSEHasGuidByte6,
|
||||
MSEHasFallData,
|
||||
MSEHasGuidByte0,
|
||||
MSEHasTransportData,
|
||||
MSEHasGuidByte5,
|
||||
|
||||
MSEHasTransportGuidByte1,
|
||||
MSEHasTransportGuidByte4,
|
||||
MSEHasTransportGuidByte5,
|
||||
MSEHasTransportGuidByte3,
|
||||
MSEHasTransportGuidByte0,
|
||||
MSEHasTransportTime2,
|
||||
MSEHasTransportGuidByte7,
|
||||
MSEHasTransportGuidByte6,
|
||||
MSEHasTransportTime3,
|
||||
MSEHasTransportGuidByte2,
|
||||
|
||||
MSEZeroBit,
|
||||
|
||||
MSEHasGuidByte7,
|
||||
MSEHasGuidByte3,
|
||||
MSEHasPitch,
|
||||
MSEHasMovementFlags2,
|
||||
MSEHasTimestamp,
|
||||
|
||||
MSEHasFallDirection,
|
||||
MSEMovementFlags2,
|
||||
MSEHasSplineElevation,
|
||||
MSEMovementFlags,
|
||||
MSEHasGuidByte1,
|
||||
|
||||
MSEGuidByte7,
|
||||
MSETransportGuidByte3,
|
||||
MSETransportGuidByte4,
|
||||
MSETransportOrientation,
|
||||
MSETransportTime3,
|
||||
MSETransportGuidByte1,
|
||||
MSETransportTime2,
|
||||
MSETransportPositionZ,
|
||||
MSETransportGuidByte7,
|
||||
MSETransportGuidByte0,
|
||||
MSETransportGuidByte6,
|
||||
MSETransportGuidByte5,
|
||||
MSETransportGuidByte2,
|
||||
MSETransportSeat,
|
||||
MSETransportTime,
|
||||
MSETransportPositionY,
|
||||
MSETransportPositionX,
|
||||
|
||||
MSEGuidByte6,
|
||||
MSEPitch,
|
||||
MSESplineElevation,
|
||||
MSEOrientation,
|
||||
MSEGuidByte2,
|
||||
MSEGuidByte3,
|
||||
MSEGuidByte1,
|
||||
|
||||
MSEFallTime,
|
||||
MSEFallHorizontalSpeed,
|
||||
MSEFallSinAngle,
|
||||
MSEFallCosAngle,
|
||||
MSEFallVerticalSpeed,
|
||||
|
||||
MSEGuidByte5,
|
||||
MSEGuidByte4,
|
||||
MSETimestamp,
|
||||
MSEGuidByte0,
|
||||
|
||||
MSEEnd,
|
||||
};
|
||||
|
||||
MovementStatusElements* GetMovementStatusElementsSequence(Opcodes opcode)
|
||||
{
|
||||
switch (opcode)
|
||||
@@ -2152,6 +2235,8 @@ MovementStatusElements* GetMovementStatusElementsSequence(Opcodes opcode)
|
||||
return MoveNotActiveMover;
|
||||
case CMSG_DISMISS_CONTROLLED_VEHICLE:
|
||||
return DismissControlledVehicle;
|
||||
case MSG_MOVE_UPDATE_TELEPORT:
|
||||
return MoveUpdateTeleport;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -597,7 +597,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_COLLISION_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_FLIGHT_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_RUN_SPEED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_TELEPORT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_MOVE_WORLDPORT_ACK, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode );
|
||||
DEFINE_OPCODE_HANDLER(MSG_NOTIFY_PARTY_SQUELCH, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER(MSG_PARTY_ASSIGNMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
|
||||
|
||||
@@ -209,9 +209,6 @@ class WorldSession
|
||||
void SendAddonsInfo();
|
||||
bool IsAddonRegistered(const std::string& prefix) const;
|
||||
|
||||
void ReadMovementInfo(WorldPacket& data, MovementInfo* mi);
|
||||
void WriteMovementInfo(WorldPacket& data, MovementInfo* mi);
|
||||
|
||||
void SendPacket(WorldPacket const* packet, bool forced = false);
|
||||
void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3);
|
||||
void SendNotification(uint32 string_id, ...);
|
||||
|
||||
Reference in New Issue
Block a user