From 5a80c53e796f9d2eaf7cee89f1ac61af343a1afd Mon Sep 17 00:00:00 2001 From: dongresource Date: Thu, 15 Oct 2020 04:36:38 +0200 Subject: [PATCH] Remove the pointer to the deallocated chunk from the current player/NPC. This fixes the Great Crash Bug(tm). --- .gitignore | 1 + src/ChunkManager.cpp | 26 ++++++++++++++++++++------ src/ChunkManager.hpp | 4 ++-- src/NPCManager.cpp | 13 ++++++++++--- src/PlayerManager.cpp | 12 +++++++++--- src/PlayerManager.hpp | 2 +- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 073f909..c895922 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ build/ .idea/ *.db version.h +infer-out diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index 8e2319d..8e80f53 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -37,30 +37,44 @@ void ChunkManager::addPlayer(int posX, int posY, int instanceID, CNSocket* sock) chunk->players.insert(sock); } -void ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* sock) { +bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* sock) { if (!checkChunk(chunkPos)) - return; // do nothing if chunk doesn't even exist + return false; // do nothing if chunk doesn't even exist Chunk* chunk = chunks[chunkPos]; chunk->players.erase(sock); // gone // if players and NPCs are empty, free chunk and remove it from surrounding views - if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) + if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { destroyChunk(chunkPos); + + // the chunk we left was destroyed + return true; + } + + // the chunk we left was not destroyed + return false; } -void ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { +bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { if (!checkChunk(chunkPos)) - return; // do nothing if chunk doesn't even exist + return false; // do nothing if chunk doesn't even exist Chunk* chunk = chunks[chunkPos]; chunk->NPCs.erase(id); // gone // if players and NPCs are empty, free chunk and remove it from surrounding views - if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) + if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { destroyChunk(chunkPos); + + // the chunk we left was destroyed + return true; + } + + // the chunk we left was not destroyed + return false; } void ChunkManager::destroyChunk(std::tuple chunkPos) { diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 59eb745..633b658 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -28,8 +28,8 @@ namespace ChunkManager { void addNPC(int posX, int posY, int instanceID, int32_t id); void addPlayer(int posX, int posY, int instanceID, CNSocket* sock); - void removePlayer(std::tuple chunkPos, CNSocket* sock); - void removeNPC(std::tuple chunkPos, int32_t id); + bool removePlayer(std::tuple chunkPos, CNSocket* sock); + bool removeNPC(std::tuple chunkPos, int32_t id); bool checkChunk(std::tuple chunk); void destroyChunk(std::tuple chunkPos); std::tuple grabChunk(int posX, int posY, int instanceID); diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 7663e6b..71b6b18 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -126,7 +126,7 @@ void NPCManager::destroyNPC(int32_t id) { // remove from mob manager if (MobManager::Mobs.find(id) != MobManager::Mobs.end()) - MobManager::Mobs.erase(id); + MobManager::Mobs.erase(id); // finally, remove it from the map and free it NPCs.erase(id); @@ -162,8 +162,15 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) { // send npc enter to new chunks addNPC(ChunkManager::getDeltaChunks(allChunks, npc->currentChunks), id); - // update chunks - ChunkManager::removeNPC(npc->chunkPos, id); + Chunk *chunk = nullptr; + if (ChunkManager::checkChunk(npc->chunkPos)) + chunk = ChunkManager::chunks[npc->chunkPos]; + + if (ChunkManager::removeNPC(npc->chunkPos, id)) { + // if the old chunk was deallocated, remove it + allChunks.erase(std::remove(allChunks.begin(), allChunks.end(), chunk), allChunks.end()); + } + ChunkManager::addNPC(X, Y, npc->instanceID, id); npc->chunkPos = newPos; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index f45fd88..2b3746e 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -85,7 +85,7 @@ void PlayerManager::removePlayer(CNSocket* key) { std::cout << players.size() << " players" << std::endl; } -void PlayerManager::removePlayerFromChunks(std::vector chunks, CNSocket* sock) { +bool PlayerManager::removePlayerFromChunks(std::vector chunks, CNSocket* sock) { INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer); // for chunks that need the player to be removed from @@ -119,7 +119,7 @@ void PlayerManager::removePlayerFromChunks(std::vector chunks, CNSocket* } // remove us from that old stinky chunk - ChunkManager::removePlayer(players[sock].chunkPos, sock); + return ChunkManager::removePlayer(players[sock].chunkPos, sock); } void PlayerManager::addPlayerToChunks(std::vector chunks, CNSocket* sock) { @@ -205,8 +205,14 @@ void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y) { // add player to chunk std::vector allChunks = ChunkManager::grabChunks(newPos); + Chunk *chunk = nullptr; + if (ChunkManager::checkChunk(view.chunkPos)) + chunk = ChunkManager::chunks[view.chunkPos]; + // first, remove all the old npcs & players from the old chunks - removePlayerFromChunks(ChunkManager::getDeltaChunks(view.currentChunks, allChunks), sock); + if (removePlayerFromChunks(ChunkManager::getDeltaChunks(view.currentChunks, allChunks), sock)) { + allChunks.erase(std::remove(allChunks.begin(), allChunks.end(), chunk), allChunks.end()); + } // now, add all the new npcs & players! addPlayerToChunks(ChunkManager::getDeltaChunks(allChunks, view.currentChunks), sock); diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index 21f100d..38ce6ae 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -27,7 +27,7 @@ namespace PlayerManager { void addPlayer(CNSocket* key, Player plr); void removePlayer(CNSocket* key); - void removePlayerFromChunks(std::vector chunks, CNSocket* sock); + bool removePlayerFromChunks(std::vector chunks, CNSocket* sock); void addPlayerToChunks(std::vector chunks, CNSocket* sock); void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z);