Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
MovementHandler.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battleground.h"
7#include "BattlePetMgr.h"
8#include "Common.h"
9#include "Corpse.h"
10#include "InstanceSaveMgr.h"
11#include "Log.h"
12#include "MapManager.h"
13#include "MovementStructures.h"
14#include "ObjectMgr.h"
15#include "Opcodes.h"
17#include "PetTransportSupport.h"
18#include "Player.h"
19#include "SpellAuras.h"
20#include "Transport.h"
22#include "WorldPacket.h"
23#include "WorldSession.h"
24
25#define MOVEMENT_PACKET_TIME_DELAY 0
26
27namespace
28{
29struct MoveTeleportAckRequest
30{
31 ObjectGuid guid;
32 uint32 flags;
33 uint32 time;
34};
35
36struct ActiveMoverRequest
37{
38 ObjectGuid guid;
39};
40
41struct ForceSpeedChangeAckRequest
42{
43 MovementInfo movementInfo;
44 float newSpeed;
45 uint32 opcode;
46};
47
48struct SummonResponseRequest
49{
50 ObjectGuid summonerGuid;
51 bool accept;
52};
53
54MoveTeleportAckRequest ReadMoveTeleportAckRequest(WorldPacket& recvPacket)
55{
56 MoveTeleportAckRequest request;
57 recvPacket >> request.time >> request.flags;
58
59 request.guid[0] = recvPacket.ReadBit();
60 request.guid[7] = recvPacket.ReadBit();
61 request.guid[3] = recvPacket.ReadBit();
62 request.guid[5] = recvPacket.ReadBit();
63 request.guid[4] = recvPacket.ReadBit();
64 request.guid[6] = recvPacket.ReadBit();
65 request.guid[1] = recvPacket.ReadBit();
66 request.guid[2] = recvPacket.ReadBit();
67
68 recvPacket.ReadByteSeq(request.guid[4]);
69 recvPacket.ReadByteSeq(request.guid[1]);
70 recvPacket.ReadByteSeq(request.guid[6]);
71 recvPacket.ReadByteSeq(request.guid[7]);
72 recvPacket.ReadByteSeq(request.guid[0]);
73 recvPacket.ReadByteSeq(request.guid[2]);
74 recvPacket.ReadByteSeq(request.guid[5]);
75 recvPacket.ReadByteSeq(request.guid[3]);
76
77 return request;
78}
79
80MovementInfo ReadMovementInfoRequest(Player* player, WorldPacket& recvPacket)
81{
82 MovementInfo movementInfo;
83 player->ReadMovementInfo(recvPacket, &movementInfo);
84 return movementInfo;
85}
86
87ForceSpeedChangeAckRequest ReadForceSpeedChangeAckRequest(Player* player, WorldPacket& recvData)
88{
89 ForceSpeedChangeAckRequest request;
90 request.opcode = recvData.GetOpcode();
91
92 static MovementStatusElements const speedElement = MSEExtraFloat;
93 Movement::ExtraMovementStatusElement extras(&speedElement);
94 player->ReadMovementInfo(recvData, &request.movementInfo, &extras);
95 request.newSpeed = extras.Data.floatData;
96
97 return request;
98}
99
100ActiveMoverRequest ReadActiveMoverRequest(WorldPacket& recvPacket)
101{
102 ActiveMoverRequest request;
103
104 recvPacket.ReadBit();
105
106 request.guid[3] = recvPacket.ReadBit();
107 request.guid[0] = recvPacket.ReadBit();
108 request.guid[2] = recvPacket.ReadBit();
109 request.guid[1] = recvPacket.ReadBit();
110 request.guid[5] = recvPacket.ReadBit();
111 request.guid[4] = recvPacket.ReadBit();
112 request.guid[7] = recvPacket.ReadBit();
113 request.guid[6] = recvPacket.ReadBit();
114
115 recvPacket.ReadByteSeq(request.guid[3]);
116 recvPacket.ReadByteSeq(request.guid[4]);
117 recvPacket.ReadByteSeq(request.guid[5]);
118 recvPacket.ReadByteSeq(request.guid[2]);
119 recvPacket.ReadByteSeq(request.guid[7]);
120 recvPacket.ReadByteSeq(request.guid[0]);
121 recvPacket.ReadByteSeq(request.guid[1]);
122 recvPacket.ReadByteSeq(request.guid[6]);
123
124 return request;
125}
126
127MovementInfo ReadMoveHoverAckRequest(Player* player, WorldPacket& recvData)
128{
129 uint64 guid; // guid - unused
130 recvData.readPackGUID(guid);
131
132 recvData.read_skip<uint32>(); // unk
133
134 MovementInfo movementInfo;
135 player->ReadMovementInfo(recvData, &movementInfo);
136
137 recvData.read_skip<uint32>(); // unk2
138
139 return movementInfo;
140}
141
142SummonResponseRequest ReadSummonResponseRequest(WorldPacket& recvData)
143{
144 SummonResponseRequest request;
145
146 request.summonerGuid[1] = recvData.ReadBit();
147 request.summonerGuid[3] = recvData.ReadBit();
148 request.summonerGuid[5] = recvData.ReadBit();
149 request.summonerGuid[2] = recvData.ReadBit();
150 request.accept = recvData.ReadBit();
151 request.summonerGuid[7] = recvData.ReadBit();
152 request.summonerGuid[0] = recvData.ReadBit();
153 request.summonerGuid[4] = recvData.ReadBit();
154 request.summonerGuid[6] = recvData.ReadBit();
155
156 recvData.ReadByteSeq(request.summonerGuid[0]);
157 recvData.ReadByteSeq(request.summonerGuid[1]);
158 recvData.ReadByteSeq(request.summonerGuid[6]);
159 recvData.ReadByteSeq(request.summonerGuid[3]);
160 recvData.ReadByteSeq(request.summonerGuid[5]);
161 recvData.ReadByteSeq(request.summonerGuid[4]);
162 recvData.ReadByteSeq(request.summonerGuid[2]);
163 recvData.ReadByteSeq(request.summonerGuid[7]);
164
165 return request;
166}
167
168MovementInfo ReadMoveSetCanFlyAckRequest(Player* player, WorldPacket& recvData)
169{
170 return ReadMovementInfoRequest(player, recvData);
171}
172
173void ReadSetCollisionHeightAckRequest(Player* player, WorldPacket& recvPacket)
174{
175 static MovementStatusElements const heightElements[] = { MSEExtraFloat, MSEExtra2Bits };
176 Movement::ExtraMovementStatusElement extra(heightElements);
177 MovementInfo movementInfo;
178 player->ReadMovementInfo(recvPacket, &movementInfo, &extra);
179}
180
181void ReadMovementForceAckRequest(Player* player, WorldPacket& recvPacket)
182{
184 {
185 static MovementStatusElements const unkElements[] = { MSEExtraFloat, MSEExtraInt32, MSEExtraFloat };
186 Movement::ExtraMovementStatusElement extra(unkElements);
187 MovementInfo movementInfo;
188 player->ReadMovementInfo(recvPacket, &movementInfo, &extra);
189 }
190 else
191 ReadMovementInfoRequest(player, recvPacket);
192}
193
194bool ValidateMoveTeleportAck(Player* mover, ObjectGuid guid)
195{
196 return mover && mover->IsBeingTeleportedNear() && guid == mover->GetGUID();
197}
198
199bool ShouldIgnoreMovementWhileTeleporting(Player* mover, WorldPacket& recvPacket)
200{
201 if (!mover || !mover->IsBeingTeleported())
202 return false;
203
204 recvPacket.rfinish(); // prevent warnings spam
205 return true;
206}
207
208bool ValidateMovementInfo(Unit* mover, MovementInfo const& movementInfo)
209{
210 if (movementInfo.guid != mover->GetGUID())
211 {
212 SF_LOG_ERROR("network", "HandleMovementOpcodes: guid error");
213 return false;
214 }
215
216 if (!movementInfo.pos.IsPositionValid())
217 {
218 SF_LOG_ERROR("network", "HandleMovementOpcodes: Invalid Position");
219 return false;
220 }
221
222 return true;
223}
224
225bool ValidateTransportMovementInfo(WorldPacket& recvPacket, MovementInfo const& movementInfo)
226{
227 if (!movementInfo.transport.guid)
228 return true;
229
230 // transports size limited
231 // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
233 movementInfo.transport.pos.GetPositionY(), movementInfo.transport.pos.GetPositionZ(), 50.0f))
234 {
235 recvPacket.rfinish(); // prevent warnings spam
236 return false;
237 }
238
239 if (!Skyfire::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
240 movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
241 {
242 recvPacket.rfinish(); // prevent warnings spam
243 return false;
244 }
245
246 return true;
247}
248
249bool ValidateSpeedChangeAck(WorldPacket& recvData, Player* player, MovementInfo const& movementInfo)
250{
251 if (player->GetGUID() == movementInfo.guid)
252 return true;
253
254 recvData.rfinish(); // prevent warnings spam
255 return false;
256}
257
258bool ValidateActiveMoverGuid(Player* player, ObjectGuid guid)
259{
260 if (!player->IsInWorld() || player->m_mover->GetGUID() == guid)
261 return true;
262
263 SF_LOG_ERROR("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, uint64(guid), GetLogNameForGuid(guid), GUID_ENPART(guid), player->m_mover->GetGUID());
264 return false;
265}
266
267bool ValidateKnockBackAck(Unit* mover, MovementInfo const& movementInfo)
268{
269 return mover->GetGUID() == movementInfo.guid;
270}
271}
272
274{
275 SF_LOG_DEBUG("network", "WORLD: got MSG_MOVE_WORLDPORT_ACK.");
277}
278
280{
281 // ignore unexpected far teleports
282 if (!GetPlayer()->IsBeingTeleportedFar())
283 return;
284
287
288 // get the teleport destination
289 WorldLocation const& loc = GetPlayer()->GetTeleportDest();
290
291 // possible errors in the coordinate validity check
293 {
294 LogoutPlayer(false);
295 return;
296 }
297
298 // get the destination map entry, not the current one, this will fix homebind and reset greeting
299 MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
300 InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());
301
302 // reset instance validity, except if going to an instance inside an instance
303 if (GetPlayer()->m_InstanceValid == false && !mInstance)
304 GetPlayer()->m_InstanceValid = true;
305
306 Map* oldMap = GetPlayer()->GetMap();
307 Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer());
308
309 if (GetPlayer()->IsInWorld())
310 {
311 SF_LOG_ERROR("network", "Player %s (GUID: %u) is still in world when teleported from map %s (%u) to new map %s (%u)", GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID()), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId());
312 oldMap->RemovePlayerFromMap(GetPlayer(), false);
313 }
314
315 // relocate the player to the teleport destination
316 // the CanEnter checks are done in TeleporTo but conditions may change
317 // while the player is in transit, for example the map may get full
318 if (!newMap || !newMap->CanEnter(GetPlayer()))
319 {
320 SF_LOG_ERROR("network", "Map %d (%s) could not be created for player %d (%s), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str());
321 GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
322 return;
323 }
324 else
325 GetPlayer()->Relocate(&loc);
326
327 GetPlayer()->ResetMap();
328 GetPlayer()->SetMap(newMap);
329
331 if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
332 {
333 SF_LOG_ERROR("network", "WORLD: failed to teleport player %s (%d) to map %d (%s) because of unknown reason!",
334 GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
335 GetPlayer()->ResetMap();
336 GetPlayer()->SetMap(oldMap);
337 GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
338 return;
339 }
340
341 // battleground state prepare (in case join to BG), at relogin/tele player not invited
342 // only add to bg group and object, if the player was invited (else he entered through command)
343 if (_player->InBattleground())
344 {
345 // cleanup setting if outdated
346 if (!mEntry->IsBattlegroundOrArena())
347 {
348 // We're not in BG
350 // reset destination bg team
351 _player->SetBGTeam(0);
352 }
353 // join to bg case
354 else if (Battleground* bg = _player->GetBattleground())
355 {
356 if (_player->IsInvitedForBattlegroundInstance(_player->GetBattlegroundId()))
357 bg->AddPlayer(_player);
358 }
359 }
360
362
363 // flight fast teleport case
364 if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
365 {
366 if (!_player->InBattleground())
367 {
368 // short preparations to continue flight
369 FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
370 flight->Initialize(GetPlayer());
371 return;
372 }
373
374 // battleground state prepare, stop flight
377 }
378
379 // resurrect character at enter into instance where his corpse exist after add to map
380 Corpse* corpse = GetPlayer()->GetCorpse();
381 if (corpse && corpse->GetType() != CorpseType::CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId())
382 {
383 if (mEntry->IsInstance())
384 {
385 GetPlayer()->ResurrectPlayer(0.5f, false);
387 }
388 }
389
390 bool allowMount = !mEntry->IsInstance() || mEntry->IsBattlegroundOrArena();
391 if (mInstance)
392 {
393 DifficultyID diff = GetPlayer()->GetDifficulty(mEntry);
394 if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff))
395 {
396 if (mapDiff->resetTime)
397 {
398 if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff))
399 {
400 uint32 timeleft = uint32(timeReset - time(NULL));
401 GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft);
402 }
403 }
404 }
405 allowMount = mInstance->AllowMount;
406 }
407
408 // mount allow check
409 if (!allowMount)
410 _player->RemoveAurasByType(SPELL_AURA_MOUNTED);
411
412 // update zone immediately, otherwise leave channel will cause crash in mtmap
413 uint32 newzone, newarea;
414 GetPlayer()->GetZoneAndAreaId(newzone, newarea);
415 GetPlayer()->UpdateZone(newzone, newarea);
416
417 // honorless target
418 if (GetPlayer()->pvpInfo.IsHostile)
419 GetPlayer()->CastSpell(GetPlayer(), 2479, true);
420
421 // in friendly area
422 else if (GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FIELD_PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
423 GetPlayer()->UpdatePvP(false, false);
424
425 // resummon pet
427
428 // resummon battle pet
430
431 //lets process all delayed operations on successful teleport
433}
434
436{
437 SF_LOG_DEBUG("network", "CMSG_MOVE_TELEPORT_ACK");
438
439 MoveTeleportAckRequest request = ReadMoveTeleportAckRequest(recvPacket);
440 ObjectGuid guid = request.guid;
441 uint32 flags = request.flags;
442 uint32 time = request.time;
443
444 SF_LOG_DEBUG("network", "Guid " UI64FMTD, uint64(guid));
445 SF_LOG_DEBUG("network", "Flags %u, time %u", flags, time / IN_MILLISECONDS);
446
447 Player* plMover = _player->m_mover->ToPlayer();
448
449 if (!ValidateMoveTeleportAck(plMover, guid))
450 return;
451
452 plMover->SetSemaphoreTeleportNear(false);
453
454 uint32 old_zone = plMover->GetZoneId();
455
456 WorldLocation const& dest = plMover->GetTeleportDest();
457
458 plMover->UpdatePosition(dest, true);
459
460 uint32 newzone, newarea;
461 plMover->GetZoneAndAreaId(newzone, newarea);
462 plMover->UpdateZone(newzone, newarea);
463
464 // new zone
465 if (old_zone != newzone)
466 {
467 // honorless target
468 if (plMover->pvpInfo.IsHostile)
469 plMover->CastSpell(plMover, 2479, true);
470
471 // in friendly area
472 else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FIELD_PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
473 plMover->UpdatePvP(false, false);
474 }
475
476 // resummon pet
478
479 // resummon battle pet
481
482 //lets process all delayed operations on successful teleport
484}
485
487{
488 uint16 opcode = recvPacket.GetOpcode();
489
490 Unit* mover = _player->m_mover;
491
492 ASSERT(mover != NULL); // there must always be a mover
493
494 Player* plrMover = mover->ToPlayer();
495
496 if (plrMover && plrMover->IsInCinematic())
497 return;
498
499 // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
500 if (ShouldIgnoreMovementWhileTeleporting(plrMover, recvPacket))
501 return;
502
503 /* extract packet */
504 MovementInfo movementInfo = ReadMovementInfoRequest(GetPlayer(), recvPacket);
505
506 // prevent tampered movement data
507 if (!ValidateMovementInfo(mover, movementInfo))
508 return;
509
510 Transport* pendingPetTransportRemoval = NULL;
511
512 /* handle special cases */
513 if (movementInfo.transport.guid)
514 {
515 if (!ValidateTransportMovementInfo(recvPacket, movementInfo))
516 return;
517
518 // if we boarded a transport, add us to it
519 if (plrMover)
520 {
521 if (!plrMover->GetTransport())
522 {
523 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
524 {
525 plrMover->m_transport = transport;
526 transport->AddPassenger(plrMover);
527 }
528 }
529 else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
530 {
531 bool foundNewTransport = false;
532 Transport* oldTransport = plrMover->m_transport;
533 oldTransport->RemovePassenger(plrMover);
534 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
535 {
536 foundNewTransport = true;
537 plrMover->m_transport = transport;
538 transport->AddPassenger(plrMover);
539 }
540
541 if (!foundNewTransport)
542 {
543 plrMover->m_transport = NULL;
544 movementInfo.ResetTransport();
545 pendingPetTransportRemoval = oldTransport;
546 }
547 }
548 }
549
550 if (!mover->GetTransport() && !mover->GetVehicle())
551 {
552 GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
553 if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
554 movementInfo.transport.guid = 0;
555 }
556 }
557 else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
558 {
559 pendingPetTransportRemoval = plrMover->m_transport;
560 plrMover->m_transport->RemovePassenger(plrMover);
561 plrMover->m_transport = NULL;
562 movementInfo.ResetTransport();
563 }
564
565 // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
566 if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
567 plrMover->HandleFall(movementInfo);
568
569 if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
570 {
571 // now client not include swimming flag in case jumping under water
572 plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
573 }
574
575 uint32 mstime = getMSTime();
576 /*----------------------*/
577 if (m_clientTimeDelay == 0)
578 m_clientTimeDelay = mstime - movementInfo.time;
579
580 /* process position-change */
581 movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
582
583 movementInfo.guid = mover->GetGUID();
584 mover->m_movementInfo = movementInfo;
585
586 if (plrMover && plrMover->GetTransport())
588
589 /*----------------------*/
590 /* process position-change */
591 // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle()
592 if (mover->GetVehicle())
593 {
594 mover->SetOrientation(movementInfo.pos.GetOrientation());
595 return;
596 }
597
598 if (Transport* transport = mover->GetTransport())
599 {
600 movementInfo.pos.Relocate(movementInfo.transport.pos);
601 transport->CalculatePassengerPosition(
602 movementInfo.pos.m_positionX,
603 movementInfo.pos.m_positionY,
604 movementInfo.pos.m_positionZ,
605 &movementInfo.pos.m_orientation);
606 }
607
608 mover->UpdatePosition(movementInfo.pos);
609
610 if (plrMover && pendingPetTransportRemoval)
611 Skyfire::PetTransport::RemoveOwnerHunterPet(plrMover, pendingPetTransportRemoval);
612
613 if (plrMover && plrMover->GetTransport())
615
617 {
619 }
620
621 WorldPacket data(SMSG_PLAYER_MOVE, recvPacket.size());
622 mover->WriteMovementInfo(data);
623 mover->SendMessageToSet(&data, _player);
624
625 if (plrMover) // nothing is charmed, or player charmed
626 {
627 plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
628
629 AreaTableEntry const* zone = GetAreaEntryByAreaID(plrMover->GetAreaId());
630 float depth = zone ? zone->m_MinElevation : -500.0f;
631 if (movementInfo.pos.GetPositionZ() < depth)
632 {
633 if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
634 {
635 // NOTE: this is actually called many times while falling
636 // even after the player has been teleported away
638 if (plrMover->IsAlive())
639 {
640 plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
641 // player can be alive if GM/etc
642 // change the death state to CORPSE to prevent the death timer from
643 // starting in the next player update
644 if (!plrMover->IsAlive())
645 plrMover->KillPlayer();
646 }
647 }
648 }
649 }
650}
651
653{
654 /* extract packet */
655 ForceSpeedChangeAckRequest request = ReadForceSpeedChangeAckRequest(GetPlayer(), recvData);
656 MovementInfo const& movementInfo = request.movementInfo;
657 uint32 opcode = request.opcode;
658
659 // now can skip not our packet
660 if (!ValidateSpeedChangeAck(recvData, _player, movementInfo))
661 return;
662
663 float newspeed = request.newSpeed;
664 /*----------------*/
665
666 // client ACK send one packet for mounted/run case and need skip all except last from its
667 // in other cases anti-cheat check can be fail in false case
668 UnitMoveType move_type;
669
670 static char const* const move_type_name[MAX_MOVE_TYPE] =
671 {
672 "Walk",
673 "Run",
674 "RunBack",
675 "Swim",
676 "SwimBack",
677 "TurnRate",
678 "Flight",
679 "FlightBack",
680 "PitchRate"
681 };
682
683 switch (opcode)
684 {
685 case CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
686 case CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
688 case CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
694 default:
695 SF_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
696 return;
697 }
698
699 // skip all forced speed changes except last and unexpected
700 // in run/mounted case used one ACK and it must be skipped. m_forced_speed_changes[MOVE_RUN] store both.
701 if (_player->m_forced_speed_changes[move_type] > 0)
702 {
703 --_player->m_forced_speed_changes[move_type];
704 if (_player->m_forced_speed_changes[move_type] > 0)
705 return;
706 }
707
708 if (!_player->GetTransport() && fabs(_player->GetSpeed(move_type) - newspeed) > 0.01f)
709 {
710 if (_player->GetSpeed(move_type) > newspeed) // must be greater - just correct
711 {
712 SF_LOG_ERROR("network", "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value",
713 move_type_name[move_type], _player->GetName().c_str(), _player->GetSpeed(move_type), newspeed);
714 _player->SetSpeed(move_type, _player->GetSpeedRate(move_type), true);
715 }
716 else // must be lesser - cheating
717 {
718 SF_LOG_DEBUG("misc", "Player %s from account id %u kicked for incorrect speed (must be %f instead %f)",
719 _player->GetName().c_str(), _player->GetSession()->GetAccountId(), _player->GetSpeed(move_type), newspeed);
720 _player->GetSession()->KickPlayer();
721 }
722 }
723}
724
726{
727 SF_LOG_DEBUG("network", "WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
728
729 ActiveMoverRequest request = ReadActiveMoverRequest(recvPacket);
730 ObjectGuid guid = request.guid;
731
732 ValidateActiveMoverGuid(_player, guid);
733}
734
736{
737 SF_LOG_DEBUG("network", "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
738
739 MovementInfo mi = ReadMovementInfoRequest(GetPlayer(), recvData);
740 _player->m_movementInfo = mi;
741}
742
744{
745 ObjectGuid guid = GetPlayer()->GetGUID();
746
748
749 data.WriteGuidMask(guid, 5, 7, 0, 3, 2, 1, 4, 6);
750 data.WriteGuidBytes(guid, 7, 2, 0, 4, 5, 6, 1, 3);
751
752 GetPlayer()->SendMessageToSet(&data, false);
753}
754
756{
757 SF_LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK");
758
759 MovementInfo movementInfo = ReadMovementInfoRequest(GetPlayer(), recvData);
760
761 if (!ValidateKnockBackAck(_player->m_mover, movementInfo))
762 return;
763
764 _player->m_movementInfo = movementInfo;
765
767 _player->WriteMovementInfo(data);
768 _player->SendMessageToSet(&data, false);
769}
770
772{
773 SF_LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK");
774
775 ReadMoveHoverAckRequest(GetPlayer(), recvData);
776}
777
779{
780 SF_LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK");
781
782 ReadMovementInfoRequest(GetPlayer(), recvData);
783
784 // Temp disable until I get home to check the structure
785 /*uint64 guid; // guid - unused
786 recvData.readPackGUID(guid);
787
788 recvData.read_skip<uint32>(); // unk
789
790 MovementInfo movementInfo;
791 GetPlayer()->ReadMovementInfo(recvData, &movementInfo);
792
793 recvData.read_skip<uint32>(); // unk2
794 */
795}
796
798{
799 if (!_player->IsAlive() || _player->IsInCombat())
800 return;
801
802 SummonResponseRequest request = ReadSummonResponseRequest(recvData);
803
804 _player->SummonIfPossible(request.accept);
805}
806
807
809{
810 // fly mode on/off
811 SF_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
812
813 MovementInfo movementInfo = ReadMoveSetCanFlyAckRequest(GetPlayer(), recvData);
814
815 _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
816}
817
819{
820 SF_LOG_DEBUG("network", "CMSG_MOVE_SET_COLLISION_HEIGHT_ACK");
821
822 ReadSetCollisionHeightAckRequest(GetPlayer(), recvPacket);
823}
824
826{
827 SF_LOG_DEBUG("network", "%s", recvPacket.GetOpcode() == CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK ? "CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK" : "CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK");
828
829 ReadMovementForceAckRequest(GetPlayer(), recvPacket);
830}
831
833{
834 SF_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_TURN_WHILE_FALLING_ACK");
835
836 recvData.rfinish();
837}
@ IN_MILLISECONDS
Definition Common.h:125
@ CORPSE_BONES
Definition Corpse.h:16
DifficultyID
Definition DBCEnums.h:330
MapDifficulty const * GetMapDifficultyData(uint32 mapId, DifficultyID difficulty)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
AreaTableEntry const * GetAreaEntryByAreaID(uint32 area_id)
#define UI64FMTD
Definition Define.h:64
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
#define ASSERT
Definition Errors.h:29
#define sInstanceSaveMgr
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define sMapMgr
Definition MapManager.h:145
@ FLIGHT_MOTION_TYPE
#define MOVEMENT_PACKET_TIME_DELAY
MovementStatusElements
@ MSEExtraInt32
@ MSEExtraFloat
@ MSEExtra2Bits
uint32 GUID_LOPART(uint64 x)
char const * GetLogNameForGuid(uint64 guid)
uint32 GUID_ENPART(uint64 x)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ DAMAGE_FALL_TO_VOID
Definition Player.h:845
@ PLAYER_FLAGS_IN_PVP
Definition Player.h:546
@ GAMEOBJECT_TYPE_TRANSPORT
@ SPELL_AURA_MOUNTED
uint32 getMSTime()
Definition Timer.h:12
@ MOVEMENTFLAG_SWIMMING
Definition Unit.h:743
#define MAX_MOVE_TYPE
Definition Unit.h:566
UnitMoveType
Definition Unit.h:554
@ MOVE_FLIGHT
Definition Unit.h:561
@ MOVE_SWIM
Definition Unit.h:558
@ MOVE_TURN_RATE
Definition Unit.h:560
@ MOVE_FLIGHT_BACK
Definition Unit.h:562
@ MOVE_SWIM_BACK
Definition Unit.h:559
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_PITCH_RATE
Definition Unit.h:563
@ MOVE_RUN_BACK
Definition Unit.h:557
@ MOVE_WALK
Definition Unit.h:555
@ UNIT_FIELD_NPC_EMOTESTATE
@ PLAYER_FIELD_PLAYER_FLAGS
void ResummonLastBattlePet()
virtual bool HandlePlayerUnderMap(Player *)
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
void read_skip()
Definition ByteBuffer.h:502
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
void ReadByteSeq(uint8 &b)
Definition ByteBuffer.h:215
void rfinish()
Definition ByteBuffer.h:478
size_t size() const
Definition ByteBuffer.h:609
void readPackGUID(uint64 &guid)
Definition ByteBuffer.h:541
bool ReadBit()
Definition ByteBuffer.h:180
CorpseType GetType() const
Definition Corpse.h:58
GameobjectTypes GetGoType() const
Definition GameObject.h:719
Definition Map.h:238
virtual void RemovePlayerFromMap(Player *, bool)
Definition Map.cpp:808
Transport * GetTransport(uint64 guid)
Definition Map.cpp:3189
GameObject * GetGameObject(uint64 guid)
Definition Map.cpp:3184
bool IsUnderWater(float x, float y, float z) const
Definition Map.cpp:2263
virtual bool CanEnter(Player *)
Definition Map.h:359
const char * GetMapName() const
Definition Map.cpp:2285
uint32 GetId(void) const
Definition Map.h:300
static bool IsValidMapCoord(uint32 mapid, float x, float y)
Definition MapManager.h:75
void MovementExpired(bool reset=true)
struct Movement::ExtraMovementStatusElement::@223034106340337246130275244156275117357303062005 Data
uint64 GetGUID() const
Definition Object.h:119
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:325
Player * ToPlayer()
Definition Object.h:204
bool IsInWorld() const
Definition Object.h:114
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void SetSemaphoreTeleportNear(bool semphsetting)
Definition Player.h:2505
void SendInitialPacketsAfterAddToMap()
Definition Player.cpp:18646
bool m_InstanceValid
Definition Player.h:2922
WorldLocation & GetTeleportDest()
Definition Player.h:2489
void HandleFall(MovementInfo const &movementInfo)
Definition Player.cpp:20949
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
Definition Player.cpp:1115
void KillPlayer()
Definition Player.cpp:5284
void SetInWater(bool apply)
Definition Player.cpp:2926
void ReadMovementInfo(WorldPacket &data, MovementInfo *mi, Movement::ExtraMovementStatusElement *extras=NULL)
Definition Player.cpp:22773
BattlePetMgr * GetBattlePetMgr()
Definition Player.h:2573
Unit * m_mover
Definition Player.h:2807
bool IsInWater() const override
Definition Player.h:1319
void UpdateZone(uint32 newZone, uint32 newArea)
Definition Player.cpp:8126
void SendInitialPacketsBeforeAddToMap()
Definition Player.cpp:18521
void ResetMap() override
Definition Player.cpp:21643
DifficultyID GetDifficulty(MapEntry const *mapEntry) const
Definition Player.cpp:20762
void UpdateFallInformationIfNeed(MovementInfo const &minfo, uint16 opcode)
Definition Player.cpp:21107
void SetSemaphoreTeleportFar(bool semphsetting)
Definition Player.h:2509
Corpse * GetCorpse() const
Definition Player.cpp:5385
Battleground * GetBattleground() const
Definition Player.cpp:19212
void ProcessDelayedOperations()
Definition Player.cpp:2352
bool UpdatePosition(float x, float y, float z, float orientation, bool teleport=false) override
Definition Player.cpp:6843
void SpawnCorpseBones()
Definition Player.cpp:5378
PvPInfo pvpInfo
Definition Player.h:2233
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
bool IsBeingTeleportedNear() const
Definition Player.h:2497
void SetSemaphoreTeleportForcedFar(bool semphsetting)
Definition Player.h:2521
void SendMessageToSet(WorldPacket *data, bool self) override
Definition Player.h:2443
void SetMap(Map *map) override
Definition Player.cpp:21655
bool IsInCinematic() const
Definition Player.h:2907
void ResummonPetTemporaryUnSummonedIfAny()
Definition Player.cpp:21128
void UpdatePvP(bool state, bool override=false)
Definition Player.cpp:17484
void CleanupAfterTaxiFlight()
Definition Player.cpp:16748
void SendInstanceResetWarning(uint32 mapid, DifficultyID difficulty, uint32 time)
Definition Player.cpp:18727
bool IsBeingTeleported() const
Definition Player.h:2493
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:5203
void RemovePassenger(WorldObject *passenger)
void AddPassenger(WorldObject *passenger)
Definition Unit.h:1367
Vehicle * GetVehicle() const
Definition Unit.h:2743
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void WriteMovementInfo(WorldPacket &data, Movement::ExtraMovementStatusElement *extras=NULL)
Definition Unit.cpp:8407
bool IsPvP() const
Definition Unit.h:1716
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool IsAlive() const
Definition Unit.h:2032
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition Unit.cpp:8701
bool IsInFlight() const
Definition Unit.h:1891
uint32 GetMapId() const
Definition Object.h:546
Map * GetMap() const
Definition Object.h:740
Transport * GetTransport() const
Definition Object.h:797
Map const * GetBaseMap() const
Definition Object.cpp:2544
uint32 GetAreaId() const
Definition Object.cpp:1602
uint32 GetZoneId() const
Definition Object.cpp:1597
MovementInfo m_movementInfo
Definition Object.h:807
virtual void SendMessageToSet(WorldPacket *data, bool self)
Definition Object.cpp:2485
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.cpp:1607
Transport * m_transport
Definition Object.h:821
Opcodes GetOpcode() const
Definition WorldPacket.h:38
void HandleMountSpecialAnimOpcode(WorldPacket &recvdata)
void LogoutPlayer(bool save)
Log the player out
void HandleMoveTeleportAck(WorldPacket &recvPacket)
void HandleMovementForceAck(WorldPacket &recvPacket)
void HandleMoveHoverAck(WorldPacket &recvData)
uint32 m_clientTimeDelay
void HandleSetCollisionHeightAck(WorldPacket &recvPacket)
void HandleSummonResponseOpcode(WorldPacket &recvData)
void HandleMovementOpcodes(WorldPacket &recvPacket)
Player * GetPlayer() const
void HandleForceSpeedChangeAck(WorldPacket &recvData)
void HandleMoveWorldportAckOpcode()
void HandleMoveSetCanTurnWhileFallingAck(WorldPacket &recvData)
void HandleMoveWaterWalkAck(WorldPacket &recvPacket)
Player * _player
void HandleMoveSetCanFlyAckOpcode(WorldPacket &recvData)
void HandleMoveNotActiveMover(WorldPacket &recvData)
void HandleSetActiveMoverOpcode(WorldPacket &recvData)
void HandleMoveKnockBackAck(WorldPacket &recvPacket)
@ CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK
Definition Opcodes.h:298
@ CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK
Definition Opcodes.h:288
@ CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK
Definition Opcodes.h:299
@ SMSG_MOUNTSPECIAL_ANIM
Definition Opcodes.h:786
@ CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK
Definition Opcodes.h:300
@ CMSG_MOVE_FORCE_FLIGHT_SPEED_CHANGE_ACK
Definition Opcodes.h:293
@ CMSG_MOVE_FORCE_RUN_SPEED_CHANGE_ACK
Definition Opcodes.h:296
@ CMSG_MOVE_FORCE_RUN_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:295
@ CMSG_MOVE_FORCE_SWIM_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:297
@ MSG_MOVE_FALL_LAND
Definition Opcodes.h:476
@ CMSG_MOVE_FORCE_PITCH_RATE_CHANGE_ACK
Definition Opcodes.h:294
@ SMSG_MOVE_UPDATE_KNOCK_BACK
Definition Opcodes.h:822
@ SMSG_PLAYER_MOVE
Definition Opcodes.h:878
@ CMSG_MOVE_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:292
bool BoardOwnerHunterPet(Player *owner, Transport *transport)
void RemoveOwnerHunterPet(Player *owner, Transport *transport)
bool IsPassengerOffsetWithinLimit(float x, float y, float z, float limit)
bool IsValidMapCoord(float c)
float m_MinElevation
bool AllowMount
Definition Map.h:221
bool IsInstance() const
uint32 MapID
bool IsBattlegroundOrArena() const
void ResetTransport()
Definition Object.h:518
uint64 guid
Definition Object.h:449
uint32 time
Definition Object.h:453
uint32 flags
Definition Object.h:450
struct MovementInfo::TransportInfo transport
uint32 GetMovementFlags() const
Definition Object.h:504
Position pos
Definition Object.h:452
float m_positionZ
Definition Object.h:289
float m_positionX
Definition Object.h:287
float GetPositionZ() const
Definition Object.h:330
float m_positionY
Definition Object.h:288
float GetOrientation() const
Definition Object.h:331
bool IsPositionValid() const
Definition Object.cpp:2049
void SetOrientation(float orientation)
Definition Object.h:323
float m_orientation
Definition Object.h:292
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
void Relocate(float x, float y)
Definition Object.h:302
bool IsHostile
Definition Player.h:446