Remove the pointer to the deallocated chunk from the current player/NPC.

This fixes the Great Crash Bug(tm).
This commit is contained in:
dongresource 2020-10-15 04:36:38 +02:00
parent 5784e77654
commit 5a80c53e79
6 changed files with 43 additions and 15 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ build/
.idea/ .idea/
*.db *.db
version.h version.h
infer-out

View File

@ -37,30 +37,44 @@ void ChunkManager::addPlayer(int posX, int posY, int instanceID, CNSocket* sock)
chunk->players.insert(sock); chunk->players.insert(sock);
} }
void ChunkManager::removePlayer(std::tuple<int, int, int> chunkPos, CNSocket* sock) { bool ChunkManager::removePlayer(std::tuple<int, int, int> chunkPos, CNSocket* sock) {
if (!checkChunk(chunkPos)) 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* chunk = chunks[chunkPos];
chunk->players.erase(sock); // gone chunk->players.erase(sock); // gone
// if players and NPCs are empty, free chunk and remove it from surrounding views // 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); destroyChunk(chunkPos);
// the chunk we left was destroyed
return true;
}
// the chunk we left was not destroyed
return false;
} }
void ChunkManager::removeNPC(std::tuple<int, int, int> chunkPos, int32_t id) { bool ChunkManager::removeNPC(std::tuple<int, int, int> chunkPos, int32_t id) {
if (!checkChunk(chunkPos)) 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* chunk = chunks[chunkPos];
chunk->NPCs.erase(id); // gone chunk->NPCs.erase(id); // gone
// if players and NPCs are empty, free chunk and remove it from surrounding views // 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); destroyChunk(chunkPos);
// the chunk we left was destroyed
return true;
}
// the chunk we left was not destroyed
return false;
} }
void ChunkManager::destroyChunk(std::tuple<int, int, int> chunkPos) { void ChunkManager::destroyChunk(std::tuple<int, int, int> chunkPos) {

View File

@ -28,8 +28,8 @@ namespace ChunkManager {
void addNPC(int posX, int posY, int instanceID, int32_t id); void addNPC(int posX, int posY, int instanceID, int32_t id);
void addPlayer(int posX, int posY, int instanceID, CNSocket* sock); void addPlayer(int posX, int posY, int instanceID, CNSocket* sock);
void removePlayer(std::tuple<int, int, int> chunkPos, CNSocket* sock); bool removePlayer(std::tuple<int, int, int> chunkPos, CNSocket* sock);
void removeNPC(std::tuple<int, int, int> chunkPos, int32_t id); bool removeNPC(std::tuple<int, int, int> chunkPos, int32_t id);
bool checkChunk(std::tuple<int, int, int> chunk); bool checkChunk(std::tuple<int, int, int> chunk);
void destroyChunk(std::tuple<int, int, int> chunkPos); void destroyChunk(std::tuple<int, int, int> chunkPos);
std::tuple<int, int, int> grabChunk(int posX, int posY, int instanceID); std::tuple<int, int, int> grabChunk(int posX, int posY, int instanceID);

View File

@ -126,7 +126,7 @@ void NPCManager::destroyNPC(int32_t id) {
// remove from mob manager // remove from mob manager
if (MobManager::Mobs.find(id) != MobManager::Mobs.end()) 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 // finally, remove it from the map and free it
NPCs.erase(id); 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 // send npc enter to new chunks
addNPC(ChunkManager::getDeltaChunks(allChunks, npc->currentChunks), id); addNPC(ChunkManager::getDeltaChunks(allChunks, npc->currentChunks), id);
// update chunks Chunk *chunk = nullptr;
ChunkManager::removeNPC(npc->chunkPos, id); 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); ChunkManager::addNPC(X, Y, npc->instanceID, id);
npc->chunkPos = newPos; npc->chunkPos = newPos;

View File

@ -85,7 +85,7 @@ void PlayerManager::removePlayer(CNSocket* key) {
std::cout << players.size() << " players" << std::endl; std::cout << players.size() << " players" << std::endl;
} }
void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) { bool PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer); INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer);
// for chunks that need the player to be removed from // for chunks that need the player to be removed from
@ -119,7 +119,7 @@ void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket*
} }
// remove us from that old stinky chunk // 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<Chunk*> chunks, CNSocket* sock) { void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
@ -205,8 +205,14 @@ void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y) {
// add player to chunk // add player to chunk
std::vector<Chunk*> allChunks = ChunkManager::grabChunks(newPos); std::vector<Chunk*> 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 // 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! // now, add all the new npcs & players!
addPlayerToChunks(ChunkManager::getDeltaChunks(allChunks, view.currentChunks), sock); addPlayerToChunks(ChunkManager::getDeltaChunks(allChunks, view.currentChunks), sock);

View File

@ -27,7 +27,7 @@ namespace PlayerManager {
void addPlayer(CNSocket* key, Player plr); void addPlayer(CNSocket* key, Player plr);
void removePlayer(CNSocket* key); void removePlayer(CNSocket* key);
void removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock); bool removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock);
void addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock); void addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock);
void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z); void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z);