fix: Clean visibility references before bot teleport to prevent crash

Add PLAYERHOOK_ON_BEFORE_TELEPORT to proactively clean visibility
references when a bot teleports between maps. This prevents a race
condition where:
1. Bot A teleports and its visible objects start getting cleaned up
2. Bot B is simultaneously updating visibility and tries to access
   objects in Bot A's old visibility map
3. Those objects may already be freed, causing a segmentation fault
   at GridNotifiers.cpp:65 in IsWorldObjectOutOfSightRange()

The fix only affects bots to avoid changing behavior for real players.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-10-05 16:15:09 +11:00
parent 21ea3a7226
commit d26c2a3549

View File

@@ -87,7 +87,8 @@ public:
PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS,
PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE,
PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
PLAYERHOOK_ON_GIVE_EXP
PLAYERHOOK_ON_GIVE_EXP,
PLAYERHOOK_ON_BEFORE_TELEPORT
}) {}
void OnPlayerLogin(Player* player) override
@@ -121,6 +122,26 @@ public:
}
}
bool OnPlayerBeforeTeleport(Player* player, uint32 mapid, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override
{
// Only apply to bots to prevent affecting real players
if (!player || !player->GetSession()->IsBot())
return true;
// If changing maps, proactively clean visibility references to prevent
// stale pointers in other players' visibility maps during the teleport.
// This fixes a race condition where:
// 1. Bot A teleports and its visible objects start getting cleaned up
// 2. Bot B is simultaneously updating visibility and tries to access objects in Bot A's old visibility map
// 3. Those objects may already be freed, causing a segmentation fault
if (player->GetMapId() != mapid && player->IsInWorld())
{
player->GetObjectVisibilityContainer().CleanVisibilityReferences();
}
return true; // Allow teleport to continue
}
void OnPlayerAfterUpdate(Player* player, uint32 diff) override
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))