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/
*.db
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);
}
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))
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<int, int, int> chunkPos, int32_t id) {
bool ChunkManager::removeNPC(std::tuple<int, int, int> 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<int, int, int> chunkPos) {

View File

@ -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<int, int, int> chunkPos, CNSocket* sock);
void removeNPC(std::tuple<int, int, int> chunkPos, int32_t id);
bool removePlayer(std::tuple<int, int, int> chunkPos, CNSocket* sock);
bool removeNPC(std::tuple<int, int, int> chunkPos, int32_t id);
bool checkChunk(std::tuple<int, int, int> chunk);
void destroyChunk(std::tuple<int, int, int> chunkPos);
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
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;

View File

@ -85,7 +85,7 @@ void PlayerManager::removePlayer(CNSocket* key) {
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);
// 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
ChunkManager::removePlayer(players[sock].chunkPos, sock);
return ChunkManager::removePlayer(players[sock].chunkPos, 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
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
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);

View File

@ -27,7 +27,7 @@ namespace PlayerManager {
void addPlayer(CNSocket* key, Player plr);
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 updatePlayerPosition(CNSocket* sock, int X, int Y, int Z);