From 922177abe03fb020ec001c6ca875f39fb921dd45 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 20 Mar 2026 18:05:09 -0700 Subject: [PATCH] fix: invoke despawn callbacks during zone transitions to release renderer resources handleNewWorld() previously called entityManager.clear() directly without notifying the renderer, leaving stale M2 instances and character models allocated. Now iterates all entities and fires creatureDespawnCallback, playerDespawnCallback, and gameObjectDespawnCallback before clearing. Also clears player caches (visible items, cast states, aura cache, combat text) to prevent state leaking between zones. --- src/game/game_handler.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index a2a0cc51..a0a84fad 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -23063,7 +23063,24 @@ void GameHandler::handleNewWorld(network::Packet& packet) { mountCallback_(0); } - // Clear world state for the new map + // Invoke despawn callbacks for all entities before clearing, so the renderer + // can release M2 instances, character models, and associated resources. + for (const auto& [guid, entity] : entityManager.getEntities()) { + if (guid == playerGuid) continue; // skip self + if (entity->getType() == ObjectType::UNIT && creatureDespawnCallback_) { + creatureDespawnCallback_(guid); + } else if (entity->getType() == ObjectType::PLAYER && playerDespawnCallback_) { + playerDespawnCallback_(guid); + } else if (entity->getType() == ObjectType::GAMEOBJECT && gameObjectDespawnCallback_) { + gameObjectDespawnCallback_(guid); + } + } + otherPlayerVisibleItemEntries_.clear(); + otherPlayerVisibleDirty_.clear(); + otherPlayerMoveTimeMs_.clear(); + unitCastStates_.clear(); + unitAurasCache_.clear(); + combatText.clear(); entityManager.clear(); hostileAttackers_.clear(); worldStates_.clear();