game: fix NPCs not spawning on reconnect to same map

On disconnect/reconnect to the same map, entityManager was not cleared
and creatureInstances_ still held old entries from the previous session.
When the server re-sent CREATE_OBJECT for the same GUIDs, the spawn
callback's early-return guard (creatureInstances_.count(guid)) silently
dropped every NPC re-spawn, leaving the world empty.

Fixes:
- disconnect() now calls entityManager.clear() to purge stale entities
- WorldEntryCallback gains a bool isInitialEntry parameter (true on first
  login or reconnect, false on in-world teleport/flight landing)
- Same-map optimization path skipped when isInitialEntry=true, so
  loadOnlineWorldTerrain runs its full cleanup and properly despawns old
  creature/player instances before the server refreshes them
This commit is contained in:
Kelsi 2026-03-10 08:35:36 -07:00
parent baab997da8
commit 54246345bb
3 changed files with 13 additions and 8 deletions

View file

@ -1692,13 +1692,16 @@ void Application::setupUICallbacks() {
});
// World entry callback (online mode) - load terrain when entering world
gameHandler->setWorldEntryCallback([this](uint32_t mapId, float x, float y, float z) {
LOG_INFO("Online world entry: mapId=", mapId, " pos=(", x, ", ", y, ", ", z, ")");
gameHandler->setWorldEntryCallback([this](uint32_t mapId, float x, float y, float z, bool isInitialEntry) {
LOG_INFO("Online world entry: mapId=", mapId, " pos=(", x, ", ", y, ", ", z, ")"
" initial=", isInitialEntry);
// Same-map teleport (taxi landing, GM teleport on same continent):
// just update position, let terrain streamer handle tile loading incrementally.
// A full reload is only needed on first entry or map change.
if (mapId == loadedMapId_ && renderer && renderer->getTerrainManager()) {
// Exception: on reconnect to the same map (isInitialEntry=true), all online entities
// are stale and must be cleared so the server's fresh CREATE_OBJECTs re-spawn them.
if (mapId == loadedMapId_ && renderer && renderer->getTerrainManager() && !isInitialEntry) {
LOG_INFO("Same-map teleport (map ", mapId, "), skipping full world reload");
glm::vec3 canonical = core::coords::serverToCanonical(glm::vec3(x, y, z));
glm::vec3 renderPos = core::coords::canonicalToRender(canonical);