From e97b58ccaf13ed0ed6f45cfccd622bc3b2d89c13 Mon Sep 17 00:00:00 2001 From: dongresource Date: Mon, 19 Oct 2020 04:30:12 +0200 Subject: [PATCH] Fixed private instance memory leaks. --- src/ChunkManager.cpp | 16 ++++++++++++++++ src/ChunkManager.hpp | 1 + src/NPCManager.cpp | 11 +---------- src/PlayerManager.cpp | 13 +++++++++---- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index bc53470..45e5f24 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -236,3 +236,19 @@ void ChunkManager::destroyInstance(uint64_t instanceID) { destroyChunk(coords); } } + +void ChunkManager::destroyInstanceIfEmpty(uint64_t instanceID) { + if (PLAYERID(instanceID) == 0) + return; // don't clean up overworld/IZ chunks + + std::vector> sourceChunkCoords = getChunksInMap(instanceID); + + for (std::tuple& coords : sourceChunkCoords) { + Chunk* chunk = chunks[coords]; + + if (chunk->players.size() > 0) + return; // there are still players inside + } + + destroyInstance(instanceID); +} diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 2a8a049..22c3328 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -40,4 +40,5 @@ namespace ChunkManager { void createInstance(uint64_t); void destroyInstance(uint64_t); + void destroyInstanceIfEmpty(uint64_t); } diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 0f9f6af..ffd7234 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -628,16 +628,7 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) { } // post-warp: check if the source instance has no more players in it and delete it if so - if (PLAYERID(fromInstance) == 0) - return; // don't clean up overworld/IZ chunks - - std::vector> sourceChunkCoords = ChunkManager::getChunksInMap(fromInstance); - for (std::tuple& coords : sourceChunkCoords) { - Chunk* chunk = ChunkManager::chunks[coords]; - if (chunk->players.size() > 0) - return; // there are still players inside - } - ChunkManager::destroyInstance(fromInstance); + ChunkManager::destroyInstanceIfEmpty(fromInstance); } /* diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 90365fe..97cdb1e 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -64,6 +64,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) { void PlayerManager::removePlayer(CNSocket* key) { PlayerView& view = players[key]; + uint64_t fromInstance = view.plr->instanceID; //MissionManager::failInstancedMissions(key); moved to enter GroupManager::groupKickPlayer(view.plr); @@ -71,9 +72,6 @@ void PlayerManager::removePlayer(CNSocket* key) { // save player to DB Database::updatePlayer(view.plr); - INITSTRUCT(sP_FE2CL_PC_EXIT, exitPacket); - exitPacket.iID = players[key].plr->iID; - // remove players from all chunks removePlayerFromChunks(view.currentChunks, key); @@ -87,6 +85,9 @@ void PlayerManager::removePlayer(CNSocket* key) { delete view.plr; players.erase(key); + // if the player was in a lair, clean it up + ChunkManager::destroyInstanceIfEmpty(fromInstance); + std::cout << players.size() << " players" << std::endl; } @@ -230,6 +231,9 @@ void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y, uint64_t ins void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I) { PlayerView& plrv = PlayerManager::players[sock]; Player* plr = plrv.plr; + + uint64_t fromInstance = plr->instanceID; + plr->instanceID = I; if (I != INSTANCE_OVERWORLD) { INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt); @@ -250,7 +254,8 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I plrv.currentChunks.clear(); sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC)); } - + + ChunkManager::destroyInstanceIfEmpty(fromInstance); } void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z) {