From 11747f6a5022aec120ceedd8fd86dd409d23e224 Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Sun, 19 Jul 2026 06:27:43 -0400 Subject: [PATCH] fix(Core/Transports): Exclude out of world players from receiving transport creations/removes. (#26680) Co-authored-by: Claude --- src/server/game/Handlers/MovementHandler.cpp | 9 +++++++++ src/server/game/Maps/Map.cpp | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 46140f5a4..d809747c5 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -35,6 +35,7 @@ #include "ScriptMgr.h" #include "SpellAuras.h" #include "Transport.h" +#include "UpdateData.h" #include "Vehicle.h" #include "WaypointMovementGenerator.h" #include "WorldPacket.h" @@ -129,6 +130,14 @@ void WorldSession::HandleMoveWorldportAck() if (Transport* t = _player->GetTransport()) if (!t->IsInMap(_player)) { + // Client was never told to destroy its own transport + // Destroy it now or it keeps a phantom copy of the transport on the new map + UpdateData transData; + t->BuildOutOfRangeUpdateBlock(&transData); + WorldPacket packet; + transData.BuildPacket(packet); + _player->SendDirectMessage(&packet); + t->RemovePassenger(_player); _player->m_transport = nullptr; _player->m_movementInfo.transport.Reset(); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 13b4e1bfb..b47e4c5fc 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -376,9 +376,12 @@ bool Map::AddToMap(Transport* obj, bool /*checkTransport*/) _transports.insert(obj); // Broadcast creation to players + // Skip players that are not in world. Sending the create to their loading client + // could materialize a lingering transport on whatever map they are teleporting to. + // They get the correct transport list from SendInitTransports when added to their new map for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { - if (itr->GetSource()->GetTransport() != obj) + if (itr->GetSource()->IsInWorld() && itr->GetSource()->GetTransport() != obj) { UpdateData data; obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource()); @@ -761,8 +764,10 @@ void Map::RemoveFromMap(Transport* obj, bool remove) obj->BuildOutOfRangeUpdateBlock(&data); WorldPacket packet; data.BuildPacket(packet); + // Skip players that are not in world + // Their client already received the destroy from SendRemoveTransports when leaving this map for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - if (itr->GetSource()->GetTransport() != obj) + if (itr->GetSource()->IsInWorld() && itr->GetSource()->GetTransport() != obj) itr->GetSource()->SendDirectMessage(&packet); }