From 95b385dee1c60b2f5283bd3ea543380b4540bdbb Mon Sep 17 00:00:00 2001 From: Gent S Date: Thu, 19 Nov 2020 17:19:46 -0500 Subject: [PATCH] Reimplement chunk data caching --- src/ChunkManager.cpp | 58 +++++++++++++++++++++++++++++++++---------- src/ChunkManager.hpp | 3 ++- src/MobManager.cpp | 8 +++--- src/NPC.hpp | 2 ++ src/NPCManager.cpp | 6 ++--- src/Player.hpp | 1 + src/PlayerManager.cpp | 5 ++-- 7 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index 6728909..4e90c18 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -20,6 +20,37 @@ void ChunkManager::newChunk(ChunkPos pos) { chunk->NPCs = std::set(); chunks[pos] = chunk; + + // add the chunk to the cache of all players and NPCs in the surrounding chunks + std::set surroundings = getViewableChunks(pos); + for (Chunk* c : surroundings) { + for (CNSocket* sock : c->players) + PlayerManager::getPlayer(sock)->viewableChunks->insert(chunk); + for (int32_t id : c->NPCs) + NPCManager::NPCs[id]->viewableChunks->insert(chunk); + } +} + +void ChunkManager::deleteChunk(ChunkPos pos) { + if (!chunkExists(pos)) { + std::cout << "[WARN] Tried to delete a chunk that doesn't exist\n"; + return; + } + + Chunk* chunk = chunks[pos]; + + // remove the chunk from the cache of all players and NPCs in the surrounding chunks + std::set surroundings = getViewableChunks(pos); + for(Chunk* c : surroundings) + { + for (CNSocket* sock : c->players) + PlayerManager::getPlayer(sock)->viewableChunks->erase(chunk); + for (int32_t id : c->NPCs) + NPCManager::NPCs[id]->viewableChunks->erase(chunk); + } + + chunks.erase(pos); // remove from map + delete chunk; // free from memory } void ChunkManager::updatePlayerChunk(CNSocket* sock, ChunkPos from, ChunkPos to) { @@ -53,6 +84,9 @@ void ChunkManager::updatePlayerChunk(CNSocket* sock, ChunkPos from, ChunkPos to) addPlayerToChunks(toEnter, sock); plr->chunkPos = to; // update cached chunk position + // updated cached viewable chunks + plr->viewableChunks->clear(); + plr->viewableChunks->insert(newViewables.begin(), newViewables.end()); } void ChunkManager::updateNPCChunk(int32_t id, ChunkPos from, ChunkPos to) { @@ -85,7 +119,10 @@ void ChunkManager::updateNPCChunk(int32_t id, ChunkPos from, ChunkPos to) { removeNPCFromChunks(toExit, id); addNPCToChunks(toEnter, id); - npc->chunkPos = to; + npc->chunkPos = to; // update cached chunk position + // updated cached viewable chunks + npc->viewableChunks->clear(); + npc->viewableChunks->insert(newViewables.begin(), newViewables.end()); } void ChunkManager::trackPlayer(ChunkPos chunkPos, CNSocket* sock) { @@ -111,10 +148,8 @@ void ChunkManager::untrackPlayer(ChunkPos chunkPos, CNSocket* sock) { chunk->players.erase(sock); // gone // if chunk is empty, free it - if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { - chunks.erase(chunkPos); // remove from map - delete chunk; // free from memory - } + if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) + deleteChunk(chunkPos); } void ChunkManager::untrackNPC(ChunkPos chunkPos, int32_t id) { @@ -126,10 +161,8 @@ void ChunkManager::untrackNPC(ChunkPos chunkPos, int32_t id) { chunk->NPCs.erase(id); // gone // if chunk is empty, free it - if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { - chunks.erase(chunkPos); // remove from map - delete chunk; // free from memory - } + if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) + deleteChunk(chunkPos); } void ChunkManager::addPlayerToChunks(std::set chnks, CNSocket* sock) { @@ -394,11 +427,10 @@ std::vector ChunkManager::getChunksInMap(uint64_t mapNum) { return chnks; } -bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) { - auto nearbyChunks = ChunkManager::getViewableChunks(chunkPosAt(posX, posY, instanceID)); +bool ChunkManager::inPopulatedChunks(std::set* chnks) { - for (Chunk *c: nearbyChunks) { - if (!c->players.empty()) + for (auto it = chnks->begin(); it != chnks->end(); it++) { + if (!(*it)->players.empty()) return true; } diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 49b93ba..406e98a 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -28,6 +28,7 @@ namespace ChunkManager { extern std::map chunks; void newChunk(ChunkPos pos); + void deleteChunk(ChunkPos pos); void updatePlayerChunk(CNSocket* sock, ChunkPos from, ChunkPos to); void updateNPCChunk(int32_t id, ChunkPos from, ChunkPos to); @@ -48,7 +49,7 @@ namespace ChunkManager { std::set getViewableChunks(ChunkPos chunkPos); std::vector getChunksInMap(uint64_t mapNum); - bool inPopulatedChunks(int posX, int posY, uint64_t instanceID); + bool inPopulatedChunks(std::set* chnks); void createInstance(uint64_t); void destroyInstance(uint64_t); void destroyInstanceIfEmpty(uint64_t); diff --git a/src/MobManager.cpp b/src/MobManager.cpp index cdd5c79..51f2134 100644 --- a/src/MobManager.cpp +++ b/src/MobManager.cpp @@ -689,11 +689,9 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) { void MobManager::step(CNServer *serv, time_t currTime) { for (auto& pair : Mobs) { - int x = pair.second->appearanceData.iX; - int y = pair.second->appearanceData.iY; // skip chunks without players - if (!ChunkManager::inPopulatedChunks(x, y, pair.second->instanceID)) + if (!ChunkManager::inPopulatedChunks(pair.second->viewableChunks)) continue; // skip mob movement and combat if disabled @@ -1115,8 +1113,8 @@ bool MobManager::aggroCheck(Mob *mob, time_t currTime) { CNSocket *closest = nullptr; int closestDistance = INT_MAX; - std::set chunks = ChunkManager::getViewableChunks(mob->chunkPos); - for (Chunk *chunk : chunks) { + for (auto it = mob->viewableChunks->begin(); it != mob->viewableChunks->end(); it++) { + Chunk* chunk = *it; for (CNSocket *s : chunk->players) { Player *plr = s->plr; diff --git a/src/NPC.hpp b/src/NPC.hpp index 080b06f..38d6b9d 100644 --- a/src/NPC.hpp +++ b/src/NPC.hpp @@ -9,6 +9,7 @@ public: NPCClass npcClass; uint64_t instanceID; ChunkPos chunkPos; + std::set* viewableChunks; BaseNPC() {}; BaseNPC(int x, int y, int z, int angle, uint64_t iID, int type, int id) { @@ -25,6 +26,7 @@ public: instanceID = iID; chunkPos = std::make_tuple(0, 0, 0); + viewableChunks = new std::set(); }; BaseNPC(int x, int y, int z, int angle, uint64_t iID, int type, int id, NPCClass classType) : BaseNPC(x, y, z, angle, iID, type, id) { npcClass = classType; diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index a6862ca..659dfd3 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -103,8 +103,8 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z, uint64_t I, } void NPCManager::sendToViewable(BaseNPC *npc, void *buf, uint32_t type, size_t size) { - std::set chunks = ChunkManager::getViewableChunks(npc->chunkPos); - for (Chunk *chunk : chunks) { + for (auto it = npc->viewableChunks->begin(); it != npc->viewableChunks->end(); it++) { + Chunk* chunk = *it; for (CNSocket *s : chunk->players) { s->sendPacket(buf, type, size); } @@ -718,7 +718,7 @@ void NPCManager::eggStep(CNServer* serv, time_t currTime) { // check dead eggs and eggs in inactive chunks for (auto egg : Eggs) { - if (!egg.second->dead || !ChunkManager::inPopulatedChunks(egg.second->appearanceData.iX, egg.second->appearanceData.iY, egg.second->instanceID)) + if (!egg.second->dead || !ChunkManager::inPopulatedChunks(egg.second->viewableChunks)) continue; if (egg.second->deadUntil <= timeStamp) { // respawn it diff --git a/src/Player.hpp b/src/Player.hpp index a78a027..1e4dd21 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -78,5 +78,6 @@ struct Player { int64_t buddyIDs[50]; ChunkPos chunkPos; + std::set* viewableChunks; time_t lastHeartbeat; }; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 4a926e1..7b15d19 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -54,6 +54,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) { players[key] = p; p->chunkPos = std::make_tuple(0, 0, 0); + p->viewableChunks = new std::set(); p->lastHeartbeat = 0; key->plr = p; @@ -291,8 +292,8 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) { Player* plr = getPlayer(sock); - std::set chunks = ChunkManager::getViewableChunks(plr->chunkPos); - for (Chunk* chunk : chunks) { + for (auto it = plr->viewableChunks->begin(); it != plr->viewableChunks->end(); it++) { + Chunk* chunk = *it; for (CNSocket* otherSock : chunk->players) { if (otherSock == sock) continue;