diff --git a/src/server/game/Entities/Object/MovementInfo.cpp b/src/server/game/Entities/Object/MovementInfo.cpp new file mode 100644 index 0000000000..ce3a44068c --- /dev/null +++ b/src/server/game/Entities/Object/MovementInfo.cpp @@ -0,0 +1,134 @@ +/* + * This file is part of the TrinityCore 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 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 General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "MovementInfo.h" +#include "GameTime.h" +#include "Log.h" +#include "UnitDefines.h" +#include "G3DPosition.hpp" + +void MovementInfo::ResetTransport() +{ + transport.Reset(); +} + +void MovementInfo::ResetJump() +{ + jump.Reset(); +} + +bool MovementInfo::HasFallDirection() const +{ + return HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR); +} + +bool MovementInfo::HasFallData() const +{ + return (HasFallDirection() || jump.fallTime != 0); +} + +bool MovementInfo::HasMovementFlags() const +{ + return GetMovementFlags() != 0; +}; + +bool MovementInfo::HasExtraMovementFlags() const +{ + return GetExtraMovementFlags() != 0; +}; + +bool MovementInfo::HasSpline() const +{ + // Todo: handle this + return false; +}; + +bool MovementInfo::HasHeightChangeFailed() const +{ + // Todo: handle this + return false; +} + +bool MovementInfo::HasTime() const +{ + return time != 0; +} + +bool MovementInfo::HasOrientation() const +{ + return !G3D::fuzzyEq(pos.GetOrientation(), 0.0f); +} + +bool MovementInfo::HasSplineElevation() const +{ + return HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); +} + +bool MovementInfo::HasPitch() const +{ + return (HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)); +} + +bool MovementInfo::HasTransportData() const +{ + return !transport.guid.IsEmpty(); +} + +bool MovementInfo::HasTransportVehicleId() const +{ + return HasTransportData() && transport.vehicleId != 0; +} + +bool MovementInfo::HasTransportTime2() const +{ + return HasTransportData() && transport.time2 != 0; +} + +void MovementInfo::OutDebug() +{ + TC_LOG_DEBUG("misc", "MOVEMENT INFO"); + TC_LOG_DEBUG("misc", "%s", guid.ToString().c_str()); + TC_LOG_DEBUG("misc", "flags %u", flags); + TC_LOG_DEBUG("misc", "flags2 %u", flags2); + TC_LOG_DEBUG("misc", "time %u current time " UI64FMTD "", flags2, uint64(::GameTime::GetGameTime())); + TC_LOG_DEBUG("misc", "position: `%s`", pos.ToString().c_str()); + if (transport.guid) + { + TC_LOG_DEBUG("misc", "TRANSPORT:"); + TC_LOG_DEBUG("misc", "%s", transport.guid.ToString().c_str()); + TC_LOG_DEBUG("misc", "position: `%s`", transport.pos.ToString().c_str()); + TC_LOG_DEBUG("misc", "seat: %i", transport.seat); + TC_LOG_DEBUG("misc", "time: %u", transport.time); + if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT) + TC_LOG_DEBUG("misc", "time2: %u", transport.time2); + if (transport.vehicleId) + TC_LOG_INFO("misc", "vehicleId: %u", transport.vehicleId); + } + + if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) + TC_LOG_DEBUG("misc", "pitch: %f", pitch); + + if (flags & MOVEMENTFLAG_FALLING || jump.fallTime) + { + TC_LOG_INFO("misc", "fallTime: %u j_zspeed: %f", jump.fallTime, jump.zspeed); + if (flags & MOVEMENTFLAG_FALLING) + TC_LOG_DEBUG("misc", "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed); + } + + if (flags & MOVEMENTFLAG_SPLINE_ELEVATION) + TC_LOG_DEBUG("misc", "splineElevation: %f", splineElevation); +} diff --git a/src/server/game/Entities/Object/MovementInfo.h b/src/server/game/Entities/Object/MovementInfo.h index a1283a779f..4edb9dee00 100644 --- a/src/server/game/Entities/Object/MovementInfo.h +++ b/src/server/game/Entities/Object/MovementInfo.h @@ -95,15 +95,21 @@ struct MovementInfo uint32 GetFallTime() const { return jump.fallTime; } void SetFallTime(uint32 time) { jump.fallTime = time; } - void ResetTransport() - { - transport.Reset(); - } - - void ResetJump() - { - jump.Reset(); - } + void ResetTransport(); + void ResetJump(); + bool HasFallDirection() const; + bool HasFallData() const; + bool HasMovementFlags() const; + bool HasExtraMovementFlags() const; + bool HasSpline() const; + bool HasHeightChangeFailed() const; + bool HasTime() const; + bool HasOrientation() const; + bool HasSplineElevation() const; + bool HasPitch() const; + bool HasTransportData() const; + bool HasTransportVehicleId() const; + bool HasTransportTime2() const; void OutDebug(); }; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index b867676684..a62d6e713c 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1151,41 +1151,6 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } -void MovementInfo::OutDebug() -{ - TC_LOG_DEBUG("misc", "MOVEMENT INFO"); - TC_LOG_DEBUG("misc", "%s", guid.ToString().c_str()); - TC_LOG_DEBUG("misc", "flags %u", flags); - TC_LOG_DEBUG("misc", "flags2 %u", flags2); - TC_LOG_DEBUG("misc", "time %u current time " UI64FMTD "", flags2, uint64(::GameTime::GetGameTime())); - TC_LOG_DEBUG("misc", "position: `%s`", pos.ToString().c_str()); - if (transport.guid) - { - TC_LOG_DEBUG("misc", "TRANSPORT:"); - TC_LOG_DEBUG("misc", "%s", transport.guid.ToString().c_str()); - TC_LOG_DEBUG("misc", "position: `%s`", transport.pos.ToString().c_str()); - TC_LOG_DEBUG("misc", "seat: %i", transport.seat); - TC_LOG_DEBUG("misc", "time: %u", transport.time); - if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT) - TC_LOG_DEBUG("misc", "time2: %u", transport.time2); - if (transport.vehicleId) - TC_LOG_INFO("misc", "vehicleId: %u", transport.vehicleId); - } - - if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) - TC_LOG_DEBUG("misc", "pitch: %f", pitch); - - if (flags & MOVEMENTFLAG_FALLING || jump.fallTime) - { - TC_LOG_INFO("misc", "fallTime: %u j_zspeed: %f", jump.fallTime, jump.zspeed); - if (flags & MOVEMENTFLAG_FALLING) - TC_LOG_DEBUG("misc", "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed); - } - - if (flags & MOVEMENTFLAG_SPLINE_ELEVATION) - TC_LOG_DEBUG("misc", "splineElevation: %f", splineElevation); -} - WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0), m_name(""), m_isActive(false), m_isFarVisible(false), m_isWorldObject(isWorldObject), m_zoneScript(nullptr), m_transport(nullptr), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_outdoors(true), m_liquidStatus(LIQUID_MAP_NO_WATER), diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 32f58b2e44..d816e64bcc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -27775,6 +27775,94 @@ bool Player::CanUseMastery() const return HasSpell(MasterySpells[getClass()]); } +void Player::ValidateMovementInfo(MovementInfo* 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) \ + { \ + TC_LOG_DEBUG("entities.unit", "Player::ValidateMovementInfo: Violation of MovementFlags found (%s). " \ + "MovementFlags: %u, MovementFlags2: %u for player %s. Mask %u will be removed.", \ + STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetGUID().ToString().c_str(), maskToRemove); \ + mi->RemoveMovementFlag((maskToRemove)); \ + } \ + } + #else + #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) \ + if (check) \ + mi->RemoveMovementFlag((maskToRemove)); + #endif + + if (!m_unitMovedByMe->GetVehicleBase() || !(m_unitMovedByMe->GetVehicle()->GetVehicleInfo()->Flags & VEHICLE_FLAG_FIXED_POSITION)) + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT), MOVEMENTFLAG_ROOT); + + /*! 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) && mi->HasMovementFlag(MOVEMENTFLAG_MASK_MOVING), + MOVEMENTFLAG_MASK_MOVING); + + //! Cannot hover without SPELL_AURA_HOVER + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !m_unitMovedByMe->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 except for ghosts + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && + !m_unitMovedByMe->HasAuraType(SPELL_AURA_WATER_WALK) && + !m_unitMovedByMe->HasAuraType(SPELL_AURA_GHOST), + MOVEMENTFLAG_WATERWALKING); + + //! Cannot feather fall without SPELL_AURA_FEATHER_FALL + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !m_unitMovedByMe->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) && GetSession()->GetSecurity() == SEC_PLAYER && + !m_unitMovedByMe->HasAuraType(SPELL_AURA_FLY) && + !m_unitMovedByMe->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED), + MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY); + + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING), + MOVEMENTFLAG_FALLING); + + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) && G3D::fuzzyEq(mi->splineElevation, 0.0f), MOVEMENTFLAG_SPLINE_ELEVATION); + + // Client first checks if spline elevation != 0, then verifies flag presence + if (G3D::fuzzyNe(mi->splineElevation, 0.0f)) + mi->AddMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); + + #undef REMOVE_VIOLATING_FLAGS +} + void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::ExtraMovementStatusElement* extras /*= nullptr*/) { MovementStatusElements const* sequence = GetMovementStatusElementsSequence(static_cast(data.GetOpcode())); @@ -27990,89 +28078,7 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext mi->guid = guid; mi->transport.guid = tguid; - //! 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) \ - { \ - TC_LOG_DEBUG("entities.unit", "Player::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(), GetGUID().GetCounter(), 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) && mi->HasMovementFlag(MOVEMENTFLAG_MASK_MOVING), - MOVEMENTFLAG_MASK_MOVING); - - //! 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 except for ghosts - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && - !HasAuraType(SPELL_AURA_WATER_WALK) && - !HasAuraType(SPELL_AURA_GHOST), - 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_unitMovedByMe->HasAuraType(SPELL_AURA_FLY) && - !ToPlayer()->m_unitMovedByMe->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED), - MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY); - - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING), - MOVEMENTFLAG_FALLING); - - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING) && (!hasFallData || !hasFallDirection), MOVEMENTFLAG_FALLING); - - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) && G3D::fuzzyEq(mi->splineElevation, 0.0f), MOVEMENTFLAG_SPLINE_ELEVATION); - - // Client first checks if spline elevation != 0, then verifies flag presence - if (hasSplineElevation) - mi->AddMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); - - #undef REMOVE_VIOLATING_FLAGS + ValidateMovementInfo(mi); } void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index d95989810a..9619de89cd 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2356,6 +2356,9 @@ class TC_GAME_API Player : public Unit, public GridObject /*! These methods send different packets to the client in apply and unapply case. These methods are only sent to the current unit. */ + + void ValidateMovementInfo(MovementInfo* mi); + void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply); void SendMovementSetCollisionHeight(float height, UpdateCollisionHeightReason reason); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 38a38ea55a..72ddf5821d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13823,7 +13823,7 @@ void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusEle break; case MSETimestamp: if (hasTimestamp) - data << getMSTime(); + data << mi.time; break; case MSEPositionX: data << GetPositionX(); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 5001468d47..3b162c717a 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -682,16 +682,14 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData) _player->SummonIfPossible(agree); } -void WorldSession::HandleSetCollisionHeightAck(WorldPacket& recvPacket) +void WorldSession::HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCollisionHeightAck& packet) { - TC_LOG_DEBUG("network", "CMSG_MOVE_SET_COLLISION_HEIGHT_ACK"); + _player->ValidateMovementInfo(&packet.Data.Status); - static MovementStatusElements const heightElement = MSEExtraFloat; - Movement::ExtraMovementStatusElement extra(&heightElement); - MovementInfo movementInfo; - GetPlayer()->ReadMovementInfo(recvPacket, &movementInfo, &extra); - - Movement::PacketSender(_player, NULL_OPCODE, NULL_OPCODE, SMSG_MOVE_UPDATE_COLLISION_HEIGHT, &extra).Send(); + WorldPackets::Movement::MoveUpdateCollisionHeight updateCollisionHeight; + updateCollisionHeight.Height = packet.Height; + updateCollisionHeight.Status = &_player->m_movementInfo; + _player->SendMessageToSet(updateCollisionHeight.Write(), false); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData) diff --git a/src/server/game/Movement/MovementStructures.cpp b/src/server/game/Movement/MovementStructures.cpp index 2d0494410c..770a437f0f 100644 --- a/src/server/game/Movement/MovementStructures.cpp +++ b/src/server/game/Movement/MovementStructures.cpp @@ -2503,77 +2503,6 @@ MovementStatusElements const MovementUpdateFlightSpeed[] = MSEEnd }; -MovementStatusElements const MovementUpdateCollisionHeight[] = -{ - MSEPositionZ, - MSEExtraElement, - MSEPositionX, - MSEPositionY, - MSEHasGuidByte6, - MSEHasGuidByte7, - MSEHasSplineElevation, - MSEHasTransportData, - MSEHasTransportGuidByte6, - MSEHasTransportGuidByte4, - MSEHasTransportGuidByte3, - MSEHasTransportGuidByte7, - MSEHasTransportGuidByte5, - MSEHasTransportGuidByte1, - MSEHasTransportGuidByte0, - MSEHasTransportGuidByte2, - MSEHasGuidByte3, - MSEHasOrientation, - MSEHasGuidByte4, - MSEHasGuidByte5, - MSEHasTimestamp, - MSEHasFallData, - MSEHasGuidByte0, - MSEHasPitch, - MSEZeroBit, - MSEHasGuidByte2, - MSEHasMovementFlags, - MSEHasFallDirection, - MSEHasGuidByte1, - MSEHasMovementFlags2, - MSEHasSpline, - MSEMovementFlags2, - MSEMovementFlags, - MSEGuidByte3, - MSETransportGuidByte7, - MSETransportTime, - MSETransportGuidByte4, - MSETransportVehicleId, - MSETransportTime2, - MSETransportGuidByte5, - MSETransportOrientation, - MSETransportPositionX, - MSETransportGuidByte6, - MSETransportGuidByte0, - MSETransportPositionY, - MSETransportGuidByte2, - MSETransportPositionZ, - MSETransportGuidByte3, - MSETransportGuidByte1, - MSETransportSeat, - MSEPitch, - MSEGuidByte6, - MSEFallCosAngle, - MSEFallSinAngle, - MSEFallHorizontalSpeed, - MSEFallVerticalSpeed, - MSEFallTime, - MSEGuidByte7, - MSEOrientation, - MSEGuidByte0, - MSEGuidByte5, - MSEGuidByte4, - MSESplineElevation, - MSETimestamp, - MSEGuidByte2, - MSEGuidByte1, - MSEEnd, -}; - MovementStatusElements const MovementForceRunSpeedChangeAck[] = { MSECounter, @@ -2648,82 +2577,6 @@ MovementStatusElements const MovementForceRunSpeedChangeAck[] = MSEEnd, }; -MovementStatusElements const MovementSetCollisionHeightAck[] = -{ - MSEExtraElement, - MSEPositionX, - MSEPositionZ, - MSECounter, - MSEPositionY, - MSEHasGuidByte6, - MSEHasGuidByte4, - MSEZeroBit, - MSEZeroBit, - MSEHasPitch, - MSEHasGuidByte5, - MSEZeroBit, - MSEHasGuidByte2, - MSEHasGuidByte1, - MSEHasFallData, - MSEHasGuidByte3, - MSEHasSpline, - MSEHasGuidByte7, - MSEHasMovementFlags, - MSEHasTransportData, - MSEHasTimestamp, - MSEHasSplineElevation, - MSEHasMovementFlags2, - MSEHasOrientation, - MSEHasGuidByte0, - MSEHasTransportGuidByte4, - MSEHasTransportGuidByte3, - MSEHasTransportTime2, - MSEHasVehicleId, - MSEHasTransportGuidByte5, - MSEHasTransportGuidByte1, - MSEHasTransportGuidByte7, - MSEHasTransportGuidByte2, - MSEHasTransportGuidByte6, - MSEHasTransportGuidByte0, - MSEMovementFlags2, - MSEMovementFlags, - MSEHasFallDirection, - MSEGuidByte0, - MSEGuidByte3, - MSEGuidByte1, - MSEGuidByte5, - MSEGuidByte7, - MSEGuidByte6, - MSEGuidByte2, - MSEGuidByte4, - MSETransportPositionX, - MSETransportGuidByte4, - MSETransportTime2, - MSETransportGuidByte0, - MSETransportOrientation, - MSETransportPositionY, - MSETransportGuidByte7, - MSETransportSeat, - MSETransportGuidByte5, - MSETransportGuidByte2, - MSETransportTime, - MSETransportGuidByte6, - MSETransportGuidByte3, - MSETransportGuidByte1, - MSETransportVehicleId, - MSETransportPositionZ, - MSEFallVerticalSpeed, - MSEFallTime, - MSEFallCosAngle, - MSEFallSinAngle, - MSEFallHorizontalSpeed, - MSETimestamp, - MSESplineElevation, - MSEOrientation, - MSEPitch, - MSEEnd, -}; - MovementStatusElements const MovementForceFlightSpeedChangeAck[] = { MSECounter, @@ -5684,10 +5537,6 @@ MovementStatusElements const* GetMovementStatusElementsSequence(uint32 opcode) return MovementSetCanFlyAck; case CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK: return MovementSetCanTransitionBetweenSwimAndFlyAck; - case CMSG_MOVE_SET_COLLISION_HEIGHT_ACK: - return MovementSetCollisionHeightAck; - case SMSG_MOVE_UPDATE_COLLISION_HEIGHT: - return MovementUpdateCollisionHeight; case CMSG_MOVE_WATER_WALK_ACK: return MovementWaterWalkAck; case MSG_MOVE_SET_RUN_MODE: diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 1be22695f9..20c8f0485d 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -24,73 +24,59 @@ WorldPacket const* WorldPackets::Movement::MoveUpdate::Write() { - bool hasFallDirection = Status->HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR); - bool hasFallData = hasFallDirection || Status->jump.fallTime != 0; - bool hasMovementFlags = Status->GetMovementFlags() != 0; - bool hasExtraMovementFlags = Status->GetExtraMovementFlags() != 0; - bool hasSpline = false; // todo 4.x send this info - bool heightChangeFailed = false; // todo 4.x send this info - bool hasTime = Status->time != 0; - bool hasOrientation = !G3D::fuzzyEq(Status->pos.GetOrientation(), 0.0f); - bool hasSplineElevation = Status->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); - bool hasPitch = Status->HasMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || Status->HasExtraMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING); - bool hasTransportData = !Status->transport.guid.IsEmpty(); - bool hasTransportVehicleId = hasTransportData && Status->transport.vehicleId != 0; - bool hasTransportTime2 = hasTransportData && Status->transport.time2 != 0; - ObjectGuid guid = Status->guid; ObjectGuid transportGuid = Status->transport.guid; - _worldPacket.WriteBit(hasFallData); + _worldPacket.WriteBit(Status->HasFallData()); _worldPacket.WriteBit(guid[3]); _worldPacket.WriteBit(guid[6]); - _worldPacket.WriteBit(!hasExtraMovementFlags); - _worldPacket.WriteBit(hasSpline); - _worldPacket.WriteBit(!hasTime); + _worldPacket.WriteBit(!Status->HasExtraMovementFlags()); + _worldPacket.WriteBit(Status->HasSpline()); + _worldPacket.WriteBit(!Status->HasTime()); _worldPacket.WriteBit(guid[0]); _worldPacket.WriteBit(guid[1]); - if (hasExtraMovementFlags) + if (Status->HasExtraMovementFlags()) _worldPacket.WriteBits(Status->GetExtraMovementFlags(), 12); _worldPacket.WriteBit(guid[7]); - _worldPacket.WriteBit(!hasMovementFlags); - _worldPacket.WriteBit(!hasOrientation); + _worldPacket.WriteBit(!Status->HasMovementFlags()); + _worldPacket.WriteBit(!Status->HasOrientation()); _worldPacket.WriteBit(guid[2]); - _worldPacket.WriteBit(!hasSplineElevation); - _worldPacket.WriteBit(heightChangeFailed); + _worldPacket.WriteBit(!Status->HasSplineElevation()); + _worldPacket.WriteBit(Status->HasHeightChangeFailed()); _worldPacket.WriteBit(guid[4]); - if (hasFallData) - _worldPacket.WriteBit(hasFallDirection); + if (Status->HasFallData()) + _worldPacket.WriteBit(Status->HasFallDirection()); _worldPacket.WriteBit(guid[5]); - _worldPacket.WriteBit(hasTransportData); - if (hasMovementFlags) + _worldPacket.WriteBit(Status->HasTransportData()); + if (Status->HasMovementFlags()) _worldPacket.WriteBits(Status->GetMovementFlags(), 30); - if (hasTransportData) + if (Status->HasTransportData()) { _worldPacket.WriteBit(transportGuid[3]); - _worldPacket.WriteBit(hasTransportVehicleId); + _worldPacket.WriteBit(Status->HasTransportVehicleId()); _worldPacket.WriteBit(transportGuid[6]); _worldPacket.WriteBit(transportGuid[1]); _worldPacket.WriteBit(transportGuid[7]); _worldPacket.WriteBit(transportGuid[0]); _worldPacket.WriteBit(transportGuid[4]); - _worldPacket.WriteBit(hasTransportTime2); + _worldPacket.WriteBit(Status->HasTransportTime2()); _worldPacket.WriteBit(transportGuid[5]); _worldPacket.WriteBit(transportGuid[2]); } - _worldPacket.WriteBit(!hasPitch); + _worldPacket.WriteBit(!Status->HasPitch()); _worldPacket.FlushBits(); _worldPacket.WriteByteSeq(guid[5]); - if (hasFallData) + if (Status->HasFallData()) { - if (hasFallDirection) + if (Status->HasFallDirection()) { _worldPacket << float(Status->jump.xyspeed); _worldPacket << float(Status->jump.sinAngle); @@ -101,27 +87,27 @@ WorldPacket const* WorldPackets::Movement::MoveUpdate::Write() _worldPacket << uint32(Status->jump.fallTime); } - if (hasSplineElevation) + if (Status->HasSplineElevation()) _worldPacket << float(Status->splineElevation); _worldPacket.WriteByteSeq(guid[7]); _worldPacket << float(Status->pos.GetPositionY()); _worldPacket.WriteByteSeq(guid[3]); - if (hasTransportData) + if (Status->HasTransportData()) { - if (hasTransportVehicleId) + if (Status->HasTransportVehicleId()) _worldPacket << uint32(Status->transport.vehicleId); _worldPacket.WriteByteSeq(transportGuid[6]); - _worldPacket << uint8(Status->transport.seat); + _worldPacket << int8(Status->transport.seat); _worldPacket.WriteByteSeq(transportGuid[5]); _worldPacket << float(Status->transport.pos.GetPositionX()); _worldPacket.WriteByteSeq(transportGuid[1]); _worldPacket << float(Status->transport.pos.GetOrientation()); _worldPacket.WriteByteSeq(transportGuid[2]); - if (hasTransportTime2) + if (Status->HasTransportTime2()) _worldPacket << uint32(Status->transport.time2); _worldPacket.WriteByteSeq(transportGuid[0]); @@ -138,16 +124,16 @@ WorldPacket const* WorldPackets::Movement::MoveUpdate::Write() _worldPacket.WriteByteSeq(guid[6]); _worldPacket << float(Status->pos.GetPositionZ()); - if (hasTime) + if (Status->HasTime()) _worldPacket << uint32(Status->time); _worldPacket.WriteByteSeq(guid[2]); - if (hasPitch) + if (Status->HasPitch()) _worldPacket << float(Status->pitch); _worldPacket.WriteByteSeq(guid[0]); - if (hasOrientation) + if (Status->HasOrientation()) _worldPacket << float(Status->pos.GetOrientation()); _worldPacket.WriteByteSeq(guid[1]); @@ -155,6 +141,126 @@ WorldPacket const* WorldPackets::Movement::MoveUpdate::Write() return &_worldPacket; } +void WorldPackets::Movement::MoveSetCollisionHeightAck::Read() +{ + _worldPacket >> Height; + _worldPacket >> Data.Status.pos.m_positionX; + _worldPacket >> Data.Status.pos.m_positionZ; + _worldPacket >> Data.AckIndex; + _worldPacket >> Data.Status.pos.m_positionY; + Data.Status.guid[6] = _worldPacket.ReadBit(); + Data.Status.guid[4] = _worldPacket.ReadBit(); + + Reason = UpdateCollisionHeightReason(_worldPacket.ReadBits(2)); + + bool hasPitch = !_worldPacket.ReadBit(); + Data.Status.guid[5] = _worldPacket.ReadBit(); + _worldPacket.ReadBit(); // HeightChangeFailed + Data.Status.guid[2] = _worldPacket.ReadBit(); + Data.Status.guid[1] = _worldPacket.ReadBit(); + bool hasFallData = _worldPacket.ReadBit(); + Data.Status.guid[3] = _worldPacket.ReadBit(); + _worldPacket.ReadBit(); // HasSpline + Data.Status.guid[7] = _worldPacket.ReadBit(); + bool hasMovementFlags = !_worldPacket.ReadBit(); + bool hasTransportData = _worldPacket.ReadBit(); + bool hasTime = !_worldPacket.ReadBit(); + bool hasSplineElevation = !_worldPacket.ReadBit(); + bool hasExtraMovementFlags = !_worldPacket.ReadBit(); + bool hasOrientation = !_worldPacket.ReadBit(); + + Data.Status.guid[0] = _worldPacket.ReadBit(); + + bool hasTransportTime2 = false; + bool hasVehicleId = false; + if (hasTransportData) + { + Data.Status.transport.guid[4] = _worldPacket.ReadBit(); + Data.Status.transport.guid[3] = _worldPacket.ReadBit(); + hasTransportTime2 = _worldPacket.ReadBit(); + hasVehicleId = _worldPacket.ReadBit(); + Data.Status.transport.guid[5] = _worldPacket.ReadBit(); + Data.Status.transport.guid[1] = _worldPacket.ReadBit(); + Data.Status.transport.guid[7] = _worldPacket.ReadBit(); + Data.Status.transport.guid[2] = _worldPacket.ReadBit(); + Data.Status.transport.guid[6] = _worldPacket.ReadBit(); + Data.Status.transport.guid[0] = _worldPacket.ReadBit(); + } + + if (hasExtraMovementFlags) + Data.Status.flags2 = _worldPacket.ReadBits(12); + + if (hasMovementFlags) + Data.Status.flags = _worldPacket.ReadBits(30); + + bool hasFallDirection = false; + if (hasFallData) + hasFallDirection = _worldPacket.ReadBit(); + + _worldPacket.ReadByteSeq(Data.Status.guid[0]); + _worldPacket.ReadByteSeq(Data.Status.guid[3]); + _worldPacket.ReadByteSeq(Data.Status.guid[1]); + _worldPacket.ReadByteSeq(Data.Status.guid[5]); + _worldPacket.ReadByteSeq(Data.Status.guid[7]); + _worldPacket.ReadByteSeq(Data.Status.guid[6]); + _worldPacket.ReadByteSeq(Data.Status.guid[2]); + _worldPacket.ReadByteSeq(Data.Status.guid[4]); + + if (hasTransportData) + { + _worldPacket >> Data.Status.transport.pos.m_positionX; + _worldPacket.ReadByteSeq(Data.Status.transport.guid[4]); + + if (hasTransportTime2) + _worldPacket >> Data.Status.transport.time2; + + _worldPacket.ReadByteSeq(Data.Status.transport.guid[0]); + float o = 0.f; + _worldPacket >> o; + Data.Status.transport.pos.SetOrientation(o); + _worldPacket >> Data.Status.transport.pos.m_positionY; + _worldPacket.ReadByteSeq(Data.Status.transport.guid[7]); + _worldPacket >> Data.Status.transport.seat; + _worldPacket.ReadByteSeq(Data.Status.transport.guid[5]); + _worldPacket.ReadByteSeq(Data.Status.transport.guid[2]); + _worldPacket >> Data.Status.transport.time; + _worldPacket.ReadByteSeq(Data.Status.transport.guid[6]); + _worldPacket.ReadByteSeq(Data.Status.transport.guid[3]); + _worldPacket.ReadByteSeq(Data.Status.transport.guid[1]); + + if (hasVehicleId) + _worldPacket >> Data.Status.transport.vehicleId; + + _worldPacket >> Data.Status.transport.pos.m_positionZ; + } + + if (hasFallData) + { + _worldPacket >> Data.Status.jump.zspeed; + _worldPacket >> Data.Status.jump.fallTime; + + if (hasFallDirection) + { + _worldPacket >> Data.Status.jump.cosAngle; + _worldPacket >> Data.Status.jump.sinAngle; + _worldPacket >> Data.Status.jump.xyspeed; + } + } + + if (hasTime) + _worldPacket >> Data.Status.time; + if (hasSplineElevation) + _worldPacket >> Data.Status.splineElevation; + if (hasOrientation) + { + float o = 0.f; + _worldPacket >> o; + Data.Status.pos.SetOrientation(o); + } + if (hasPitch) + _worldPacket >> Data.Status.pitch; +} + WorldPacket const* WorldPackets::Movement::TransferPending::Write() { _worldPacket.WriteBit(TransferSpellID.is_initialized()); @@ -229,6 +335,125 @@ WorldPacket const* WorldPackets::Movement::MoveSetCollisionHeight::Write() return &_worldPacket; } +WorldPacket const* WorldPackets::Movement::MoveUpdateCollisionHeight::Write() +{ + _worldPacket << float(Status->pos.GetPositionZ()); + _worldPacket << float(Height); + _worldPacket << float(Status->pos.GetPositionX()); + _worldPacket << float(Status->pos.GetPositionY()); + + _worldPacket.WriteBit(Status->guid[6]); + _worldPacket.WriteBit(Status->guid[7]); + _worldPacket.WriteBit(!Status->HasSplineElevation()); + _worldPacket.WriteBit(Status->HasTransportData()); + + if (Status->HasTransportData()) + { + _worldPacket.WriteBit(Status->transport.guid[6]); + _worldPacket.WriteBit(Status->transport.guid[4]); + _worldPacket.WriteBit(Status->transport.guid[3]); + _worldPacket.WriteBit(Status->transport.guid[7]); + _worldPacket.WriteBit(Status->transport.guid[5]); + _worldPacket.WriteBit(Status->HasTransportVehicleId()); + _worldPacket.WriteBit(Status->transport.guid[1]); + _worldPacket.WriteBit(Status->transport.guid[0]); + _worldPacket.WriteBit(Status->transport.guid[2]); + _worldPacket.WriteBit(Status->HasTransportTime2()); + } + + _worldPacket.WriteBit(Status->guid[3]); + _worldPacket.WriteBit(!Status->HasOrientation()); + _worldPacket.WriteBit(Status->guid[4]); + _worldPacket.WriteBit(Status->guid[5]); + _worldPacket.WriteBit(!Status->HasTime()); + _worldPacket.WriteBit(Status->HasFallData()); + _worldPacket.WriteBit(Status->guid[0]); + _worldPacket.WriteBit(!Status->HasPitch()); + _worldPacket.WriteBit(Status->HasHeightChangeFailed()); + _worldPacket.WriteBit(Status->guid[2]); + _worldPacket.WriteBit(!Status->HasMovementFlags()); + + if (Status->HasFallData()) + _worldPacket.WriteBit(Status->HasFallDirection()); + + _worldPacket.WriteBit(Status->guid[1]); + _worldPacket.WriteBit(!Status->HasExtraMovementFlags()); + _worldPacket.WriteBit(Status->HasSpline()); + + if (Status->HasExtraMovementFlags()) + _worldPacket.WriteBits(Status->GetExtraMovementFlags(), 12); + + if (Status->HasMovementFlags()) + _worldPacket.WriteBits(Status->GetMovementFlags(), 30); + + _worldPacket.FlushBits(); + + _worldPacket.WriteByteSeq(Status->guid[3]); + + if (Status->HasTransportData()) + { + _worldPacket.WriteByteSeq(Status->transport.guid[7]); + _worldPacket << uint32(Status->transport.time); + _worldPacket.WriteByteSeq(Status->transport.guid[4]); + + if (Status->HasTransportVehicleId()) + _worldPacket << uint32(Status->transport.vehicleId); + + if (Status->HasTransportTime2()) + _worldPacket << uint32(Status->transport.time2); + + _worldPacket.WriteByteSeq(Status->transport.guid[5]); + _worldPacket << float(Status->transport.pos.GetOrientation()); + _worldPacket << float(Status->transport.pos.GetPositionX()); + _worldPacket.WriteByteSeq(Status->transport.guid[6]); + _worldPacket.WriteByteSeq(Status->transport.guid[0]); + _worldPacket << float(Status->transport.pos.GetPositionY()); + _worldPacket.WriteByteSeq(Status->transport.guid[2]); + _worldPacket << float(Status->transport.pos.GetPositionZ()); + _worldPacket.WriteByteSeq(Status->transport.guid[3]); + _worldPacket.WriteByteSeq(Status->transport.guid[1]); + _worldPacket << int8(Status->transport.seat); + } + + if (Status->HasPitch()) + _worldPacket << float(Status->pitch); + + _worldPacket.WriteByteSeq(Status->guid[6]); + + if (Status->HasFallData()) + { + if (Status->HasFallDirection()) + { + _worldPacket << float(Status->jump.cosAngle); + _worldPacket << float(Status->jump.sinAngle); + _worldPacket << float(Status->jump.xyspeed); + } + + _worldPacket << float(Status->jump.zspeed); + _worldPacket << uint32(Status->jump.fallTime); + } + + _worldPacket.WriteByteSeq(Status->guid[7]); + + if (Status->HasOrientation()) + _worldPacket << float(Status->pos.GetOrientation()); + + _worldPacket.WriteByteSeq(Status->guid[0]); + _worldPacket.WriteByteSeq(Status->guid[5]); + _worldPacket.WriteByteSeq(Status->guid[4]); + + if (Status->HasSplineElevation()) + _worldPacket << float(Status->splineElevation); + + if (Status->HasTime()) + _worldPacket << uint32(Status->time); + + _worldPacket.WriteByteSeq(Status->guid[2]); + _worldPacket.WriteByteSeq(Status->guid[1]); + + return &_worldPacket; +} + WorldPacket const* WorldPackets::Movement::MoveKnockBack::Write() { _worldPacket.WriteBit(MoverGUID[0]); diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index 5463273d1d..fad25dbeef 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -26,6 +26,12 @@ namespace WorldPackets { namespace Movement { + struct MovementAck + { + MovementInfo Status; + int32 AckIndex = 0; + }; + class TC_GAME_API MoveUpdate final : public ServerPacket { public: @@ -36,6 +42,20 @@ namespace WorldPackets MovementInfo* Status = nullptr; }; + class MoveSetCollisionHeightAck final : public ClientPacket + { + public: + MoveSetCollisionHeightAck(WorldPacket&& packet) : ClientPacket(CMSG_MOVE_SET_COLLISION_HEIGHT_ACK, std::move(packet)) { } + + void Read() override; + + MovementAck Data; + UpdateCollisionHeightReason Reason = UPDATE_COLLISION_HEIGHT_MOUNT; + float Height = 1.0f; + }; + + + class TransferPending final : public ServerPacket { struct ShipTransferPending @@ -99,6 +119,17 @@ namespace WorldPackets UpdateCollisionHeightReason Reason = UPDATE_COLLISION_HEIGHT_MOUNT; }; + class MoveUpdateCollisionHeight final : public ServerPacket + { + public: + MoveUpdateCollisionHeight() : ServerPacket(SMSG_MOVE_UPDATE_COLLISION_HEIGHT) { } + + WorldPacket const* Write() override; + + MovementInfo* Status = nullptr; + float Height = 1.0f; + }; + struct MoveKnockBackSpeeds { float HorzSpeed = 0.0f; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 10e2f33658..117d1b42b0 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -143,6 +143,7 @@ namespace WorldPackets namespace Movement { + class MoveSetCollisionHeightAck; class SuspendTokenResponse; } @@ -651,7 +652,7 @@ class TC_GAME_API WorldSession void HandleGravityAckMessage(WorldPacket & recvData); void HandleMoveTeleportAck(WorldPacket& recvPacket); void HandleForceSpeedChangeAck(WorldPacket& recvData); - void HandleSetCollisionHeightAck(WorldPacket& recvPacket); + void HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCollisionHeightAck& packet); void HandlePingOpcode(WorldPacket& recvPacket); void HandleRepopRequestOpcode(WorldPacket& recvPacket);