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 "MiscPackets.h"
27#include "MotionMaster.h"
28#include "MovementGenerator.h"
29#include "MovementPackets.h"
31#include "MoveSpline.h"
32#include "ObjectAccessor.h"
33#include "ObjectMgr.h"
34#include "Opcodes.h"
35#include "Player.h"
36#include "Transport.h"
37#include "Vehicle.h"
38#include "World.h"
39#include "WorldPacket.h"
40#include "WorldSession.h"
41#include <boost/accumulators/statistics/variance.hpp>
42#include <boost/accumulators/accumulators.hpp>
43#include <boost/accumulators/statistics.hpp>
44#include <boost/circular_buffer.hpp>
45
47{
50 #ifdef TRINITY_DEBUG
51 #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) do \
52 { \
53 if (check) \
54 { \
55 TC_LOG_DEBUG("entities.unit", "WorldSession::ReadMovementInfo: Violation of MovementFlags found \"{}\". " \
56 "MovementFlags: {}, MovementFlags2: {} for player {}. Mask {} will be removed.", \
57 STRINGIZE(check), mi->GetMovementFlags(), mi->GetExtraMovementFlags(), GetPlayer()->GetGUID(), maskToRemove); \
58 mi->RemoveMovementFlag((maskToRemove)); \
59 } \
60 } while(0)
61 #else
62 #define REMOVE_VIOLATING_FLAGS(check, maskToRemove) do \
63 { \
64 if (check) \
65 mi->RemoveMovementFlag((maskToRemove)); \
66 } while (0)
67 #endif
68
69 if (!mover)
70 return false;
71
72 if (!mi->pos.IsPositionValid())
73 return false;
74
75 if (!GetPlayer()->GetVehicleBase() || !(GetPlayer()->GetVehicle()->GetVehicleInfo()->Flags & VEHICLE_FLAG_FIXED_POSITION))
77
84
88
92
96
100
104
108
114
118
126 !mover->HasAuraType(SPELL_AURA_FLY) &&
129
133
136
137 #undef REMOVE_VIOLATING_FLAGS
138
139 return true;
140}
141
143{
144 GameClient* client = GetGameClient();
145
146 // the client is attempting to tamper movement data
147 // edit: this wouldn't happen in retail but it does in TC, even with a legitimate client.
148 Unit* activelyMovedUnit = client->GetActivelyMovedUnit();
149 if (!forStatusAck && (!activelyMovedUnit || activelyMovedUnit->GetGUID() != guid))
150 {
151 TC_LOG_DEBUG("entities.unit", "{} Attempted tampering movement data in {}, requesting not allowed mover {} but expected {}",
152 GetPlayerInfo(), GetOpcodeNameForLogging(opcode), guid, Object::GetGUID(activelyMovedUnit));
153 return nullptr;
154 }
155
156 // This can happen if a legitimate client has lost control of a unit but hasn't received SMSG_CONTROL_UPDATE before
157 // sending this packet yet. The server should silently ignore all MOVE messages coming from the client as soon
158 // as control over that unit is revoked (through a 'SMSG_CONTROL_UPDATE allowMove=false' message).
159 if (!client->IsAllowedToMove(guid))
160 {
161 TC_LOG_DEBUG("entities.unit", "{} Sent bad or outdated movement data in {}, requesting not allowed mover {}",
162 GetPlayerInfo(), GetOpcodeNameForLogging(opcode), guid);
163 return nullptr;
164 }
165
166 if (activelyMovedUnit && activelyMovedUnit->GetGUID() == guid)
167 return activelyMovedUnit;
168
169 if (_player->GetGUID() == guid)
170 return _player;
171
172 return ObjectAccessor::GetUnit(*_player, guid);
173}
174
176{
177 int64 movementTime = int64(time) + _timeSyncClockDelta;
178 if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > SI64LIT(0xFFFFFFFF))
179 {
180 TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
182 }
183 else
184 return uint32(movementTime);
185}
186
188{
189 TC_LOG_DEBUG("network", "WORLD: got MSG_MOVE_WORLDPORT_ACK.");
191}
192
194{
195 Player* player = GetPlayer();
196 // ignore unexpected far teleports
197 if (!player->IsBeingTeleportedFar())
198 return;
199
200 player->SetSemaphoreTeleportFar(false);
201
202 // get the teleport destination
203 WorldLocation const& loc = player->GetTeleportDest();
204
205 // possible errors in the coordinate validity check
207 {
208 LogoutPlayer(false);
209 return;
210 }
211
212 // get the destination map entry, not the current one, this will fix homebind and reset greeting
213 MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
214 InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());
215
216 // reset instance validity, except if going to an instance inside an instance
217 if (player->m_InstanceValid == false && !mInstance)
218 player->m_InstanceValid = true;
219
220 Map* oldMap = player->GetMap();
221 Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), player);
222
223 if (player->IsInWorld())
224 {
225 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());
226 oldMap->RemovePlayerFromMap(player, false);
227 }
228
229 // relocate the player to the teleport destination
230 // the CannotEnter checks are done in TeleporTo but conditions may change
231 // while the player is in transit, for example the map may get full
232 if (!newMap || newMap->CannotEnter(player))
233 {
234 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());
235 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
236 return;
237 }
238
239 float z = loc.GetPositionZ() + player->GetHoverOffset();
240 player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
241 player->SetFallInformation(0, player->GetPositionZ());
242
243 player->ResetMap();
244 player->SetMap(newMap);
245
247 if (!player->GetMap()->AddPlayerToMap(player))
248 {
249 TC_LOG_ERROR("network", "WORLD: failed to teleport player {} {} to map {} ({}) because of unknown reason!",
250 player->GetName(), player->GetGUID().ToString(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
251 player->ResetMap();
252 player->SetMap(oldMap);
253 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
254 return;
255 }
256
257 // battleground state prepare (in case join to BG), at relogin/tele player not invited
258 // only add to bg group and object, if the player was invited (else he entered through command)
259 if (player->InBattleground())
260 {
261 // cleanup setting if outdated
262 if (!mEntry->IsBattlegroundOrArena())
263 {
264 // We're not in BG
266 // reset destination bg team
267 player->SetBGTeam(0);
268 }
269 // join to bg case
270 else if (Battleground* bg = player->GetBattleground())
271 {
273 bg->AddPlayer(player);
274 }
275 }
276
278
279 // flight fast teleport case
280 if (player->IsInFlight())
281 {
282 if (!player->InBattleground())
283 {
284 // short preparations to continue flight
285 MovementGenerator* movementGenerator = player->GetMotionMaster()->GetCurrentMovementGenerator();
286 movementGenerator->Initialize(player);
287 return;
288 }
289
290 // battleground state prepare, stop flight
291 player->FinishTaxiFlight();
292 }
293
294 if (!player->IsAlive() && player->GetTeleportOptions() & TELE_REVIVE_AT_TELEPORT)
295 player->ResurrectPlayer(0.5f);
296
297 // resurrect character at enter into instance where his corpse exist after add to map
298 if (mEntry->IsDungeon() && !player->IsAlive())
299 {
300 if (player->GetCorpseLocation().GetMapId() == mEntry->ID)
301 {
302 player->ResurrectPlayer(0.5f);
303 player->SpawnCorpseBones();
304 }
305 }
306
307 bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena();
308 if (mInstance)
309 {
310 // check if this instance has a reset time and send it to player if so
311 Difficulty diff = newMap->GetDifficultyID();
312 if (MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mEntry->ID, diff))
313 {
314 if (mapDiff->RaidDuration)
315 {
316 if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->ID, diff))
317 {
318 uint32 timeleft = uint32(timeReset - GameTime::GetGameTime());
319 player->SendInstanceResetWarning(mEntry->ID, diff, timeleft, true);
320 }
321 }
322 }
323
324 // check if instance is valid
325 if (!player->CheckInstanceValidity(false))
326 player->m_InstanceValid = false;
327
328 // instance mounting is handled in InstanceTemplate
329 allowMount = mInstance->AllowMount;
330 }
331
332 // mount allow check
333 if (!allowMount)
335
336 // update zone immediately, otherwise leave channel will cause crash in mtmap
337 uint32 newzone, newarea;
338 player->GetZoneAndAreaId(newzone, newarea);
339 player->UpdateZone(newzone, newarea);
340
341 // honorless target
342 if (player->pvpInfo.IsHostile)
343 player->CastSpell(player, 2479, true);
344
345 // in friendly area
346 else if (player->IsPvP() && !player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
347 player->UpdatePvP(false, false);
348
349 // resummon pet
351
352 //lets process all delayed operations on successful teleport
353 player->ProcessDelayedOperations();
354}
355
357{
358 TC_LOG_DEBUG("network", "CMSG_MOVE_TELEPORT_ACK: Guid: {}, Sequence: {}, Time: {}", packet.MoverGUID.ToString(), packet.AckIndex, packet.MoveTime);
359
360 Unit* mover = ValidateAndGetUnitBeingMoved(packet.MoverGUID, packet.GetOpcode(), false);
361 if (!mover)
362 return;
363
364 Player* plMover = mover->ToPlayer();
365
366 if (!plMover || !plMover->IsBeingTeleportedNear())
367 return;
368
369 plMover->SetSemaphoreTeleportNear(false);
370
371 uint32 old_zone = plMover->GetZoneId();
372
373 WorldLocation const& dest = plMover->GetTeleportDest();
374
375 plMover->UpdatePosition(dest, true);
376 plMover->SetFallInformation(0, GetPlayer()->GetPositionZ());
377
378 uint32 newzone, newarea;
379 plMover->GetZoneAndAreaId(newzone, newarea);
380 plMover->UpdateZone(newzone, newarea);
381
382 // new zone
383 if (old_zone != newzone)
384 {
385 // honorless target
386 if (plMover->pvpInfo.IsHostile)
387 plMover->CastSpell(plMover, 2479, true);
388
389 // in friendly area
390 else if (plMover->IsPvP() && !plMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
391 plMover->UpdatePvP(false, false);
392 }
393
394 // resummon pet
396
397 //lets process all delayed operations on successful teleport
399}
400
405
407{
408 Unit* mover = ValidateAndGetUnitBeingMoved(movementInfo.guid, opcode, false);
409 if (!ValidateMovementInfo(mover, &movementInfo))
410 return;
411
412 Player* plrMover = mover->ToPlayer();
413
414 // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
415 if (plrMover && plrMover->IsBeingTeleported())
416 return;
417
418 if (!mover->movespline->Finalized())
419 return;
420
421 // stop some emotes at player move
422 if (plrMover && (plrMover->GetEmoteState() != 0))
424
425 /* handle special cases */
427 {
428 // We were teleported, skip packets that were broadcast before teleport
429 if (movementInfo.pos.GetExactDist2d(mover) > SIZE_OF_GRIDS)
430 return;
431
432 // transports size limited
433 // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
434 if (fabs(movementInfo.transport.pos.GetPositionX()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionY()) > 75.0f || fabs(movementInfo.transport.pos.GetPositionZ()) > 75.0f)
435 return;
436
437 if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(),
438 movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation()))
439 return;
440
441 // if we boarded a transport, add us to it
442 if (plrMover)
443 {
444 if (!plrMover->GetTransport())
445 {
446 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
447 transport->AddPassenger(plrMover);
448 }
449 else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid)
450 {
451 plrMover->GetTransport()->RemovePassenger(plrMover);
452 if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid))
453 transport->AddPassenger(plrMover);
454 else
455 movementInfo.transport.Reset();
456 }
457 }
458
459 if (!mover->GetTransport() && !mover->GetVehicle())
460 {
461 GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
462 if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
464 }
465 }
466 else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
467 {
468 plrMover->GetTransport()->RemovePassenger(plrMover);
469 movementInfo.transport.Reset();
470 }
471
472 /* process position-change */
473 movementInfo.guid = mover->GetGUID();
474 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
475 mover->m_movementInfo = movementInfo;
476
477 WorldPackets::Movement::MoveUpdate moveUpdate(opcode);
478 moveUpdate.Status = &mover->m_movementInfo;
479 mover->SendMessageToSet(moveUpdate.Write(), _player);
480
481 // Some vehicles allow the passenger to turn by himself
482 if (Vehicle* vehicle = mover->GetVehicle())
483 {
484 if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover))
485 {
486 if (seat->Flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)
487 {
488 if (movementInfo.pos.GetOrientation() != mover->GetOrientation())
489 {
490 mover->SetOrientation(movementInfo.pos.GetOrientation());
492 }
493 }
494 }
495 return;
496 }
497
498 mover->UpdatePosition(movementInfo.pos);
499
500 // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
501 if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight())
502 plrMover->HandleFall();
503
504 // interrupt parachutes upon falling or landing in water
505 if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM)
507
508 if (plrMover) // nothing is charmed, or player charmed
509 {
510 if (plrMover->IsSitState() && (movementInfo.flags & (MOVEMENTFLAG_MASK_MOVING | MOVEMENTFLAG_MASK_TURNING)))
512
513 plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
514
515 if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()))
516 {
517 if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(plrMover)))
518 {
519 // NOTE: this is actually called many times while falling
520 // even after the player has been teleported away
522 if (plrMover->IsAlive())
523 {
524 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());
526 plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
527 // player can be alive if GM/etc
528 // change the death state to CORPSE to prevent the death timer from
529 // starting in the next player update
530 if (plrMover->IsAlive())
531 plrMover->KillPlayer();
532 }
533 }
534 }
535 else
537
538 // Whenever a player stops a movement action, an indoor/outdoor check is being performed
539 switch (opcode)
540 {
543 case MSG_MOVE_STOP:
550 break;
551 default:
552 break;
553 }
554 }
555}
556
558{
559 /* extract packet */
560 ObjectGuid guid;
561 recvData >> guid.ReadAsPacked();
562
563 GameClient* client = GetGameClient();
564
565 // ACK handlers should call GameClient::IsAllowedToMove instead of WorldSession::IsRightUnitBeingMoved
566 // because the ACK could be coming from a unit that is under the control of that client but is not the 'Active Mover' unit.
567 // Example: Get a speed buff on yourself, then mount a vehicle before the end of the buff. When the buff expires,
568 // a force message will be sent to the client regarding the player and the client is required to respond with an ACK.
569 // But the vehicle will be the active mover unit at that time.
570 if (!client->IsAllowedToMove(guid))
571 {
572 recvData.rfinish(); // prevent warnings spam
573 TC_LOG_DEBUG("entities.unit", "Ignoring ACK. Bad or outdated movement data by Player {}", _player->GetName());
574 return;
575 }
576
577 Unit* mover = ObjectAccessor::GetUnit(*_player, guid);
578
579 UnitMoveType move_type;
580 switch (recvData.GetOpcode())
581 {
582 case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; break;
583 case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; break;
585 case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; break;
587 case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; break;
588 case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; break;
590 case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; break;
591 default:
592 TC_LOG_ERROR("network", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(recvData.GetOpcode())));
593 return;
594 }
595
596 uint32 movementCounter;
597 float speedReceived;
598 MovementInfo movementInfo;
599 movementInfo.guid = guid;
600
601 recvData >> movementCounter;
602 ReadMovementInfo(recvData, &movementInfo);
603 recvData >> speedReceived;
604
605 ASSERT(mover);
606
607 // verify that indeed the client is replying with the changes that were send to him
608 if (!mover->HasPendingMovementChange() || mover->PeakFirstPendingMovementChange().movementCounter > movementCounter)
609 {
610 TC_LOG_DEBUG("entities.unit", "Ignoring ACK. Bad or outdated movement data by Player {}", _player->GetName());
611 return;
612 }
613
615 float speedSent = pendingChange.newValue;
616 MovementChangeType changeType = pendingChange.movementChangeType;
617 UnitMoveType moveTypeSent;
618 switch (changeType)
619 {
620 case MovementChangeType::SPEED_CHANGE_WALK: moveTypeSent = MOVE_WALK; break;
621 case MovementChangeType::SPEED_CHANGE_RUN: moveTypeSent = MOVE_RUN; break;
623 case MovementChangeType::SPEED_CHANGE_SWIM: moveTypeSent = MOVE_SWIM; break;
625 case MovementChangeType::RATE_CHANGE_TURN: moveTypeSent = MOVE_TURN_RATE; break;
628 case MovementChangeType::RATE_CHANGE_PITCH: moveTypeSent = MOVE_PITCH_RATE; break;
629 default:
630 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. movementChangeType: {}",
631 _player->GetName(), _player->GetSession()->GetAccountId(), static_cast<uint32>(AsUnderlyingType(changeType)));
632 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
633 _player->GetSession()->KickPlayer("incorrect movementChangeType returned in an ack");
634 return;
635 }
636
637 if (pendingChange.movementCounter != movementCounter)
638 {
639 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. pendingChange.movementCounter: {}, movementCounter: {}",
640 _player->GetName(), _player->GetSession()->GetAccountId(), pendingChange.movementCounter, movementCounter);
641 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
642 _player->GetSession()->KickPlayer("incorrect movementCounter returned in an ack");
643 return;
644 }
645
646 if (std::fabs(speedSent - speedReceived) > 0.01f)
647 {
648 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. speedSent - speedReceived: {}",
649 _player->GetName(), _player->GetSession()->GetAccountId(), std::fabs(speedSent - speedReceived));
650 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
651 _player->GetSession()->KickPlayer("incorrect speed returned in an ack");
652 return;
653 }
654
655 if (moveTypeSent != move_type)
656 {
657 TC_LOG_INFO("cheat", "WorldSession::HandleForceSpeedChangeAck: Player {} from account id {} kicked for incorrect data returned in an ack. moveTypeSent: {}, move_type: {}",
658 _player->GetName(), _player->GetSession()->GetAccountId(), static_cast<uint32>(AsUnderlyingType(moveTypeSent)), static_cast<uint32>(AsUnderlyingType(move_type)));
659 if (sWorld->getIntConfig(CONFIG_PENDING_MOVE_CHANGES_TIMEOUT) != 0)
660 _player->GetSession()->KickPlayer("incorrect moveType returned in an ack");
661 return;
662 }
663
664 /* the client data has been verified. let's do the actual change now */
665 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
666 mover->m_movementInfo = movementInfo;
667
668 float newSpeedRate = speedSent / (mover->IsControlledByPlayer() ? playerBaseMoveSpeed[move_type] : baseMoveSpeed[move_type]);
669 mover->SetSpeedRateReal(move_type, newSpeedRate);
670 MovementPacketSender::SendSpeedChangeToObservers(mover, move_type, speedSent);
671
672 // Update position after updating known serverside speed
673 // this can interrupt aura granting us the speed boost so it needs see updated value in Unit::m_speed_rate
674 mover->UpdatePosition(movementInfo.pos);
675}
676
678{
679 TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
680
681 ObjectGuid guid;
682 recvData >> guid;
683
684 GameClient* client = GetGameClient();
685
686 // 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
687 // unit that is mentioned in the packet. if not, either silently ignore, log this event or kick the client.
688 if (!client->IsAllowedToMove(guid))
689 {
690 // @todo log or kick or do nothing depending on configuration
691 TC_LOG_DEBUG("entities.unit", "set active mover FAILED for client of player {}. GUID {}.", _player->GetName(), guid.ToString());
692 return;
693 }
694
695 // step 2:
696 TC_LOG_DEBUG("entities.unit", "set active mover OK for client of player {}. GUID {}.", _player->GetName(), guid.ToString());
697 Unit* newActivelyMovedUnit = ObjectAccessor::GetUnit(*_player, guid);
698 client->SetActivelyMovedUnit(newActivelyMovedUnit);
699}
700
702{
703 TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
704
705 ObjectGuid old_mover_guid;
706 recvData >> old_mover_guid.ReadAsPacked();
707 recvData.rfinish(); // prevent warnings spam.
708 // the movement info in this kind of packet is ignored for now. It's unclear if it should be used.
709
710 GameClient* client = GetGameClient();
711
712 if (client->GetActivelyMovedUnit() == nullptr || client->GetActivelyMovedUnit()->GetGUID() != old_mover_guid)
713 {
714 TC_LOG_DEBUG("entities.unit", "unset active mover FAILED for client of player {}. GUID {}.", _player->GetName(), old_mover_guid.ToString());
715 return;
716 }
717
718 TC_LOG_DEBUG("entities.unit", "unset active mover OK for client of player {}. GUID {}.", _player->GetName(), old_mover_guid.ToString());
719 client->SetActivelyMovedUnit(nullptr);
720}
721
723{
725 data << GetPlayer()->GetGUID();
726
727 GetPlayer()->SendMessageToSet(&data, false);
728}
729
731{
732 TC_LOG_DEBUG("network", "CMSG_MOVE_KNOCK_BACK_ACK");
733
734 ObjectGuid guid;
735 recvData >> guid.ReadAsPacked();
736
737 GameClient* client = GetGameClient();
738
739 // ACK handlers should call GameClient::IsAllowedToMove instead of WorldSession::IsRightUnitBeingMoved
740 // because the ACK could be coming from a unit that is under the control of that client but is not the 'Active Mover' unit.
741 // Example: Get a speed buff on yourself, then mount a vehicle before the end of the buff. When the buff expires,
742 // a force message will be sent to the client regarding the player and the client is required to respond with an ACK.
743 // But the vehicle will be the active mover unit at that time.
744 if (!client->IsAllowedToMove(guid))
745 {
746 recvData.rfinish(); // prevent warnings spam
747 return;
748 }
749
750 Unit* mover = ObjectAccessor::GetUnit(*_player, guid);
751 ASSERT(mover);
752
753 recvData.read_skip<uint32>(); // unk
754
755 MovementInfo movementInfo;
756 movementInfo.guid = guid;
757 ReadMovementInfo(recvData, &movementInfo);
758 movementInfo.time = AdjustClientMovementTime(movementInfo.time);
759
760 mover->m_movementInfo = movementInfo;
761 mover->UpdatePosition(movementInfo.pos);
762
764 WriteMovementInfo(&data, &movementInfo);
765
766 // knockback specific info
767 data << movementInfo.jump.sinAngle;
768 data << movementInfo.jump.cosAngle;
769 data << movementInfo.jump.xyspeed;
770 data << movementInfo.jump.zspeed;
771
772 client->GetBasePlayer()->SendMessageToSet(&data, false);
773}
774
776{
777 TC_LOG_DEBUG("network", "CMSG_MOVE_HOVER_ACK");
778
779 ObjectGuid guid; // guid - unused
780 recvData >> guid.ReadAsPacked();
781
782 GameClient* client = GetGameClient();
783 if (!client->IsAllowedToMove(guid))
784 {
785 recvData.rfinish(); // prevent warnings spam
786 return;
787 }
788
789 recvData.read_skip<uint32>(); // unk
790
791 MovementInfo movementInfo;
792 movementInfo.guid = guid;
793 ReadMovementInfo(recvData, &movementInfo);
794
795 recvData.read_skip<uint32>(); // unk2
796}
797
799{
800 TC_LOG_DEBUG("network", "CMSG_MOVE_WATER_WALK_ACK");
801
802 ObjectGuid guid; // guid - unused
803 recvData >> guid.ReadAsPacked();
804
805 GameClient* client = GetGameClient();
806 if (!client->IsAllowedToMove(guid))
807 {
808 recvData.rfinish(); // prevent warnings spam
809 return;
810 }
811
812 recvData.read_skip<uint32>(); // unk
813
814 MovementInfo movementInfo;
815 movementInfo.guid = guid;
816 ReadMovementInfo(recvData, &movementInfo);
817
818 recvData.read_skip<uint32>(); // unk2
819}
820
822{
823 TC_LOG_DEBUG("network", "CMSG_MOVE_FORCE_ROOT_ACK");
824
825 ObjectGuid guid; // guid - unused
826 recvData >> guid.ReadAsPacked();
827
828 GameClient* client = GetGameClient();
829 if (!client->IsAllowedToMove(guid))
830 {
831 recvData.rfinish(); // prevent warnings spam
832 return;
833 }
834
835 recvData.read_skip<uint32>(); // unk
836
837 MovementInfo movementInfo;
838 movementInfo.guid = guid;
839 ReadMovementInfo(recvData, &movementInfo);
840}
841
843{
844 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_FEATHER_FALL_ACK");
845
846 ObjectGuid guid; // guid - unused
847 recvData >> guid.ReadAsPacked();
848
849 GameClient* client = GetGameClient();
850 if (!client->IsAllowedToMove(guid))
851 {
852 recvData.rfinish(); // prevent warnings spam
853 return;
854 }
855
856 recvData.read_skip<uint32>(); // unk
857
858 MovementInfo movementInfo;
859 movementInfo.guid = guid;
860 ReadMovementInfo(recvData, &movementInfo);
861
862 recvData.read_skip<uint32>(); // unk2
863}
864
866{
867 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_FORCE_UNROOT_ACK");
868
869 ObjectGuid guid; // guid - unused
870 recvData >> guid.ReadAsPacked();
871
872 GameClient* client = GetGameClient();
873 if (!client->IsAllowedToMove(guid))
874 {
875 recvData.rfinish(); // prevent warnings spam
876 return;
877 }
878
879 recvData.read_skip<uint32>(); // unk
880
881 MovementInfo movementInfo;
882 movementInfo.guid = guid;
883 ReadMovementInfo(recvData, &movementInfo);
884}
885
887{
888 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
889
890 ObjectGuid guid; // guid - unused
891 recvData >> guid.ReadAsPacked();
892
893 GameClient* client = GetGameClient();
894 if (!client->IsAllowedToMove(guid))
895 {
896 recvData.rfinish(); // prevent warnings spam
897 return;
898 }
899
900 recvData.read_skip<uint32>(); // unk
901
902 MovementInfo movementInfo;
903 movementInfo.guid = guid;
904 ReadMovementInfo(recvData, &movementInfo);
905
906 recvData.read_skip<uint32>(); // unk2
907}
908
910{
911 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK");
912
913 ObjectGuid guid;
914 recvData >> guid.ReadAsPacked();
915
916 GameClient* client = GetGameClient();
917 if (!client->IsAllowedToMove(guid))
918 {
919 recvData.rfinish(); // prevent warnings spam
920 return;
921 }
922
923 recvData.read_skip<uint32>(); // unk
924
925 MovementInfo movementInfo;
926 movementInfo.guid = guid;
927 ReadMovementInfo(recvData, &movementInfo);
928
929 recvData.read_skip<uint32>(); // unk2
930}
931
933{
934 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_DISABLE_ACK");
935
936 ObjectGuid guid;
937 recvData >> guid.ReadAsPacked();
938
939 GameClient* client = GetGameClient();
940 if (!client->IsAllowedToMove(guid))
941 {
942 recvData.rfinish(); // prevent warnings spam
943 return;
944 }
945
946 recvData.read_skip<uint32>(); // unk
947
948 MovementInfo movementInfo;
949 movementInfo.guid = guid;
950 ReadMovementInfo(recvData, &movementInfo);
951}
952
954{
955 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_GRAVITY_ENABLE_ACK");
956
957 ObjectGuid guid;
958 recvData >> guid.ReadAsPacked();
959
960 GameClient* client = GetGameClient();
961 if (!client->IsAllowedToMove(guid))
962 {
963 recvData.rfinish(); // prevent warnings spam
964 return;
965 }
966
967 recvData.read_skip<uint32>(); // unk
968
969 MovementInfo movementInfo;
970 movementInfo.guid = guid;
971 ReadMovementInfo(recvData, &movementInfo);
972}
973
975{
976 TC_LOG_DEBUG("network", "WORLD: CMSG_MOVE_SET_COLLISION_HGT_ACK");
977
978 ObjectGuid guid;
979 float newValue;
980 recvData >> guid.ReadAsPacked();
981
982 GameClient* client = GetGameClient();
983 if (!client->IsAllowedToMove(guid))
984 {
985 recvData.rfinish(); // prevent warnings spam
986 return;
987 }
988
989 recvData.read_skip<uint32>(); // movement counter
990
991 MovementInfo movementInfo;
992 movementInfo.guid = guid;
993 ReadMovementInfo(recvData, &movementInfo);
994
995 recvData >> newValue;
996}
997
999{
1000 if (!_player->IsAlive() || _player->IsInCombat())
1001 return;
1002
1003 ObjectGuid summonerGuid;
1004 bool agree;
1005 recvData >> summonerGuid;
1006 recvData >> agree;
1007
1008 _player->SummonIfPossible(agree);
1009}
1010
1012{
1013 TC_LOG_DEBUG("network", "WORLD: Received CMSG_MOVE_TIME_SKIPPED");
1014
1015 ObjectGuid guid;
1016 uint32 timeSkipped;
1017 recvData >> guid.ReadAsPacked();
1018 recvData >> timeSkipped;
1019
1020 Unit* mover = ValidateAndGetUnitBeingMoved(guid, static_cast<OpcodeClient>(recvData.GetOpcode()), false);
1021 if (!mover)
1022 {
1023 recvData.rfinish(); // prevent warnings spam
1024 return;
1025 }
1026
1027 mover->m_movementInfo.time += timeSkipped;
1028
1029 WorldPacket data(MSG_MOVE_TIME_SKIPPED, recvData.size());
1030 data << guid.WriteAsPacked();
1031 data << timeSkipped;
1032 GetPlayer()->SendMessageToSet(&data, false);
1033}
1034
1036{
1037 if (_pendingTimeSyncRequests.count(packet.SequenceIndex) == 0)
1038 return;
1039
1040 uint32 serverTimeAtSent = _pendingTimeSyncRequests.at(packet.SequenceIndex);
1042
1043 // 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.
1044 // we are going to make 2 assumptions:
1045 // 1) we assume that the request processing time equals 0.
1046 // 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.
1047 uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent, packet.GetReceivedTime());
1048 uint32 lagDelay = roundTripDuration / 2;
1049
1050 /*
1051 clockDelta = serverTime - clientTime
1052 where
1053 serverTime: time that was displayed on the clock of the SERVER at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
1054 clientTime: time that was displayed on the clock of the CLIENT at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
1055
1056 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,
1057 using the following relation:
1058 serverTime = clockDelta + clientTime
1059 */
1060 int64 clockDelta = (int64)serverTimeAtSent + (int64)lagDelay - (int64)packet.ClientTime;
1061 _timeSyncClockDeltaQueue->push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
1063}
1064
1066{
1067 // implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
1068 // to reduce the skew induced by dropped TCP packets that get resent.
1069
1070 using namespace boost::accumulators;
1071
1072 accumulator_set<uint32, features<tag::mean, tag::median, tag::variance(lazy)> > latencyAccumulator;
1073
1074 for (auto [_, roundTripDuration] : *_timeSyncClockDeltaQueue)
1075 latencyAccumulator(roundTripDuration);
1076
1077 uint32 latencyMedian = static_cast<uint32>(std::round(median(latencyAccumulator)));
1078 uint32 latencyStandardDeviation = static_cast<uint32>(std::round(sqrt(variance(latencyAccumulator))));
1079
1080 accumulator_set<int64, features<tag::mean> > clockDeltasAfterFiltering;
1081 uint32 sampleSizeAfterFiltering = 0;
1082 for (auto [clockDelta, roundTripDuration] : *_timeSyncClockDeltaQueue)
1083 {
1084 if (roundTripDuration < latencyStandardDeviation + latencyMedian) {
1085 clockDeltasAfterFiltering(clockDelta);
1086 sampleSizeAfterFiltering++;
1087 }
1088 }
1089
1090 if (sampleSizeAfterFiltering != 0)
1091 {
1092 int64 meanClockDelta = static_cast<int64>(std::round(mean(clockDeltasAfterFiltering)));
1093 if (std::abs(meanClockDelta - _timeSyncClockDelta) > 25)
1094 _timeSyncClockDelta = meanClockDelta;
1095 }
1096 else if (_timeSyncClockDelta == 0)
1098}
@ SEC_PLAYER
Definition Common.h:40
@ VEHICLE_SEAT_FLAG_ALLOW_TURNING
Definition DBCEnums.h:477
Difficulty
Definition DBCEnums.h:279
MapDifficultyEntry 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:685
@ TELE_REVIVE_AT_TELEPORT
Definition Player.h:673
@ PLAYER_FLAGS_IN_PVP
Definition Player.h:355
@ PLAYER_FLAGS_IS_OUT_OF_BOUNDS
Definition Player.h:360
@ 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:88
float playerBaseMoveSpeed[MAX_MOVE_TYPE]
Definition Unit.cpp:101
MovementChangeType
Definition Unit.h:289
@ 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:334
void rfinish()
Definition ByteBuffer.h:320
size_t size() const
Definition ByteBuffer.h:413
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:302
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:4425
virtual EnterState CannotEnter(Player *)
Definition Map.h:429
Difficulty GetDifficultyID() const
Definition Map.h:433
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:4435
MovementGenerator * GetCurrentMovementGenerator() const
virtual bool Initialize(Unit *)=0
static void SendSpeedChangeToObservers(Unit *unit, UnitMoveType mtype, float newRate)
bool Finalized() const
Definition MoveSpline.h:133
bool Initialized() const
Definition MoveSpline.h:110
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:761
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:776
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:800
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
ObjectGuid GetGUID() const
Definition Object.h:79
static Player * ToPlayer(Object *o)
Definition Object.h:183
void SetSemaphoreTeleportNear(bool semphsetting)
Definition Player.h:1809
void SendInitialPacketsAfterAddToMap()
Definition Player.cpp:22470
WorldLocation const & GetCorpseLocation() const
Definition Player.h:1744
bool m_InstanceValid
Definition Player.h:2132
WorldLocation & GetTeleportDest()
Definition Player.h:1804
void SetBGTeam(uint32 team)
Definition Player.cpp:21941
float m_homebindZ
Definition Player.h:2077
bool IsBeingTeleportedFar() const
Definition Player.h:1808
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
Definition Player.cpp:638
void KillPlayer()
Definition Player.cpp:4462
uint32 m_homebindMapId
Definition Player.h:2073
void CheckOutdoorsAuraRequirements()
Definition Player.cpp:6265
void HandleFall()
Definition Player.cpp:24833
bool InBattleground() const
Definition Player.h:1969
void SpawnCorpseBones(bool triggerSave=true)
Definition Player.cpp:4555
void UpdateZone(uint32 newZone, uint32 newArea)
Definition Player.cpp:6805
void SetFallInformation(uint32 time, float z)
Definition Player.cpp:24827
void SendInitialPacketsBeforeAddToMap()
Definition Player.cpp:22405
void ResetMap() override
Definition Player.cpp:25505
WorldSession * GetSession() const
Definition Player.h:1705
bool IsInvitedForBattlegroundInstance(uint32 instanceId) const
Definition Player.cpp:23115
void UpdateFallInformationIfNeed(MovementInfo const &minfo, uint16 opcode)
Definition Player.cpp:25162
void SetSemaphoreTeleportFar(bool semphsetting)
Definition Player.h:1810
void FinishTaxiFlight()
Definition Player.cpp:21199
Battleground * GetBattleground() const
Definition Player.cpp:23024
void ProcessDelayedOperations()
Definition Player.cpp:1792
float m_homebindY
Definition Player.h:2076
bool UpdatePosition(float x, float y, float z, float orientation, bool teleport=false) override
Definition Player.cpp:6105
uint32 GetTeleportOptions() const
Definition Player.h:1805
PvPInfo pvpInfo
Definition Player.h:1567
void SummonIfPossible(bool agree)
Definition Player.cpp:23305
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1539
bool IsBeingTeleportedNear() const
Definition Player.h:1807
bool CheckInstanceValidity(bool)
Definition Player.cpp:18872
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time, bool welcome) const
Definition Player.cpp:22573
uint32 GetBattlegroundId() const
Definition Player.h:1971
void SetMap(Map *map) override
Definition Player.cpp:25517
std::string GetDebugInfo() const override
Definition Player.cpp:26486
void SendMessageToSet(WorldPacket const *data, bool self) const override
Definition Player.h:1733
void ResummonPetTemporaryUnSummonedIfAny()
Definition Player.cpp:25183
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId)
Definition Player.cpp:23067
void UpdatePvP(bool state, bool override=false)
Definition Player.cpp:21684
bool IsBeingTeleported() const
Definition Player.h:1806
float m_homebindX
Definition Player.h:2075
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:4374
void RemovePassenger(WorldObject *passenger)
Definition Unit.h:783
Vehicle * GetVehicle() const
Definition Unit.h:1753
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3788
Movement::MoveSpline * movespline
Definition Unit.h:1820
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
Definition Unit.cpp:4045
Emote GetEmoteState() const
Definition Unit.h:980
PlayerMovementPendingChange PopPendingMovementChange()
Definition Unit.cpp:12929
bool IsPvP() const
Definition Unit.h:1002
MotionMaster * GetMotionMaster()
Definition Unit.h:1683
bool IsAlive() const
Definition Unit.h:1247
PlayerMovementPendingChange & PeakFirstPendingMovementChange()
Definition Unit.cpp:12924
void SetSpeedRateReal(UnitMoveType mtype, float rate)
Definition Unit.cpp:8647
void SetEmoteState(Emote emote)
Definition Unit.h:981
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition Unit.cpp:12866
bool IsInFlight() const
Definition Unit.h:1133
float GetHoverOffset() const
Definition Unit.h:1783
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4565
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10340
bool IsControlledByPlayer() const
Definition Unit.h:1271
bool IsInCombat() const
Definition Unit.h:1158
bool IsSitState() const
Definition Unit.cpp:10325
bool HasPendingMovementChange() const
Definition Unit.h:1792
uint32 GetMapId() const
Definition Position.h:193
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1784
Map * GetMap() const
Definition Object.h:451
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2833
std::string const & GetName() const
Definition Object.h:384
Transport * GetTransport() const
Definition Object.h:566
uint32 GetZoneId() const
Definition Object.h:375
MovementInfo m_movementInfo
Definition Object.h:577
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:377
uint16 GetOpcode() const
Definition WorldPacket.h:58
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 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)
std::string GetPlayerInfo() const
void KickPlayer(std::string const &reason)
Kick a player out of the World.
void HandleMoveWorldportAckOpcode(WorldPackets::Movement::WorldPortResponse &packet)
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
Unit * ValidateAndGetUnitBeingMoved(ObjectGuid guid, OpcodeClient opcode, bool forStatusAck) const
void HandleMoveSetCanFlyAckOpcode(WorldPacket &recvData)
std::unique_ptr< boost::circular_buffer< std::pair< int64, uint32 > > > _timeSyncClockDeltaQueue
void HandleMoveNotActiveMover(WorldPacket &recvData)
GameClient * GetGameClient() const
void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse &packet)
void HandleSetActiveMoverOpcode(WorldPacket &recvData)
void HandleMoveKnockBackAck(WorldPacket &recvPacket)
void HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck &packet)
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:901
@ CONFIG_PENDING_MOVE_CHANGES_TIMEOUT
Definition World.h:404
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
ObjectGuid guid
void RemoveMovementFlag(uint32 flag)
struct MovementInfo::TransportInfo transport
bool HasMovementFlag(uint32 flag) const
Position pos
MovementChangeType movementChangeType
Definition Unit.h:320
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:246