summaryrefslogtreecommitdiff
path: root/src/server/game/Handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers')
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp36
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp17
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp81
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp428
-rw-r--r--src/server/game/Handlers/PetHandler.cpp23
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);
}