TrinityCore
Loading...
Searching...
No Matches
MovementHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Battleground.h"
19#include "Common.h"
20#include "Corpse.h"
21#include "GameTime.h"
22#include "GameClient.h"
23#include "InstanceSaveMgr.h"
24#include "Log.h"
25#include "MapManager.h"
26#include "MotionMaster.h"
27#include "MovementGenerator.h"
28#include "MovementPackets.h"
30#include "MoveSpline.h"
31#include "ObjectAccessor.h"
32#include "ObjectMgr.h"
33#include "Opcodes.h"
34#include "Player.h"
35#include "Transport.h"
36#include "Vehicle.h"
37#include "World.h"
38#include "WorldPacket.h"
39#include "WorldSession.h"
40#include <boost/accumulators/statistics/variance.hpp>
41#include <boost/accumulators/accumulators.hpp>
42#include <boost/accumulators/statistics.hpp>
43#include <boost/circular_buffer.hpp>
44
46{
49 #ifdef TRINITY_DEBUG
50 #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) do \
51 { \
52 if (check) \
53 { \
54 TC_LOG_DEBUG("entities.unit", "WorldSession::ReadMovementInfo: Violation of MovementFlags found \"{}\". " \
55 "MovementFlags: {}, MovementFlags2: {} for player {}. Mask {} will be removed.", \
56 STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUID(), maskToRemove); \
57 mi->RemoveMovementFlag((maskToRemove)); \
58 } \
59 } while(0)
60 #else
61 #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) do \
62 { \
63 if (check) \
64 mi->RemoveMovementFlag((maskToRemove)); \
65 } while (0)
66 #endif
67
68 if (!mover)
69 return false;
70
71 if (!mi->pos.IsPositionValid())
72 return false;
73
74 if (!GetPlayer()->GetVehicleBase() || !(GetPlayer()->GetVehicle()->GetVehicleInfo()->Flags & VEHICLE_FLAG_FIXED_POSITION))
76
83
87
91
95
99
103
107
113
117
125 !mover->HasAuraType(SPELL_AURA_FLY) &&
128
132
135
136 #undef REMOVE_VIOLATING_FLAGS
137
138 return true;
139}
140
142{
143 GameClient* client = GetGameClient();
144
145 // the client is attempting to tamper movement data
146 // edit: this wouldn't happen in retail but it does in TC, even with a legitimate client.
147 Unit* activelyMovedUnit = client->GetActivelyMovedUnit();
148 if (!forStatusAck && (!activelyMovedUnit || activelyMovedUnit->GetGUID() != guid))
149 {
150 TC_LOG_DEBUG("entities.unit", "Attempt at tampering movement data by Player {}", _player->GetName());
151 return nullptr;
152 }
153
154 // This can happen if a legitimate client has lost control of a unit but hasn't received SMSG_CONTROL_UPDATE before
155 // sending this packet yet. The server should silently ignore all MOVE messages coming from the client as soon
156 // as control over that unit is revoked (through a 'SMSG_CONTROL_UPDATE allowMove=false' message).
157 if (!client->IsAllowedToMove(guid))
158 {
159 TC_LOG_DEBUG("entities.unit", "Bad or outdated movement data by Player {}", _player->GetName());
160 return nullptr;
161 }
162
163 if (activelyMovedUnit && activelyMovedUnit->GetGUID() == guid)
164 return activelyMovedUnit;
165
166 if (_player->GetGUID() == guid)
167 return _player;
168
169 return ObjectAccessor::GetUnit(*_player, guid);
170}
171
173{
174 int64 movementTime = int64(time) + _timeSyncClockDelta;
175 if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > SI64LIT(0xFFFFFFFF))
176 {
177 TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
179 }
180 else
181 return uint32(movementTime);
182}
183
185{
186 TC_LOG_DEBUG("network", "WORLD: got MSG_MOVE_WORLDPORT_ACK.");
188}
189
191{
192 Player* player = GetPlayer();
193 // ignore unexpected far teleports
194 if (!player->IsBeingTeleportedFar())
195 return;
196
197 player->SetSemaphoreTeleportFar(false);
198
199 // get the teleport destination
200 WorldLocation const& loc = player->GetTeleportDest();
201
202 // possible errors in the coordinate validity check
204 {
205 LogoutPlayer(false);
206 return;
207 }
208
209 // get the destination map entry, not the current one, this will fix homebind and reset greeting
210 MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
211 InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());
212
213 // reset instance validity, except if going to an instance inside an instance
214 if (player->m_InstanceValid == false && !mInstance)
215 player->m_InstanceValid = true;
216
217 Map* oldMap = player->GetMap();
218 Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), player);
219
220 if (player->IsInWorld())
221 {
222 TC_LOG_ERROR("network", "{} {} is still in world when teleported from map {} ({}) to new map {} ({})", player->GetGUID().ToString(), player->GetName(), oldMap->GetMapName(), oldMap->GetId(), newMap ? newMap->GetMapName() : "Unknown", loc.GetMapId());
223 oldMap->RemovePlayerFromMap(player, false);
224 }
225
226 // relocate the player to the teleport destination
227 // the CannotEnter checks are done in TeleporTo but conditions may change
228 // while the player is in transit, for example the map may get full
229 if (!newMap || newMap->CannotEnter(player))
230 {
231 TC_LOG_ERROR("network", "Map {} ({}) could not be created for player {} ({}), porting player to homebind", loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown", player->GetGUID().ToString(), player->GetName());
232 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
233 return;
234 }
235
236 float z = loc.GetPositionZ() + player->GetHoverOffset();
237 player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
238 player->SetFallInformation(0, player->GetPositionZ());
239
240 player->ResetMap();
241 player->SetMap(newMap);
242
244 if (!player->GetMap()->AddPlayerToMap(player))
245 {
246 TC_LOG_ERROR("network", "WORLD: failed to teleport player {} {} to map {} ({}) because of unknown reason!",
247 player->GetName(), player->GetGUID().ToString(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
248 player->ResetMap();
249 player->SetMap(oldMap);
250 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
251 return;
252 }
253
254 // battleground state prepare (in case join to BG), at relogin/tele player not invited
255 // only add to bg group and object, if the player was invited (else he entered through command)
256 if (player->InBattleground())
257 {
258 // cleanup setting if outdated
259 if (!mEntry->IsBattlegroundOrArena())
260 {
261 // We're not in BG
263 // reset destination bg team
264 player->SetBGTeam(0);
265 }
266 // join to bg case
267 else if (Battleground* bg = player->GetBattleground())
268 {
270 bg->AddPlayer(player);
271 }
272 }
273
275
276 // flight fast teleport case
277 if (player->IsInFlight())
278 {
279 if (!player->InBattleground())
280 {
281 // short preparations to continue flight
282 MovementGenerator* movementGenerator = player->GetMotionMaster()->GetCurrentMovementGenerator();
283 movementGenerator->Initialize(player);
284 return;
285 }
286
287 // battleground state prepare, stop flight
288 player->FinishTaxiFlight();
289 }
290
291 if (!player->IsAlive() && player->GetTeleportOptions() & TELE_REVIVE_AT_TELEPORT)
292 player->ResurrectPlayer(0.5f);
293
294 // resurrect character at enter into instance where his corpse exist after add to map
295 if (mEntry->IsDungeon() && !player->IsAlive())
296 {
297 if (player->GetCorpseLocation().GetMapId() == mEntry->ID)
298 {
299 player->ResurrectPlayer(0.5f);
300 player->SpawnCorpseBones();
301 }
302 }
303
304 bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena();
305 if (mInstance)
306 {
307 // check if this instance has a reset time and send it to player if so
308 Difficulty diff = player->GetDifficulty(mEntry->IsRaid());
309 if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->ID, diff))
310 {
311 if (mapDiff->resetTime)
312 {
313 if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->ID, diff))
314 {
315 uint32 timeleft = uint32(timeReset - GameTime::GetGameTime());
316 player->SendInstanceResetWarning(mEntry->ID, diff, timeleft, true);
317 }
318 }
319 }
320
321 // check if instance is valid
322 if (!player->CheckInstanceValidity(false))
323 player->m_InstanceValid = false;
324
325 // instance mounting is handled in InstanceTemplate
326 allowMount = mInstance->AllowMount;
327 }
328
329 // mount allow check
330 if (!allowMount)
332
333 // update zone immediately, otherwise leave channel will cause crash in mtmap
334 uint32 newzone, newarea;
335 player->GetZoneAndAreaId(newzone, newarea);
336 player->UpdateZone(newzone, newarea);
337
338 // honorless target
339 if (player->pvpInfo.IsHostile)
340 player->CastSpell(player, 2479, true);
341
342 // in friendly area
343 else if (player->IsPvP() && !player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
344 player->UpdatePvP(false, false);
345
346 // resummon pet
348
349 //lets process all delayed operations on successful teleport
350 player->ProcessDelayedOperations();
351}
352
354{
355 TC_LOG_DEBUG("network", "MSG_MOVE_TELEPORT_ACK");
356 ObjectGuid guid;
357
358 recvPacket >> guid.ReadAsPacked();
359
360 Unit* mover = ValidateAndGetUnitBeingMoved(guid, false);
361 if (!mover)
362 {
363 recvPacket.rfinish(); // prevent warnings spam
364 return;
365 }
366
367 uint32 sequenceIndex, time;
368 recvPacket >> sequenceIndex >> time;
369
370 Player* plMover = mover->ToPlayer();
371
372 if (!plMover || !plMover->IsBeingTeleportedNear())
373 return;
374
375 plMover->SetSemaphoreTeleportNear(false);
376
377 uint32 old_zone = plMover->GetZoneId();
378
379 WorldLocation const& dest = plMover->GetTeleportDest();
380
381 plMover->UpdatePosition(dest, true);
382 plMover->SetFallInformation(0, GetPlayer()->GetPositionZ());
383
384 uint32 newzone, newarea;
385 plMover->GetZoneAndAreaId(newzone, newarea);
386 plMover->UpdateZone(newzone, newarea);
387
388 // new zone
389 if (old_zone != newzone)
390 {
391 // honorless target
392 if (plMover->pvpInfo.IsHostile)
393 plMover->CastSpell(plMover, 2479, true);
394
395 // in friendly area
396 else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
397 plMover->UpdatePvP(false, false);
398 }
399
400 // resummon pet
402
403 //lets process all delayed operations on successful teleport
405}
406
411
413{
414 Unit* mover = ValidateAndGetUnitBeingMoved(movementInfo.guid, false);
415 if (!ValidateMovementInfo(mover, &movementInfo))
416 return;
417
418 Player* plrMover = mover->ToPlayer();
419
420 // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
421 if (plrMover && plrMover->IsBeingTeleported())
422 return;
423
424 if (!mover->movespline->Finalized())
425 return;
426
427 // stop some emotes at player move
428 if (plrMover && (plrMover->GetEmoteState() != 0))
430
431 /* handle special cases */
433 {
434 // We were teleported, skip packets that were broadcast before teleport
435 if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
436 return;
437
438 // transports size limited
439 // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
440 if (fabs(movementInfo.transport.pos.GetPositionX()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionY()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionZ()) > 75.0f)
441 return;
442
443 if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
444 movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
445 return;
446
447 // if we boarded a transport, add us to it
448 if (plrMover)
449 {
450 if (!plrMover->GetTransport())
451 {
452 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
453 transport->AddPassenger(plrMover);
454 }
455 else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
456 {
457 plrMover->GetTransport()->RemovePassenger(plrMover);
458 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
459 transport->AddPassenger(plrMover);
460 else
461 movementInfo.transport.Reset();
462 }
463 }
464
465 if (!mover->GetTransport() && !mover->GetVehicle())
466 {
467 GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
468 if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
470 }
471 }
472 else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
473 {
474 plrMover->GetTransport()->RemovePassenger(plrMover);
475 movementInfo.transport.Reset();
476 }
477
478 // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
479 if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
480 plrMover->HandleFall(movementInfo);
481
482 // interrupt parachutes upon falling or landing in water
483 if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM)
485
486 /* process position-change */
487 movementInfo.guid = mover->GetGUID();
488 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
489 mover->m_movementInfo = movementInfo;
490
491 WorldPackets::Movement::MoveUpdate moveUpdate(opcode);
492 moveUpdate.Status = &mover->m_movementInfo;
493 mover->SendMessageToSet(moveUpdate.Write(), _player);
494
495 // Some vehicles allow the passenger to turn by himself
496 if (Vehicle* vehicle = mover->GetVehicle())
497 {
498 if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
499 {
500 if (seat->Flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)
501 {
502 if (movementInfo.pos.GetOrientation() != mover->GetOrientation())
503 {
504 mover->SetOrientation(movementInfo.pos.GetOrientation());
506 }
507 }
508 }
509 return;
510 }
511
512 mover->UpdatePosition(movementInfo.pos);
513
514 if (plrMover) // nothing is charmed, or player charmed
515 {
516 if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
518
519 plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
520
521 if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
522 {
523 if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(plrMover)))
524 {
525 // NOTE: this is actually called many times while falling
526 // even after the player has been teleported away
528 if (plrMover->IsAlive())
529 {
530 TC_LOG_DEBUG("entities.player.falldamage", "FALLDAMAGE Below map. Map min height: {} , Player debug info:\n{}", plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()), plrMover->GetDebugInfo());
532 plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
533 // player can be alive if GM/etc
534 // change the death state to CORPSE to prevent the death timer from
535 // starting in the next player update
536 if (plrMover->IsAlive())
537 plrMover->KillPlayer();
538 }
539 }
540 }
541 else
543
544 // Whenever a player stops a movement action, an indoor/outdoor check is being performed
545 switch (opcode)
546 {
549 case MSG_MOVE_STOP:
556 break;
557 default:
558 break;
559 }
560 }
561}
562
564{
565 /* extract packet */
566 ObjectGuid guid;
567 recvData >> guid.ReadAsPacked();
568
569 GameClient* client = GetGameClient();
570
571 // ACK handlers should call GameClient::IsAllowedToMove instead of WorldSession::IsRightUnitBeingMoved
572 // because the ACK could be coming from a unit that is under the control of that client but is not the 'Active Mover' unit.
573 // Example: Get a speed buff on yourself, then mount a vehicle before the end of the buff. When the buff expires,
574 // a force message will be sent to the client regarding the player and the client is required to respond with an ACK.
575 // But the vehicle will be the active mover unit at that time.
576 if (!client->IsAllowedToMove(guid))
577 {
578 recvData.rfinish(); // prevent warnings spam
579 TC_LOG_DEBUG("entities.unit", "Ignoring ACK. Bad or outdated movement data by Player {}", _player->GetName());
580 return;
581 }
582
583 Unit* mover = ObjectAccessor::GetUnit(*_player, guid);
584
585 UnitMoveType move_type;
586 switch (recvData.GetOpcode())
587 {
588 case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
589 case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
591 case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
593 case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break;
594 case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break;
596 case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break;
597 default:
598 TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(recvData.GetOpcode())));
599 return;
600 }
601
602 uint32 movementCounter;
603 float speedReceived;
604 MovementInfo movementInfo;
605 movementInfo.guid = guid;
606
607 recvData >> movementCounter;
608 ReadMovementInfo(recvData, &movementInfo);
609 recvData >> speedReceived;
610
611 ASSERT(mover);
612
613 // verify that indeed the client is replying with the changes that were send to him
614 if (!mover->HasPendingMovementChange() || mover->PeakFirstPendingMovementChange().movementCounter > movementCounter)
615 {
616 TC_LOG_DEBUG("entities.unit", "Ignoring ACK. Bad or outdated movement data by Player {}", _player->GetName());
617 return;
618 }
619
621 float speedSent = pendingChange.newValue;
622 MovementChangeType changeType = pendingChange.movementChangeType;
623 UnitMoveType moveTypeSent;
624 switch (changeType)
625 {
626 case MovementChangeType::SPEED_CHANGE_WALK: moveTypeSent = MOVE_WALK; break;
627 case MovementChangeType::SPEED_CHANGE_RUN: moveTypeSent = MOVE_RUN; break;
629 case MovementChangeType::SPEED_CHANGE_SWIM: moveTypeSent = MOVE_SWIM; break;
631 case MovementChangeType::RATE_CHANGE_TURN: moveTypeSent = MOVE_TURN_RATE; break;
634 case MovementChangeType::RATE_CHANGE_PITCH: moveTypeSent = MOVE_PITCH_RATE; break;
635 default:
636 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. movementChangeType: {}",
637 _player->GetName(), _player->GetSession()->GetAccountId(), static_cast<uint32>(AsUnderlyingType(changeType)));
638 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
639 _player->GetSession()->KickPlayer("incorrect movementChangeType returned in an ack");
640 return;
641 }
642
643 if (pendingChange.movementCounter != movementCounter)
644 {
645 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. pendingChange.movementCounter: {}, movementCounter: {}",
646 _player->GetName(), _player->GetSession()->GetAccountId(), pendingChange.movementCounter, movementCounter);
647 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
648 _player->GetSession()->KickPlayer("incorrect movementCounter returned in an ack");
649 return;
650 }
651
652 if (std::fabs(speedSent - speedReceived) > 0.01f)
653 {
654 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. speedSent - speedReceived: {}",
655 _player->GetName(), _player->GetSession()->GetAccountId(), std::fabs(speedSent - speedReceived));
656 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
657 _player->GetSession()->KickPlayer("incorrect speed returned in an ack");
658 return;
659 }
660
661 if (moveTypeSent != move_type)
662 {
663 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. moveTypeSent: {}, move_type: {}",
664 _player->GetName(), _player->GetSession()->GetAccountId(), static_cast<uint32>(AsUnderlyingType(moveTypeSent)), static_cast<uint32>(AsUnderlyingType(move_type)));
665 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
666 _player->GetSession()->KickPlayer("incorrect moveType returned in an ack");
667 return;
668 }
669
670 /* the client data has been verified. let's do the actual change now */
671 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
672 mover->m_movementInfo = movementInfo;
673
674 float newSpeedRate = speedSent / (mover->IsControlledByPlayer() ? playerBaseMoveSpeed[move_type] : baseMoveSpeed[move_type]);
675 mover->SetSpeedRateReal(move_type, newSpeedRate);
676 MovementPacketSender::SendSpeedChangeToObservers(mover, move_type, speedSent);
677
678 // Update position after updating known serverside speed
679 // this can interrupt aura granting us the speed boost so it needs see updated value in Unit::m_speed_rate
680 mover->UpdatePosition(movementInfo.pos);
681}
682
684{
685 TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
686
687 ObjectGuid guid;
688 recvData >> guid;
689
690 GameClient* client = GetGameClient();
691
692 // step 1: look at the list of units that this client is allowed to move. check if the client is allowed to even move the
693 // unit that is mentioned in the packet. if not, either silently ignore, log this event or kick the client.
694 if (!client->IsAllowedToMove(guid))
695 {
696 // @todo log or kick or do nothing depending on configuration
697 TC_LOG_DEBUG("entities.unit", "set active mover FAILED for client of player {}. GUID {}.", _player->GetName(), guid.ToString());
698 return;
699 }
700
701 // step 2:
702 TC_LOG_DEBUG("entities.unit", "set active mover OK for client of player {}. GUID {}.", _player->GetName(), guid.ToString());
703 Unit* newActivelyMovedUnit = ObjectAccessor::GetUnit(*_player, guid);
704 client->SetActivelyMovedUnit(newActivelyMovedUnit);
705}
706
708{
709 TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
710
711 ObjectGuid old_mover_guid;
712 recvData >> old_mover_guid.ReadAsPacked();
713 recvData.rfinish(); // prevent warnings spam.
714 // the movement info in this kind of packet is ignored for now. It's unclear if it should be used.
715
716 GameClient* client = GetGameClient();
717
718 if (client->GetActivelyMovedUnit() == nullptr || client->GetActivelyMovedUnit()->GetGUID() != old_mover_guid)
719 {
720 TC_LOG_DEBUG("entities.unit", "unset active mover FAILED for client of player {}. GUID {}.", _player->GetName(), old_mover_guid.ToString());
721 return;
722 }
723
724 TC_LOG_DEBUG("entities.unit", "unset active mover OK for client of player {}. GUID {}.", _player->GetName(), old_mover_guid.ToString());
725 client->SetActivelyMovedUnit(nullptr);
726}
727
729{
731 data << GetPlayer()->GetGUID();
732
733 GetPlayer()->SendMessageToSet(&data, false);
734}
735
737{
738 TC_LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK");
739
740 ObjectGuid guid;
741 recvData >> guid.ReadAsPacked();
742
743 GameClient* client = GetGameClient();
744
745 // ACK handlers should call GameClient::IsAllowedToMove instead of WorldSession::IsRightUnitBeingMoved
746 // because the ACK could be coming from a unit that is under the control of that client but is not the 'Active Mover' unit.
747 // Example: Get a speed buff on yourself, then mount a vehicle before the end of the buff. When the buff expires,
748 // a force message will be sent to the client regarding the player and the client is required to respond with an ACK.
749 // But the vehicle will be the active mover unit at that time.
750 if (!client->IsAllowedToMove(guid))
751 {
752 recvData.rfinish(); // prevent warnings spam
753 return;
754 }
755
756 Unit* mover = ObjectAccessor::GetUnit(*_player, guid);
757 ASSERT(mover);
758
759 recvData.read_skip<uint32>(); // unk
760
761 MovementInfo movementInfo;
762 movementInfo.guid = guid;
763 ReadMovementInfo(recvData, &movementInfo);
764 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
765
766 mover->m_movementInfo = movementInfo;
767 mover->UpdatePosition(movementInfo.pos);
768
770 WriteMovementInfo(&data, &movementInfo);
771
772 // knockback specific info
773 data << movementInfo.jump.sinAngle;
774 data << movementInfo.jump.cosAngle;
775 data << movementInfo.jump.xyspeed;
776 data << movementInfo.jump.zspeed;
777
778 client->GetBasePlayer()->SendMessageToSet(&data, false);
779}
780
782{
783 TC_LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK");
784
785 ObjectGuid guid; // guid - unused
786 recvData >> guid.ReadAsPacked();
787
788 GameClient* client = GetGameClient();
789 if (!client->IsAllowedToMove(guid))
790 {
791 recvData.rfinish(); // prevent warnings spam
792 return;
793 }
794
795 recvData.read_skip<uint32>(); // unk
796
797 MovementInfo movementInfo;
798 movementInfo.guid = guid;
799 ReadMovementInfo(recvData, &movementInfo);
800
801 recvData.read_skip<uint32>(); // unk2
802}
803
805{
806 TC_LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK");
807
808 ObjectGuid guid; // guid - unused
809 recvData >> guid.ReadAsPacked();
810
811 GameClient* client = GetGameClient();
812 if (!client->IsAllowedToMove(guid))
813 {
814 recvData.rfinish(); // prevent warnings spam
815 return;
816 }
817
818 recvData.read_skip<uint32>(); // unk
819
820 MovementInfo movementInfo;
821 movementInfo.guid = guid;
822 ReadMovementInfo(recvData, &movementInfo);
823
824 recvData.read_skip<uint32>(); // unk2
825}
826
828{
829 TC_LOG_DEBUG("network", "CMSG_FORCE_MOVE_ROOT_ACK");
830
831 ObjectGuid guid; // guid - unused
832 recvData >> guid.ReadAsPacked();
833
834 GameClient* client = GetGameClient();
835 if (!client->IsAllowedToMove(guid))
836 {
837 recvData.rfinish(); // prevent warnings spam
838 return;
839 }
840
841 recvData.read_skip<uint32>(); // unk
842
843 MovementInfo movementInfo;
844 movementInfo.guid = guid;
845 ReadMovementInfo(recvData, &movementInfo);
846}
847
849{
850 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_FEATHER_FALL_ACK");
851
852 ObjectGuid guid; // guid - unused
853 recvData >> guid.ReadAsPacked();
854
855 GameClient* client = GetGameClient();
856 if (!client->IsAllowedToMove(guid))
857 {
858 recvData.rfinish(); // prevent warnings spam
859 return;
860 }
861
862 recvData.read_skip<uint32>(); // unk
863
864 MovementInfo movementInfo;
865 movementInfo.guid = guid;
866 ReadMovementInfo(recvData, &movementInfo);
867
868 recvData.read_skip<uint32>(); // unk2
869}
870
872{
873 TC_LOG_DEBUG("network", "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK");
874
875 ObjectGuid guid; // guid - unused
876 recvData >> guid.ReadAsPacked();
877
878 GameClient* client = GetGameClient();
879 if (!client->IsAllowedToMove(guid))
880 {
881 recvData.rfinish(); // prevent warnings spam
882 return;
883 }
884
885 recvData.read_skip<uint32>(); // unk
886
887 MovementInfo movementInfo;
888 movementInfo.guid = guid;
889 ReadMovementInfo(recvData, &movementInfo);
890}
891
893{
894 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
895
896 ObjectGuid guid; // guid - unused
897 recvData >> guid.ReadAsPacked();
898
899 GameClient* client = GetGameClient();
900 if (!client->IsAllowedToMove(guid))
901 {
902 recvData.rfinish(); // prevent warnings spam
903 return;
904 }
905
906 recvData.read_skip<uint32>(); // unk
907
908 MovementInfo movementInfo;
909 movementInfo.guid = guid;
910 ReadMovementInfo(recvData, &movementInfo);
911
912 recvData.read_skip<uint32>(); // unk2
913}
914
916{
917 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK");
918
919 ObjectGuid guid;
920 recvData >> guid.ReadAsPacked();
921
922 GameClient* client = GetGameClient();
923 if (!client->IsAllowedToMove(guid))
924 {
925 recvData.rfinish(); // prevent warnings spam
926 return;
927 }
928
929 recvData.read_skip<uint32>(); // unk
930
931 MovementInfo movementInfo;
932 movementInfo.guid = guid;
933 ReadMovementInfo(recvData, &movementInfo);
934
935 recvData.read_skip<uint32>(); // unk2
936}
937
939{
940 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_DISABLE_ACK");
941
942 ObjectGuid guid;
943 recvData >> guid.ReadAsPacked();
944
945 GameClient* client = GetGameClient();
946 if (!client->IsAllowedToMove(guid))
947 {
948 recvData.rfinish(); // prevent warnings spam
949 return;
950 }
951
952 recvData.read_skip<uint32>(); // unk
953
954 MovementInfo movementInfo;
955 movementInfo.guid = guid;
956 ReadMovementInfo(recvData, &movementInfo);
957}
958
960{
961 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_ENABLE_ACK");
962
963 ObjectGuid guid;
964 recvData >> guid.ReadAsPacked();
965
966 GameClient* client = GetGameClient();
967 if (!client->IsAllowedToMove(guid))
968 {
969 recvData.rfinish(); // prevent warnings spam
970 return;
971 }
972
973 recvData.read_skip<uint32>(); // unk
974
975 MovementInfo movementInfo;
976 movementInfo.guid = guid;
977 ReadMovementInfo(recvData, &movementInfo);
978}
979
981{
982 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_COLLISION_HGT_ACK");
983
984 ObjectGuid guid;
985 float newValue;
986 recvData >> guid.ReadAsPacked();
987
988 GameClient* client = GetGameClient();
989 if (!client->IsAllowedToMove(guid))
990 {
991 recvData.rfinish(); // prevent warnings spam
992 return;
993 }
994
995 recvData.read_skip<uint32>(); // movement counter
996
997 MovementInfo movementInfo;
998 movementInfo.guid = guid;
999 ReadMovementInfo(recvData, &movementInfo);
1000
1001 recvData >> newValue;
1002}
1003
1005{
1006 if (!_player->IsAlive() || _player->IsInCombat())
1007 return;
1008
1009 ObjectGuid summonerGuid;
1010 bool agree;
1011 recvData >> summonerGuid;
1012 recvData >> agree;
1013
1014 _player->SummonIfPossible(agree);
1015}
1016
1018{
1019 TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_TIME_SKIPPED");
1020
1021 ObjectGuid guid;
1022 uint32 timeSkipped;
1023 recvData >> guid.ReadAsPacked();
1024 recvData >> timeSkipped;
1025
1026 Unit* mover = ValidateAndGetUnitBeingMoved(guid, false);
1027 if (!mover)
1028 {
1029 recvData.rfinish(); // prevent warnings spam
1030 return;
1031 }
1032
1033 mover->m_movementInfo.time += timeSkipped;
1034
1035 WorldPacket data(MSG_MOVE_TIME_SKIPPED, recvData.size());
1036 data << guid.WriteAsPacked();
1037 data << timeSkipped;
1038 GetPlayer()->SendMessageToSet(&data, false);
1039}
1040
1042{
1043 TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESP");
1044
1045 uint32 counter, clientTimestamp;
1046 recvData >> counter >> clientTimestamp;
1047
1048 if (_pendingTimeSyncRequests.count(counter) == 0)
1049 return;
1050
1051 uint32 serverTimeAtSent = _pendingTimeSyncRequests.at(counter);
1052 _pendingTimeSyncRequests.erase(counter);
1053
1054 // time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
1055 // we are going to make 2 assumptions:
1056 // 1) we assume that the request processing time equals 0.
1057 // 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
1058 uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent, recvData.GetReceivedTime());
1059 uint32 lagDelay = roundTripDuration / 2;
1060
1061 /*
1062 clockDelta = serverTime - clientTime
1063 where
1064 serverTime: time that was displayed on the clock of the SERVER at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
1065 clientTime: time that was displayed on the clock of the CLIENT at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
1066
1067 Once clockDelta has been computed, we can compute the time of an event on server clock when we know the time of that same event on the client clock,
1068 using the following relation:
1069 serverTime = clockDelta + clientTime
1070 */
1071 int64 clockDelta = (int64)serverTimeAtSent + (int64)lagDelay - (int64)clientTimestamp;
1072 _timeSyncClockDeltaQueue->push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
1074}
1075
1077{
1078 // implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
1079 // to reduce the skew induced by dropped TCP packets that get resent.
1080
1081 using namespace boost::accumulators;
1082
1083 accumulator_set<uint32, features<tag::mean, tag::median, tag::variance(lazy)> > latencyAccumulator;
1084
1085 for (auto [_, roundTripDuration] : *_timeSyncClockDeltaQueue)
1086 latencyAccumulator(roundTripDuration);
1087
1088 uint32 latencyMedian = static_cast<uint32>(std::round(median(latencyAccumulator)));
1089 uint32 latencyStandardDeviation = static_cast<uint32>(std::round(sqrt(variance(latencyAccumulator))));
1090
1091 accumulator_set<int64, features<tag::mean> > clockDeltasAfterFiltering;
1092 uint32 sampleSizeAfterFiltering = 0;
1093 for (auto [clockDelta, roundTripDuration] : *_timeSyncClockDeltaQueue)
1094 {
1095 if (roundTripDuration < latencyStandardDeviation + latencyMedian) {
1096 clockDeltasAfterFiltering(clockDelta);
1097 sampleSizeAfterFiltering++;
1098 }
1099 }
1100
1101 if (sampleSizeAfterFiltering != 0)
1102 {
1103 int64 meanClockDelta = static_cast<int64>(std::round(mean(clockDeltasAfterFiltering)));
1104 if (std::abs(meanClockDelta - _timeSyncClockDelta) > 25)
1105 _timeSyncClockDelta = meanClockDelta;
1106 }
1107 else if (_timeSyncClockDelta == 0)
1109}
@ SEC_PLAYER
Definition Common.h:40
@ VEHICLE_SEAT_FLAG_ALLOW_TURNING
Definition DBCEnums.h:479
Difficulty
Definition DBCEnums.h:279
MapDifficulty const * GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
int64_t int64
Definition Define.h:128
#define SI64LIT(N)
Definition Define.h:121
uint32_t uint32
Definition Define.h:133
#define ASSERT
Definition Errors.h:68
#define SIZE_OF_GRIDS
Definition GridDefines.h:38
#define sInstanceSaveMgr
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
#define sMapMgr
Definition MapManager.h:211
#define REMOVE_VIOLATING_FLAGS(check, maskToRemove)
#define sObjectMgr
Definition ObjectMgr.h:1721
@ DAMAGE_FALL_TO_VOID
Definition Player.h:697
@ TELE_REVIVE_AT_TELEPORT
Definition Player.h:685
@ PLAYER_FLAGS_IN_PVP
Definition Player.h:353
@ PLAYER_FLAGS_IS_OUT_OF_BOUNDS
Definition Player.h:358
@ GAMEOBJECT_TYPE_TRANSPORT
@ EMOTE_ONESHOT_NONE
@ BATTLEGROUND_TYPE_NONE
@ SPELL_AURA_FEATHER_FALL
@ SPELL_AURA_FLY
@ SPELL_AURA_GHOST
@ SPELL_AURA_WATER_WALK
@ SPELL_AURA_HOVER
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
@ AURA_INTERRUPT_FLAG_TURNING
@ AURA_INTERRUPT_FLAG_LANDING
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition Timer.h:40
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ MOVEMENTFLAG_DESCENDING
@ MOVEMENTFLAG_PITCH_DOWN
@ MOVEMENTFLAG_PITCH_UP
@ MOVEMENTFLAG_RIGHT
@ MOVEMENTFLAG_SPLINE_ENABLED
@ MOVEMENTFLAG_FORWARD
@ MOVEMENTFLAG_STRAFE_LEFT
@ MOVEMENTFLAG_ONTRANSPORT
@ MOVEMENTFLAG_BACKWARD
@ MOVEMENTFLAG_WATERWALKING
@ MOVEMENTFLAG_MASK_MOVING
@ MOVEMENTFLAG_DISABLE_GRAVITY
@ MOVEMENTFLAG_FLYING
@ MOVEMENTFLAG_FALLING_SLOW
@ MOVEMENTFLAG_CAN_FLY
@ MOVEMENTFLAG_ROOT
@ MOVEMENTFLAG_MASK_TURNING
@ MOVEMENTFLAG_FALLING
@ MOVEMENTFLAG_LEFT
@ MOVEMENTFLAG_STRAFE_RIGHT
@ MOVEMENTFLAG_ASCENDING
@ MOVEMENTFLAG_HOVER
UnitMoveType
@ MOVE_FLIGHT
@ MOVE_SWIM
@ MOVE_TURN_RATE
@ MOVE_FLIGHT_BACK
@ MOVE_SWIM_BACK
@ MOVE_RUN
@ MOVE_PITCH_RATE
@ MOVE_RUN_BACK
@ MOVE_WALK
float baseMoveSpeed[MAX_MOVE_TYPE]
Definition Unit.cpp:87
float playerBaseMoveSpeed[MAX_MOVE_TYPE]
Definition Unit.cpp:100
MovementChangeType
Definition Unit.h:275
@ PLAYER_FLAGS
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
@ VEHICLE_FLAG_FIXED_POSITION
virtual bool HandlePlayerUnderMap(Player *)
void read_skip()
Definition ByteBuffer.h:330
void rfinish()
Definition ByteBuffer.h:316
size_t size() const
Definition ByteBuffer.h:409
void SetActivelyMovedUnit(Unit *activelyMovedUnit)
Definition GameClient.h:38
Unit * GetActivelyMovedUnit() const
Definition GameClient.h:37
Player * GetBasePlayer() const
Definition GameClient.h:40
bool IsAllowedToMove(Unit *unit) const
GameobjectTypes GetGoType() const
Definition GameObject.h:176
static bool IsValidMapCoord(uint32 mapid, float x, float y)
Definition MapManager.h:90
Definition Map.h:281
virtual void RemovePlayerFromMap(Player *, bool)
Definition Map.cpp:1002
float GetMinHeight(float x, float y) const
Definition Map.cpp:2530
GameObject * GetGameObject(ObjectGuid const &guid)
Definition Map.cpp:4430
virtual EnterState CannotEnter(Player *)
Definition Map.h:408
uint32 GetId() const
Definition Map.cpp:4216
char const * GetMapName() const
Definition Map.cpp:2924
virtual bool AddPlayerToMap(Player *)
Definition Map.cpp:583
Transport * GetTransport(ObjectGuid const &guid)
Definition Map.cpp:4440
MovementGenerator * GetCurrentMovementGenerator() const
virtual bool Initialize(Unit *)=0
static void SendSpeedChangeToObservers(Unit *unit, UnitMoveType mtype, float newRate)
bool Finalized() const
Definition MoveSpline.h:121
bool Initialized() const
Definition MoveSpline.h:98
PackedGuidWriter WriteAsPacked() const
Definition ObjectGuid.h:152
std::string ToString() const
PackedGuidReader ReadAsPacked()
Definition ObjectGuid.h:146
bool IsInWorld() const
Definition Object.h:73
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:760
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:775
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:799
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
void SetSemaphoreTeleportNear(bool semphsetting)
Definition Player.h:1823
void SendInitialPacketsAfterAddToMap()
Definition Player.cpp:22472
WorldLocation const & GetCorpseLocation() const
Definition Player.h:1758
bool m_InstanceValid
Definition Player.h:2144
WorldLocation & GetTeleportDest()
Definition Player.h:1818
void SetBGTeam(uint32 team)
Definition Player.cpp:21944
void HandleFall(MovementInfo const &movementInfo)
Definition Player.cpp:24859
float m_homebindZ
Definition Player.h:2089
bool IsBeingTeleportedFar() const
Definition Player.h:1822
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
Definition Player.cpp:634
void KillPlayer()
Definition Player.cpp:4434
uint32 m_homebindMapId
Definition Player.h:2085
void CheckOutdoorsAuraRequirements()
Definition Player.cpp:6263
bool InBattleground() const
Definition Player.h:1982
void SpawnCorpseBones(bool triggerSave=true)
Definition Player.cpp:4536
void UpdateZone(uint32 newZone, uint32 newArea)
Definition Player.cpp:6804
Difficulty GetDifficulty(bool isRaid) const
Definition Player.h:1634
void SetFallInformation(uint32 time, float z)
Definition Player.cpp:24853
void SendInitialPacketsBeforeAddToMap()
Definition Player.cpp:22408
void ResetMap() override
Definition Player.cpp:25551
WorldSession * GetSession() const
Definition Player.h:1719
bool IsInvitedForBattlegroundInstance(uint32 instanceId) const
Definition Player.cpp:23140
void UpdateFallInformationIfNeed(MovementInfo const &minfo, uint16 opcode)
Definition Player.cpp:25191
void SetSemaphoreTeleportFar(bool semphsetting)
Definition Player.h:1824
void FinishTaxiFlight()
Definition Player.cpp:21202
Battleground * GetBattleground() const
Definition Player.cpp:23049
void ProcessDelayedOperations()
Definition Player.cpp:1776
float m_homebindY
Definition Player.h:2088
bool UpdatePosition(float x, float y, float z, float orientation, bool teleport=false) override
Definition Player.cpp:6103
uint32 GetTeleportOptions() const
Definition Player.h:1819
PvPInfo pvpInfo
Definition Player.h:1582
void SummonIfPossible(bool agree)
Definition Player.cpp:23330
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
bool IsBeingTeleportedNear() const
Definition Player.h:1821
bool CheckInstanceValidity(bool)
Definition Player.cpp:18867
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool welcome) const
Definition Player.cpp:22597
uint32 GetBattlegroundId() const
Definition Player.h:1984
void SetMap(Map *map) override
Definition Player.cpp:25563
std::string GetDebugInfo() const override
Definition Player.cpp:26504
void SendMessageToSet(WorldPacket const *data, bool self) const override
Definition Player.h:1747
void ResummonPetTemporaryUnSummonedIfAny()
Definition Player.cpp:25212
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId)
Definition Player.cpp:23092
void UpdatePvP(bool state, bool override=false)
Definition Player.cpp:21687
bool IsBeingTeleported() const
Definition Player.h:1820
float m_homebindX
Definition Player.h:2087
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:4346
void RemovePassenger(WorldObject *passenger)
Definition Unit.h:769
Vehicle * GetVehicle() const
Definition Unit.h:1737
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3765
Movement::MoveSpline * movespline
Definition Unit.h:1804
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
Definition Unit.cpp:4022
Emote GetEmoteState() const
Definition Unit.h:966
PlayerMovementPendingChange PopPendingMovementChange()
Definition Unit.cpp:12953
bool IsPvP() const
Definition Unit.h:988
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsAlive() const
Definition Unit.h:1234
PlayerMovementPendingChange & PeakFirstPendingMovementChange()
Definition Unit.cpp:12948
void SetSpeedRateReal(UnitMoveType mtype, float rate)
Definition Unit.cpp:8707
void SetEmoteState(Emote emote)
Definition Unit.h:967
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition Unit.cpp:12890
bool IsInFlight() const
Definition Unit.h:1119
float GetHoverOffset() const
Definition Unit.h:1767
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4542
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
bool IsControlledByPlayer() const
Definition Unit.h:1258
bool IsInCombat() const
Definition Unit.h:1144
bool IsSitState() const
Definition Unit.cpp:10348
bool HasPendingMovementChange() const
Definition Unit.h:1776
uint32 GetMapId() const
Definition Position.h:193
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1783
Map * GetMap() const
Definition Object.h:449
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
std::string const & GetName() const
Definition Object.h:382
Transport * GetTransport() const
Definition Object.h:564
uint32 GetZoneId() const
Definition Object.h:373
MovementInfo m_movementInfo
Definition Object.h:575
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:375
TimePoint GetReceivedTime() const
Definition WorldPacket.h:83
uint16 GetOpcode() const
Definition WorldPacket.h:80
OpcodeClient GetOpcode() const
Definition Packet.h:67
WorldPacket const * Write() override
void HandleMountSpecialAnimOpcode(WorldPacket &recvdata)
void LogoutPlayer(bool save)
Log the player out
void HandleMovementOpcode(OpcodeClient opcode, MovementInfo &movementInfo)
void HandleMoveTeleportAck(WorldPacket &recvPacket)
Unit * ValidateAndGetUnitBeingMoved(ObjectGuid guid, bool forStatusAck) const
void HandleMoveWorldportAck()
void HandleMoveHoverAck(WorldPacket &recvData)
static void WriteMovementInfo(WorldPacket *data, MovementInfo *mi)
void HandleMoveRootAck(WorldPacket &recvPacket)
AccountTypes GetSecurity() const
int64 _timeSyncClockDelta
std::map< uint32, uint32 > _pendingTimeSyncRequests
uint32 AdjustClientMovementTime(uint32 time) const
void HandleSummonResponseOpcode(WorldPacket &recvData)
void HandleMoveTimeSkippedOpcode(WorldPacket &recvData)
void HandleMoveSetCollisionHgtAck(WorldPacket &recvData)
void HandleMoveGravityEnableAck(WorldPacket &recvData)
void KickPlayer(std::string const &reason)
Kick a player out of the World.
Player * GetPlayer() const
void HandleMoveGravityDisableAck(WorldPacket &recvData)
bool ValidateMovementInfo(Unit const *mover, MovementInfo *mi) const
void HandleMoveSetCanTransitionBetweenSwinAndFlyAck(WorldPacket &recvData)
void HandleMovementOpcodes(WorldPackets::Movement::ClientPlayerMovement &packet)
void HandleForceSpeedChangeAck(WorldPacket &recvData)
void HandleMoveWaterWalkAck(WorldPacket &recvPacket)
void HandleMoveUnRootAck(WorldPacket &recvPacket)
uint32 GetAccountId() const
void ReadMovementInfo(WorldPacket &data, MovementInfo *mi)
Player * _player
void HandleMoveSetCanFlyAckOpcode(WorldPacket &recvData)
std::unique_ptr< boost::circular_buffer< std::pair< int64, uint32 > > > _timeSyncClockDeltaQueue
void HandleMoveNotActiveMover(WorldPacket &recvData)
void HandleMoveWorldportAckOpcode(WorldPacket &recvPacket)
GameClient * GetGameClient() const
void HandleTimeSyncResponse(WorldPacket &recvData)
void HandleSetActiveMoverOpcode(WorldPacket &recvData)
void HandleMoveKnockBackAck(WorldPacket &recvPacket)
void HandleFeatherFallAck(WorldPacket &recvData)
Opcodes
Definition Opcodes.h:29
std::string GetOpcodeNameForLogging(Opcodes opcode)
Lookup opcode name for human understandable logging.
Definition Opcodes.cpp:1469
@ MSG_MOVE_STOP_PITCH
Definition Opcodes.h:222
@ CMSG_FORCE_PITCH_RATE_CHANGE_ACK
Definition Opcodes.h:1146
@ MSG_MOVE_STOP_ASCEND
Definition Opcodes.h:887
@ MSG_MOVE_START_SWIM
Definition Opcodes.h:231
@ MSG_MOVE_STOP_STRAFE
Definition Opcodes.h:215
@ MSG_MOVE_KNOCK_BACK
Definition Opcodes.h:270
@ SMSG_MOUNTSPECIAL_ANIM
Definition Opcodes.h:399
@ CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:258
@ MSG_MOVE_STOP_TURN
Definition Opcodes.h:219
@ CMSG_FORCE_TURN_RATE_CHANGE_ACK
Definition Opcodes.h:764
@ CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:929
@ CMSG_FORCE_SWIM_SPEED_CHANGE_ACK
Definition Opcodes.h:260
@ MSG_MOVE_FALL_LAND
Definition Opcodes.h:230
@ CMSG_FORCE_RUN_SPEED_CHANGE_ACK
Definition Opcodes.h:256
@ MSG_MOVE_STOP
Definition Opcodes.h:212
@ CMSG_FORCE_WALK_SPEED_CHANGE_ACK
Definition Opcodes.h:760
@ MSG_MOVE_TIME_SKIPPED
Definition Opcodes.h:822
@ CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK
Definition Opcodes.h:927
@ MSG_MOVE_STOP_SWIM
Definition Opcodes.h:232
@ CMSG_MOVE_SET_FLY
Definition Opcodes.h:867
@ CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK
Definition Opcodes.h:762
#define sWorld
Definition World.h:900
@ CONFIG_PENDING_MOVE_CHANGES_TIMEOUT
Definition World.h:403
time_t GetGameTime()
Definition GameTime.cpp:42
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
bool IsValidMapCoord(float c)
bool IsBattlegroundOrArena() const
bool IsDungeon() const
bool IsRaid() const
ObjectGuid guid
void RemoveMovementFlag(uint32 flag)
struct MovementInfo::TransportInfo transport
bool HasMovementFlag(uint32 flag) const
Position pos
MovementChangeType movementChangeType
Definition Unit.h:306
float GetExactDist2d(const float x, const float y) const
Definition Position.h:109
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
bool IsPositionValid() const
Definition Position.cpp:44
void SetOrientation(float orientation)
Definition Position.h:74
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
void Relocate(float x, float y)
Definition Position.h:66
bool IsHostile
Definition Player.h:244