diff options
Diffstat (limited to 'src/server/game/Handlers')
-rw-r--r-- | src/server/game/Handlers/CalendarHandler.cpp | 36 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 81 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 428 | ||||
-rw-r--r-- | src/server/game/Handlers/PetHandler.cpp | 23 |
5 files changed, 276 insertions, 309 deletions
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 53cccbf4e0..6bb531636f 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -35,6 +35,7 @@ Copied events should probably have a new owner #include "ArenaTeamMgr.h" #include "CalendarMgr.h" +#include "CalendarPackets.h" #include "DatabaseEnv.h" #include "DisableMgr.h" #include "GameEventMgr.h" @@ -184,43 +185,31 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) SendPacket(&data); } -void WorldSession::HandleCalendarGetEvent(WorldPacket& recvData) +void WorldSession::HandleCalendarGetEvent(WorldPackets::Calendar::GetEvent& packet) { - uint64 eventId; - recvData >> eventId; + LOG_DEBUG("network", "CMSG_CALENDAR_GET_EVENT. Player [{}] Event [{}]", _player->GetGUID().ToString(), packet.EventId); - LOG_DEBUG("network", "CMSG_CALENDAR_GET_EVENT. Player [{}] Event [{}]", _player->GetGUID().ToString(), eventId); - - if (CalendarEvent* calendarEvent = sCalendarMgr->GetEvent(eventId)) + if (CalendarEvent* calendarEvent = sCalendarMgr->GetEvent(packet.EventId)) sCalendarMgr->SendCalendarEvent(_player->GetGUID(), *calendarEvent, CALENDAR_SENDTYPE_GET); else sCalendarMgr->SendCalendarCommandResult(_player->GetGUID(), CALENDAR_ERROR_EVENT_INVALID); } -void WorldSession::HandleCalendarGuildFilter(WorldPacket& recvData) +void WorldSession::HandleCalendarGuildFilter(WorldPackets::Calendar::GuildFilter& packet) { LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER [{}]", _player->GetGUID().ToString()); - uint32 minLevel; - uint32 maxLevel; - uint32 minRank; - - recvData >> minLevel >> maxLevel >> minRank; - if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId())) - guild->MassInviteToEvent(this, minLevel, maxLevel, minRank); + guild->MassInviteToEvent(this, packet.MinimumLevel, packet.MaximumLevel, packet.MinimumRank); - LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER: Min level [{}], Max level [{}], Min rank [{}]", minLevel, maxLevel, minRank); + LOG_DEBUG("network", "CMSG_CALENDAR_GUILD_FILTER: Min level [{}], Max level [{}], Min rank [{}]", packet.MinimumLevel, packet.MaximumLevel, packet.MinimumRank); } -void WorldSession::HandleCalendarArenaTeam(WorldPacket& recvData) +void WorldSession::HandleCalendarArenaTeam(WorldPackets::Calendar::ArenaTeam& packet) { LOG_DEBUG("network", "CMSG_CALENDAR_ARENA_TEAM [{}]", _player->GetGUID().ToString()); - uint32 arenaTeamId; - recvData >> arenaTeamId; - - if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenaTeamId)) + if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(packet.ArenaTeamId)) team->MassInviteToEvent(this); } @@ -763,14 +752,11 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket& recvData) sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_INVALID); } -void WorldSession::HandleCalendarComplain(WorldPacket& recvData) +void WorldSession::HandleCalendarComplain(WorldPackets::Calendar::CalendarComplain& packet) { ObjectGuid guid = _player->GetGUID(); - uint64 eventId; - ObjectGuid complainGUID; - recvData >> eventId >> complainGUID; - LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [{}] EventId [{}] guid [{}]", guid.ToString(), eventId, complainGUID.ToString()); + LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [{}] EventId [{}] guid [{}]", guid.ToString(), packet.EventId, packet.ComplainGuid.ToString()); // what to do with complains? } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 1bb8ac6ed2..ac7ab27834 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1164,8 +1164,11 @@ void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar) SendPacket(&data); // Xinef: fix possible problem with flag UNIT_FLAG_STUNNED added during logout - if (!pCurrChar->HasUnitState(UNIT_STATE_STUNNED)) + if (pCurrChar->HasUnitState(UNIT_STATE_LOGOUT_TIMER)) + { + pCurrChar->SetRooted(false, true, true); pCurrChar->RemoveUnitFlag(UNIT_FLAG_STUNNED); + } pCurrChar->SendInitialPacketsBeforeAddToMap(); @@ -1754,9 +1757,21 @@ void WorldSession::HandleEquipmentSetSave(WorldPacket& recvData) std::string name; recvData >> name; + if (name.length() > 16) // Client limitation + { + LOG_ERROR("entities.player.cheat", "Character GUID {} tried to create equipment set {} with too long a name!", _player->GetGUID().ToString(), setGuid); + return; + } + std::string iconName; recvData >> iconName; + if (iconName.length() > 100) // DB limitation + { + LOG_ERROR("entities.player.cheat", "Character GUID {} tried to create equipment set {} with too long an icon name!", _player->GetGUID().ToString(), setGuid); + return; + } + EquipmentSet eqSet; eqSet.Guid = setGuid; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 942eae9c54..03c91c298c 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -468,7 +468,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequ GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); } - GetPlayer()->SetRooted(true); + GetPlayer()->SetRooted(true, true, true); GetPlayer()->SetUnitFlag(UNIT_FLAG_STUNNED); } @@ -492,7 +492,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCance // not remove flags if can't free move - its not set in Logout request code. if (GetPlayer()->CanFreeMove()) { - GetPlayer()->SetRooted(false); + GetPlayer()->SetRooted(false, true, true); GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND); GetPlayer()->RemoveUnitFlag(UNIT_FLAG_STUNNED); @@ -949,12 +949,6 @@ void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recv_data*/) GetPlayer()->GetCinematicMgr()->BeginCinematic(); } -void WorldSession::HandleFeatherFallAck(WorldPacket& recv_data) -{ - // no used - recv_data.rfinish(); // prevent warnings spam -} - void WorldSession::HandleSetActionBarToggles(WorldPacket& recv_data) { uint8 ActionBar; @@ -1144,45 +1138,18 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) LOG_DEBUG("network", "Received whois command from player {} for character {}", GetPlayer()->GetName(), charname); } -void WorldSession::HandleComplainOpcode(WorldPacket& recv_data) +void WorldSession::HandleComplainOpcode(WorldPackets::Misc::Complain& packet) { LOG_DEBUG("network", "WORLD: CMSG_COMPLAIN"); - uint8 spam_type; // 0 - mail, 1 - chat - ObjectGuid spammer_guid; - uint32 unk1 = 0; - uint32 unk2 = 0; - uint32 unk3 = 0; - uint32 unk4 = 0; - std::string description = ""; - recv_data >> spam_type; // unk 0x01 const, may be spam type (mail/chat) - recv_data >> spammer_guid; // player guid - switch (spam_type) - { - case 0: - recv_data >> unk1; // const 0 - recv_data >> unk2; // probably mail id - recv_data >> unk3; // const 0 - break; - case 1: - recv_data >> unk1; // probably language - recv_data >> unk2; // message type? - recv_data >> unk3; // probably channel id - recv_data >> unk4; // unk random value - recv_data >> description; // spam description string (messagetype, channel name, player name, message) - break; - } - // NOTE: all chat messages from this spammer automatically ignored by spam reporter until logout in case chat spam. // if it's mail spam - ALL mails from this spammer automatically removed by client // Complaint Received message - WorldPacket data(SMSG_COMPLAIN_RESULT, 1); - data << uint8(0); - SendPacket(&data); + SendPacket(WorldPackets::Misc::ComplainResult().Write()); LOG_DEBUG("network", "REPORT SPAM: type {}, {}, unk1 {}, unk2 {}, unk3 {}, unk4 {}, message {}", - spam_type, spammer_guid.ToString(), unk1, unk2, unk3, unk4, description); + packet.SpamType, packet.SpammerGuid.ToString(), packet.Unk1, packet.Unk2, packet.Unk3, packet.Unk4, packet.Description); } void WorldSession::HandleRealmSplitOpcode(WorldPacket& recv_data) @@ -1519,12 +1486,13 @@ void WorldSession::HandleCancelMountAuraOpcode(WorldPacket& /*recv_data*/) _player->RemoveAurasByType(SPELL_AURA_MOUNTED); } -void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data) +void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data) { - // fly mode on/off - LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK"); + LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recv_data.GetOpcode())); ObjectGuid guid; + uint32 counter; + uint32 isApplied; recv_data >> guid.ReadAsPacked(); if (!_player) @@ -1533,17 +1501,42 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket& recv_data) return; } - recv_data.read_skip<uint32>(); // unk + recv_data >> counter; MovementInfo movementInfo; movementInfo.guid = guid; ReadMovementInfo(recv_data, &movementInfo); - recv_data.read_skip<float>(); // unk2 + recv_data >> isApplied; sScriptMgr->AnticheatSetCanFlybyServer(_player, movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY)); - _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); + Unit* mover = _player->m_mover; + Player* plrMover = mover->ToPlayer(); + + mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); + + Opcodes response; + + switch (recv_data.GetOpcode()) + { + case CMSG_MOVE_HOVER_ACK: response = MSG_MOVE_HOVER; break; + case CMSG_MOVE_FEATHER_FALL_ACK: response = MSG_MOVE_FEATHER_FALL; break; + case CMSG_MOVE_WATER_WALK_ACK: response = MSG_MOVE_WATER_WALK; break; + case CMSG_MOVE_SET_CAN_FLY_ACK: response = MSG_MOVE_UPDATE_CAN_FLY; break; + default: return; + } + + if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data)) + { + recv_data.rfinish(); // prevent warnings spam + return; + } + + WorldPacket data(response, 8); + data << guid.WriteAsPacked(); + WriteMovementInfo(&data, &movementInfo); + _player->m_mover->SendMessageToSet(&data, _player); } void WorldSession::HandleRequestPetInfo(WorldPackets::Pet::RequestPetInfo& /*packet*/) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 77b5bb43bd..6bf1b899b2 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -370,82 +370,44 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - // Stop emote on move - if (Player* plrMover = mover->ToPlayer()) + if (!ProcessMovementInfo(movementInfo, mover, plrMover, recvData)) { - if (plrMover->GetUInt32Value(UNIT_NPC_EMOTESTATE) != EMOTE_ONESHOT_NONE && movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) - { - plrMover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - } - } - - if (!movementInfo.pos.IsPositionValid()) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } - recvData.rfinish(); // prevent warnings spam return; } - if (!mover->movespline->Finalized()) - { - recvData.rfinish(); // prevent warnings spam - return; - } + /* process position-change */ + WorldPacket data(opcode, recvData.size()); + movementInfo.guid = mover->GetGUID(); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); +} - // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE - if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) +void WorldSession::SynchronizeMovement(MovementInfo& movementInfo) +{ + int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; + if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) { - // Xinef: skip moving packets - if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } - return; - } - movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ()); - - if (mover->IsCreature()) - { - movementInfo.transport.guid = mover->m_movementInfo.transport.guid; - movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ()); - movementInfo.transport.seat = mover->m_movementInfo.transport.seat; - } + LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); + movementInfo.time = getMSTime(); } - - if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + else { - // We were teleported, skip packets that were broadcast before teleport - if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - //LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport"); - } - recvData.rfinish(); // prevent warnings spam - return; - } + movementInfo.time = (uint32)movementTime; + } +} - if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), - movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) - { - if (plrMover) - { - sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); - } +void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo, Unit* mover) +{ + SynchronizeMovement(movementInfo); - recvData.rfinish(); // prevent warnings spam - return; - } + mover->UpdatePosition(movementInfo.pos); + mover->m_movementInfo = movementInfo; + if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { // if we boarded a transport, add us to it - if (plrMover) + if (Player* plrMover = mover->ToPlayer()) { if (!plrMover->GetTransport()) { @@ -483,44 +445,92 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) } } } - else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave + else if (mover->IsPlayer()) { - sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe + if (Player* plrMover = mover->ToPlayer()) + { + if (plrMover->GetTransport()) // if we were on a transport, leave + { + sScriptMgr->AnticheatSetUnderACKmount(plrMover); // just for safe - plrMover->m_transport->RemovePassenger(plrMover); - plrMover->m_transport = nullptr; - movementInfo.transport.Reset(); + plrMover->m_transport->RemovePassenger(plrMover); + plrMover->m_transport = nullptr; + movementInfo.transport.Reset(); + } + } } - // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) + // Some vehicles allow the passenger to turn by himself + if (Vehicle* vehicle = mover->GetVehicle()) { - plrMover->HandleFall(movementInfo); - - sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + { + if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation()) + { + mover->SetOrientation(movementInfo.pos.GetOrientation()); + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + } + } } - // interrupt parachutes upon falling or landing in water - if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) + if (Player* plrMover = mover->ToPlayer()) // nothing is charmed, or player charmed { - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes + if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) + plrMover->SetStandState(UNIT_STAND_STATE_STAND); - if (plrMover) + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) { - sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) + { + if (plrMover->IsAlive()) + { + plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS); + plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // player can be alive if GM + if (plrMover->IsAlive()) + plrMover->KillPlayer(); + } + else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS)) + { + GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId()); + if (grave) + { + plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation()); + plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation()); + } + } + } } } +} - if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) +bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, Player* plrMover, Unit* mover, Opcodes opcode) const +{ + if (!movementInfo.pos.IsPositionValid()) { - // now client not include swimming flag in case jumping under water - plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetMap()->IsUnderWater(plrMover->GetPhaseMask(), movementInfo.pos.GetPositionX(), - movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ(), plrMover->GetCollisionHeight())); + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + + return false; } - if (plrMover)//Hook for OnPlayerMove + if (!mover->movespline->Finalized()) + return false; + + // Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE + if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) { - sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode); + // Xinef: skip moving packets + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING)) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + return false; + } } bool jumpopcode = false; @@ -530,7 +540,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover && !sScriptMgr->AnticheatHandleDoubleJump(plrMover, mover)) { plrMover->GetSession()->KickPlayer(); - return; + return false; } } @@ -538,74 +548,104 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (plrMover && !sScriptMgr->AnticheatCheckMovementInfo(plrMover, movementInfo, mover, jumpopcode)) { plrMover->GetSession()->KickPlayer(); - return; + return false; } - /* process position-change */ - WorldPacket data(opcode, recvData.size()); - int64 movementTime = (int64)movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); + // We were teleported, skip packets that were broadcast before teleport + if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + //LOG_INFO("anticheat", "MovementHandler:: 2 We were teleported, skip packets that were broadcast before teleport"); + } + return false; + } + + if (!Acore::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), + movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) + { + if (plrMover) + { + sScriptMgr->AnticheatUpdateMovementInfo(plrMover, movementInfo); + } + + return false; + } } - else + + // rooted mover sent packet without root or moving AND root - ignore, due to client crash possibility + if (opcode != CMSG_FORCE_MOVE_UNROOT_ACK) + if (mover->IsRooted() && (!movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT) || movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_MOVING))) + return false; + + return true; +} + +bool WorldSession::ProcessMovementInfo(MovementInfo& movementInfo, Unit* mover, Player* plrMover, WorldPacket& recvData) +{ + Opcodes opcode = (Opcodes)recvData.GetOpcode(); + if (!VerifyMovementInfo(movementInfo, plrMover, mover, opcode)) + return false; + + if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) { - movementInfo.time = (uint32) movementTime; + movementInfo.pos.Relocate(mover->GetPositionX(), mover->GetPositionY(), mover->GetPositionZ()); + + if (mover->IsCreature()) + { + movementInfo.transport.guid = mover->m_movementInfo.transport.guid; + movementInfo.transport.pos.Relocate(mover->m_movementInfo.transport.pos.GetPositionX(), mover->m_movementInfo.transport.pos.GetPositionY(), mover->m_movementInfo.transport.pos.GetPositionZ()); + movementInfo.transport.seat = mover->m_movementInfo.transport.seat; + } } - movementInfo.guid = mover->GetGUID(); - WriteMovementInfo(&data, &movementInfo); - mover->SendMessageToSet(&data, _player); + // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). + if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) + { + plrMover->HandleFall(movementInfo); - mover->m_movementInfo = movementInfo; + sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); + } - // Some vehicles allow the passenger to turn by himself - if (Vehicle* vehicle = mover->GetVehicle()) + // interrupt parachutes upon falling or landing in water + if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM) { - if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes + + if (plrMover) { - if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING && movementInfo.pos.GetOrientation() != mover->GetOrientation()) - { - mover->SetOrientation(movementInfo.pos.GetOrientation()); - mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); - } + sScriptMgr->AnticheatSetJumpingbyOpcode(plrMover, false); } + } - return; + if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) + { + // now client not include swimming flag in case jumping under water + plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetMap()->IsUnderWater(plrMover->GetPhaseMask(), movementInfo.pos.GetPositionX(), + movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ(), plrMover->GetCollisionHeight())); } - mover->UpdatePosition(movementInfo.pos); + if (plrMover)//Hook for OnPlayerMove + { + sScriptMgr->OnPlayerMove(plrMover, movementInfo, opcode); + } - if (plrMover) // nothing is charmed, or player charmed + if (movementInfo.GetMovementFlags() & MOVEMENTFLAG_MASK_MOVING_OR_TURN) { - if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING))) - plrMover->SetStandState(UNIT_STAND_STATE_STAND); + if (mover->IsStandState()) + mover->SetStandState(UNIT_STAND_STATE_STAND); + mover->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + } + HandleMoverRelocation(movementInfo, mover); + + if (plrMover && opcode != CMSG_MOVE_KNOCK_BACK_ACK) plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); - if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) - if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) - { - if (plrMover->IsAlive()) - { - plrMover->SetPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS); - plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // player can be alive if GM - if (plrMover->IsAlive()) - plrMover->KillPlayer(); - } - else if (!plrMover->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS)) - { - GraveyardStruct const* grave = sGraveyard->GetClosestGraveyard(plrMover, plrMover->GetTeamId()); - if (grave) - { - plrMover->TeleportTo(grave->Map, grave->x, grave->y, grave->z, plrMover->GetOrientation()); - plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation()); - } - } - } - } + return true; } void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) @@ -762,11 +802,13 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) { LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK"); + Unit* mover = _player->m_mover; + ObjectGuid guid; recvData >> guid.ReadAsPacked(); // pussywizard: typical check for incomming movement packets - if (!_player->m_mover || !_player->m_mover->IsInWorld() || _player->m_mover->IsDuringRemoveFromWorld() || guid != _player->m_mover->GetGUID()) + if (!mover || !mover->IsInWorld() || mover->IsDuringRemoveFromWorld() || guid != mover->GetGUID()) { recvData.rfinish(); // prevent warnings spam return; @@ -778,7 +820,10 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); - _player->m_mover->m_movementInfo = movementInfo; + mover->m_movementInfo = movementInfo; + + if (mover->IsPlayer() && static_cast<Player*>(mover)->IsFreeFlying()) + mover->SetCanFly(true); WorldPacket data(MSG_MOVE_KNOCK_BACK, 66); data << guid.WriteAsPacked(); @@ -793,38 +838,6 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) _player->SendMessageToSet(&data, false); } -void WorldSession::HandleMoveHoverAck(WorldPacket& recvData) -{ - LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK"); - - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - - recvData.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - recvData.read_skip<uint32>(); // unk2 -} - -void WorldSession::HandleMoveWaterWalkAck(WorldPacket& recvData) -{ - LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK"); - - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); - - recvData.read_skip<uint32>(); // unk - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - recvData.read_skip<uint32>(); // unk2 -} - void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData) { if (!_player->IsAlive() || _player->IsInCombat()) @@ -954,79 +967,36 @@ void WorldSession::ComputeNewClockDelta() void WorldSession::HandleMoveRootAck(WorldPacket& recvData) { - ObjectGuid guid; - recvData >> guid.ReadAsPacked(); + LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recvData.GetOpcode())); - Unit* mover = _player->m_mover; - if (!mover || guid != mover->GetGUID()) - { - recvData.rfinish(); // prevent warnings spam - return; - } - - uint32 movementCounter; - recvData >> movementCounter; - - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - /* process position-change */ - int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) - { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); - } - else - { - movementInfo.time = (uint32)movementTime; - } - - movementInfo.guid = mover->GetGUID(); - mover->m_movementInfo = movementInfo; - mover->UpdatePosition(movementInfo.pos); - -} - -void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData) -{ ObjectGuid guid; + uint32 counter; + MovementInfo movementInfo; recvData >> guid.ReadAsPacked(); + recvData >> counter; + ReadMovementInfo(recvData, &movementInfo); Unit* mover = _player->m_mover; - if (!mover || guid != mover->GetGUID()) - { - recvData.rfinish(); // prevent warnings spam - return; - } - - uint32 movementCounter; - recvData >> movementCounter; - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); + if (mover->GetGUID() != guid) + return; - /* process position-change */ - int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta; - if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) + if (recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case { - LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead"); - movementInfo.time = getMSTime(); - } - else - { - movementInfo.time = (uint32)movementTime; + if (!mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT)) + return; } - - if (G3D::fuzzyEq(movementInfo.fallTime, 0.f)) + else // root case { - movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FALLING); + if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT)) + return; } - movementInfo.guid = mover->GetGUID(); - mover->m_movementInfo = movementInfo; - mover->UpdatePosition(movementInfo.pos); + if (!ProcessMovementInfo(movementInfo, mover, _player, recvData)) + return; + WorldPacket data(recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT); + data << guid.WriteAsPacked(); + WriteMovementInfo(&data, &movementInfo); + mover->SendMessageToSet(&data, _player); } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 38b66926e5..5234684c7e 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -262,8 +262,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->ToCreature()->AI()->AttackStart(TargetUnit); //10% chance to play special pet attack talk, else growl - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature @@ -297,8 +297,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe if (pet->ToPet()->getPetType() == HUNTER_PET) GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED); else + { + pet->SendPetDismissSound(); //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) pet->setDeathState(DeathState::Corpse); + } } else if (pet->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_SUMMON | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLLABLE_GUARDIAN)) { @@ -413,8 +416,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe //10% chance to play special pet attack talk, else growl //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && (pet->ToPet()->getPetType() == SUMMON_PET) && (pet != unit_target) && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -509,8 +512,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->ToCreature()->AI()->AttackStart(TargetUnit); - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(guid1); } @@ -558,8 +561,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe pet->GetMotionMaster()->MoveFollow(unit_target, PET_FOLLOW_DIST, rand_norm() * 2 * M_PI); - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -1059,8 +1062,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); + if (pet->getPetType() == SUMMON_PET && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } |