mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-05 04:33:51 +00:00
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:
parent
baab997da8
commit
54246345bb
3 changed files with 13 additions and 8 deletions
|
|
@ -666,8 +666,8 @@ public:
|
|||
uint32_t getSkillCategory(uint32_t skillId) const;
|
||||
|
||||
// World entry callback (online mode - triggered when entering world)
|
||||
// Parameters: mapId, x, y, z (canonical WoW coordinates)
|
||||
using WorldEntryCallback = std::function<void(uint32_t mapId, float x, float y, float z)>;
|
||||
// Parameters: mapId, x, y, z (canonical WoW coords), isInitialEntry=true on first login or reconnect
|
||||
using WorldEntryCallback = std::function<void(uint32_t mapId, float x, float y, float z, bool isInitialEntry)>;
|
||||
void setWorldEntryCallback(WorldEntryCallback cb) { worldEntryCallback_ = std::move(cb); }
|
||||
|
||||
// Unstuck callback (resets player Z to floor height)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -499,6 +499,8 @@ void GameHandler::disconnect() {
|
|||
wardenModuleSize_ = 0;
|
||||
wardenModuleData_.clear();
|
||||
wardenLoadedModule_.reset();
|
||||
// Clear entity state so reconnect sees fresh CREATE_OBJECT for all visible objects.
|
||||
entityManager.clear();
|
||||
setState(WorldState::DISCONNECTED);
|
||||
LOG_INFO("Disconnected from world server");
|
||||
}
|
||||
|
|
@ -6074,7 +6076,7 @@ void GameHandler::handleLoginVerifyWorld(network::Packet& packet) {
|
|||
|
||||
// Notify application to load terrain for this map/position (online mode)
|
||||
if (worldEntryCallback_) {
|
||||
worldEntryCallback_(data.mapId, data.x, data.y, data.z);
|
||||
worldEntryCallback_(data.mapId, data.x, data.y, data.z, initialWorldEntry);
|
||||
}
|
||||
|
||||
// Auto-join default chat channels
|
||||
|
|
@ -15582,7 +15584,7 @@ void GameHandler::handleTeleportAck(network::Packet& packet) {
|
|||
// Notify application of teleport — the callback decides whether to do
|
||||
// a full world reload (map change) or just update position (same map).
|
||||
if (worldEntryCallback_) {
|
||||
worldEntryCallback_(currentMapId_, serverX, serverY, serverZ);
|
||||
worldEntryCallback_(currentMapId_, serverX, serverY, serverZ, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -15689,7 +15691,7 @@ void GameHandler::handleNewWorld(network::Packet& packet) {
|
|||
|
||||
// Reload terrain at new position
|
||||
if (worldEntryCallback_) {
|
||||
worldEntryCallback_(mapId, serverX, serverY, serverZ);
|
||||
worldEntryCallback_(mapId, serverX, serverY, serverZ, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue