From 4b56a7b9a364154bc2db3d8d220cbb6365f48be0 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Fri, 12 Nov 2021 19:29:00 +0100 Subject: [PATCH] Core/Movement: converted SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY and SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY to new ack handling --- src/server/game/Entities/Player/Player.cpp | 24 ++++++------ src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 22 ++++++++--- src/server/game/Entities/Unit/Unit.h | 3 +- src/server/game/Handlers/MovementHandler.cpp | 33 ++++++++++++++++ .../game/Movement/MovementPacketSender.cpp | 39 ++++++++++++++++++- .../game/Movement/MovementPacketSender.h | 3 +- .../game/Spells/Auras/SpellAuraEffects.cpp | 3 ++ 8 files changed, 108 insertions(+), 21 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index abf987d743..924f467518 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23422,9 +23422,6 @@ void Player::SendInitialPacketsAfterAddToMap() auraList.front()->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); } - if (CanFly()) - SendMovementSetCanTransitionBetweenSwimAndFly(true); - if (HasAuraType(SPELL_AURA_MOD_STUN)) SetRooted(true); @@ -25869,6 +25866,19 @@ bool Player::SetCanFly(bool enable, bool /*packetOnly = false*/) return true; } +bool Player::SetCanTransitionBetweenSwimAndFly(bool enable) +{ + if (enable == HasExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS)) + return false; + + if (IsMovedByClient() && IsInWorld()) + MovementPacketSender::SendMovementFlagChangeToMover(this, MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS, enable); + else if (IsMovedByClient() && !IsInWorld()) // (1) + Unit::SetCanTransitionBetweenSwimAndFly(enable); + + return true; +} + void Player::ResetAchievements() { m_achievementMgr->Reset(); @@ -27633,14 +27643,6 @@ VoidStorageItem* Player::GetVoidStorageItem(uint64 id, uint8& slot) const return nullptr; } -void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply) -{ - if (apply) - Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY).Send(); - else - Movement::PacketSender(this, NULL_OPCODE, SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY).Send(); -} - void Player::SendMovementSetCollisionHeight(float height, UpdateCollisionHeightReason reason) { WorldPackets::Movement::MoveSetCollisionHeight packet; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 85681e3e87..864258c1a0 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2146,6 +2146,7 @@ class TC_GAME_API Player : public Unit, public GridObject void HandleFall(MovementInfo const& movementInfo); bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override; bool SetCanFly(bool enable, bool packetOnly = false) override; + bool SetCanTransitionBetweenSwimAndFly(bool enable) override; void SetClientControl(Unit* target, bool allowMove); @@ -2352,7 +2353,6 @@ class TC_GAME_API Player : public Unit, public GridObject void ValidateMovementInfo(MovementInfo* mi); - void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply); void SendMovementSetCollisionHeight(float height, UpdateCollisionHeightReason reason); bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c758e33107..8e5997000c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13898,6 +13898,8 @@ void Unit::PurgeAndApplyPendingMovementChanges(bool informObservers /* = true */ case MovementChangeType::SET_CAN_FLY: Unit::SetCanFly(pendingChange.second.apply); break; + case MovementChangeType::SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY: + Unit::SetCanTransitionBetweenSwimAndFly(pendingChange.second.apply); default: ASSERT(false); return; @@ -13917,6 +13919,7 @@ void Unit::PurgeAndApplyPendingMovementChanges(bool informObservers /* = true */ { case MovementChangeType::GRAVITY_DISABLE: case MovementChangeType::SET_CAN_FLY: + case MovementChangeType::SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY: MovementPacketSender::SendMovementFlagChangeToObservers(this); break; default: @@ -14263,9 +14266,6 @@ bool Unit::SetCanFly(bool enable, bool packetOnly) { AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_SPLINE_ELEVATION); - if (GetTypeId() == TYPEID_PLAYER) - AddExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); - SetFall(false); } else @@ -14273,15 +14273,25 @@ bool Unit::SetCanFly(bool enable, bool packetOnly) if (IsFlying() && !IsGravityDisabled()) SetFall(true); RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_MASK_MOVING_FLY); - - if (GetTypeId() == TYPEID_PLAYER) - RemoveExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); } } return true; } +bool Unit::SetCanTransitionBetweenSwimAndFly(bool enable) +{ + if (enable == HasExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS)) + return false; + + if (enable) + AddExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + else + RemoveExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + + return true; +} + bool Unit::SetWaterWalking(bool enable, bool packetOnly /*= false */) { if (!packetOnly) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e4ec2e8f39..7eb8cc7665 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1226,6 +1226,7 @@ class TC_GAME_API Unit : public WorldObject bool SetFall(bool enable); bool SetSwim(bool enable); virtual bool SetCanFly(bool enable, bool packetOnly = false); + virtual bool SetCanTransitionBetweenSwimAndFly(bool enable); bool SetWaterWalking(bool enable, bool packetOnly = false); bool SetFeatherFall(bool enable, bool packetOnly = false); virtual bool SetHover(bool enable, bool packetOnly = false, bool updateAnimationTier = true); @@ -1696,7 +1697,7 @@ class TC_GAME_API Unit : public WorldObject void AddExtraUnitMovementFlag(uint16 f) { m_movementInfo.AddExtraMovementFlag(f); } void RemoveExtraUnitMovementFlag(uint16 f) { m_movementInfo.RemoveExtraMovementFlag(f); } - uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.HasExtraMovementFlag(f); } + bool HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.HasExtraMovementFlag(f); } uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.GetExtraMovementFlags(); } void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.SetExtraMovementFlags(f); } bool IsSplineEnabled() const; diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index e4b4cf44c0..42ea28c71b 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -674,6 +674,39 @@ void WorldSession::HandleMoveSetCanTransitionBetweenSwinAndFlyAck(WorldPacket& r TC_LOG_DEBUG("network", "CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK"); MovementInfo movementInfo; GetPlayer()->ReadMovementInfo(recvData, &movementInfo); + + GameClient* client = GetGameClient(); + if (!client->IsAllowedToMove(movementInfo.guid)) + return; + + Unit* mover = ObjectAccessor::GetUnit(*_player, movementInfo.guid); + + // verify that we have a pending change for the change type and that the counter equals our expected change in case we are about to receive multiple ack messages for the same type + PlayerMovementPendingChange const* pendingChange = mover->GetPendingMovementChange(MovementChangeType::SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY); + if (!pendingChange || pendingChange->movementCounter != movementInfo.movementCounter) + return; + + int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; + if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + { + TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); + movementInfo.time = GameTime::GetGameTimeMS(); + } + else + { + movementInfo.time = (uint32)movementTime; + } + + mover->m_movementInfo = movementInfo; + mover->UpdatePosition(movementInfo.pos); + + if (pendingChange->apply) + mover->AddExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + else + mover->RemoveExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + + MovementPacketSender::SendMovementFlagChangeToObservers(mover); + mover->ClearPendingMovementChangeForType(MovementChangeType::SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY); } void WorldSession::HandleMoveGravityDisableAck(WorldPacket& recvData) diff --git a/src/server/game/Movement/MovementPacketSender.cpp b/src/server/game/Movement/MovementPacketSender.cpp index ab83fd35f7..4e6afd0a70 100644 --- a/src/server/game/Movement/MovementPacketSender.cpp +++ b/src/server/game/Movement/MovementPacketSender.cpp @@ -63,7 +63,17 @@ MovementChangeType MovementPacketSender::GetChangeTypeByMovementFlag(MovementFla case MOVEMENTFLAG_CAN_FLY: return MovementChangeType::SET_CAN_FLY; case MOVEMENTFLAG_DISABLE_GRAVITY: return MovementChangeType::GRAVITY_DISABLE; default: - ASSERT(false, "MovementPacketSender::SendSpeedChangeToMover Unsupported MovementFlags"); + ASSERT(false, "MovementPacketSender::GetChangeTypeByMovementFlag Unsupported MovementFlags"); + } +} + +MovementChangeType MovementPacketSender::GetChangeTypeByMovementFlag(MovementFlags2 mFlag) +{ + switch (mFlag) + { + case MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS: return MovementChangeType::SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY; + default: + ASSERT(false, "MovementPacketSender::GetChangeTypeByMovementFlag Unsupported MovementFlags"); } } @@ -151,6 +161,33 @@ void MovementPacketSender::SendMovementFlagChangeToMover(Unit* unit, MovementFla controller->SendDirectMessage(&data); } +void MovementPacketSender::SendMovementFlagChangeToMover(Unit* unit, MovementFlags2 mFlag, bool apply) +{ + GameClient* controller = unit->GetGameClientMovingMe(); + + ASSERT(controller); + + uint32 mCounter = unit->GetMovementCounterAndInc(); + PlayerMovementPendingChange pendingChange; + pendingChange.movementCounter = mCounter; + pendingChange.apply = apply; + pendingChange.movementChangeType = MovementPacketSender::GetChangeTypeByMovementFlag(mFlag); + unit->AssignPendingMovementChange(pendingChange.movementChangeType, std::move(pendingChange)); + + OpcodeServer opcode; + switch (mFlag) + { + case MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS: opcode = apply ? SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY : SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY; break; + default: + ASSERT(false, "MovementPacketSender::SendMovementFlagChangeToMover Unsupported MovementFlags"); + break; + } + + WorldPacket data(opcode); + unit->WriteMovementInfo(data, nullptr, &mCounter); + controller->SendDirectMessage(&data); +} + void MovementPacketSender::SendMovementFlagChangeToObservers(Unit* unit) { GameClient* controller = unit->GetGameClientMovingMe(); diff --git a/src/server/game/Movement/MovementPacketSender.h b/src/server/game/Movement/MovementPacketSender.h index 06f558d6e6..e100a6c93e 100644 --- a/src/server/game/Movement/MovementPacketSender.h +++ b/src/server/game/Movement/MovementPacketSender.h @@ -116,12 +116,13 @@ class MovementPacketSender ///* movement flag change */ static void SendMovementFlagChangeToMover(Unit* unit, MovementFlags mFlag, bool apply); - //static void SendMovementFlagChangeToMover(Unit* unit, MovementFlags2 mFlag, bool apply); + static void SendMovementFlagChangeToMover(Unit* unit, MovementFlags2 mFlag, bool apply); static void SendMovementFlagChangeToObservers(Unit* unit); // utility method static MovementChangeType GetChangeTypeByMoveType(UnitMoveType moveType); static MovementChangeType GetChangeTypeByMovementFlag(MovementFlags mFlag); + static MovementChangeType GetChangeTypeByMovementFlag(MovementFlags2 mFlag); private: static OpcodeServer const moveTypeToOpcode[MAX_MOVE_TYPE][3]; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 5c7c1335c8..32d22c5d80 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3146,6 +3146,9 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK && (apply || (!target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !target->HasAuraType(SPELL_AURA_FLY)))) { + if (Player* player = target->ToPlayer()) + player->SetCanTransitionBetweenSwimAndFly(apply); + target->SetCanFly(apply); if (!apply && target->GetTypeId() == TYPEID_UNIT && !target->IsGravityDisabled())