Reimplement chunk data caching

This commit is contained in:
Gent S 2020-11-19 17:19:46 -05:00
parent 82b505a737
commit 95b385dee1
7 changed files with 59 additions and 24 deletions

View File

@ -20,6 +20,37 @@ void ChunkManager::newChunk(ChunkPos pos) {
chunk->NPCs = std::set<int32_t>(); chunk->NPCs = std::set<int32_t>();
chunks[pos] = chunk; chunks[pos] = chunk;
// add the chunk to the cache of all players and NPCs in the surrounding chunks
std::set<Chunk*> 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<Chunk*> 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) { 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); addPlayerToChunks(toEnter, sock);
plr->chunkPos = to; // update cached chunk position 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) { 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); removeNPCFromChunks(toExit, id);
addNPCToChunks(toEnter, 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) { void ChunkManager::trackPlayer(ChunkPos chunkPos, CNSocket* sock) {
@ -111,10 +148,8 @@ void ChunkManager::untrackPlayer(ChunkPos chunkPos, CNSocket* sock) {
chunk->players.erase(sock); // gone chunk->players.erase(sock); // gone
// if chunk is empty, free it // if chunk is empty, free it
if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { if (chunk->NPCs.size() == 0 && chunk->players.size() == 0)
chunks.erase(chunkPos); // remove from map deleteChunk(chunkPos);
delete chunk; // free from memory
}
} }
void ChunkManager::untrackNPC(ChunkPos chunkPos, int32_t id) { 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 chunk->NPCs.erase(id); // gone
// if chunk is empty, free it // if chunk is empty, free it
if (chunk->NPCs.size() == 0 && chunk->players.size() == 0) { if (chunk->NPCs.size() == 0 && chunk->players.size() == 0)
chunks.erase(chunkPos); // remove from map deleteChunk(chunkPos);
delete chunk; // free from memory
}
} }
void ChunkManager::addPlayerToChunks(std::set<Chunk*> chnks, CNSocket* sock) { void ChunkManager::addPlayerToChunks(std::set<Chunk*> chnks, CNSocket* sock) {
@ -394,11 +427,10 @@ std::vector<ChunkPos> ChunkManager::getChunksInMap(uint64_t mapNum) {
return chnks; return chnks;
} }
bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) { bool ChunkManager::inPopulatedChunks(std::set<Chunk*>* chnks) {
auto nearbyChunks = ChunkManager::getViewableChunks(chunkPosAt(posX, posY, instanceID));
for (Chunk *c: nearbyChunks) { for (auto it = chnks->begin(); it != chnks->end(); it++) {
if (!c->players.empty()) if (!(*it)->players.empty())
return true; return true;
} }

View File

@ -28,6 +28,7 @@ namespace ChunkManager {
extern std::map<ChunkPos, Chunk*> chunks; extern std::map<ChunkPos, Chunk*> chunks;
void newChunk(ChunkPos pos); void newChunk(ChunkPos pos);
void deleteChunk(ChunkPos pos);
void updatePlayerChunk(CNSocket* sock, ChunkPos from, ChunkPos to); void updatePlayerChunk(CNSocket* sock, ChunkPos from, ChunkPos to);
void updateNPCChunk(int32_t id, ChunkPos from, ChunkPos to); void updateNPCChunk(int32_t id, ChunkPos from, ChunkPos to);
@ -48,7 +49,7 @@ namespace ChunkManager {
std::set<Chunk*> getViewableChunks(ChunkPos chunkPos); std::set<Chunk*> getViewableChunks(ChunkPos chunkPos);
std::vector<ChunkPos> getChunksInMap(uint64_t mapNum); std::vector<ChunkPos> getChunksInMap(uint64_t mapNum);
bool inPopulatedChunks(int posX, int posY, uint64_t instanceID); bool inPopulatedChunks(std::set<Chunk*>* chnks);
void createInstance(uint64_t); void createInstance(uint64_t);
void destroyInstance(uint64_t); void destroyInstance(uint64_t);
void destroyInstanceIfEmpty(uint64_t); void destroyInstanceIfEmpty(uint64_t);

View File

@ -689,11 +689,9 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
void MobManager::step(CNServer *serv, time_t currTime) { void MobManager::step(CNServer *serv, time_t currTime) {
for (auto& pair : Mobs) { for (auto& pair : Mobs) {
int x = pair.second->appearanceData.iX;
int y = pair.second->appearanceData.iY;
// skip chunks without players // skip chunks without players
if (!ChunkManager::inPopulatedChunks(x, y, pair.second->instanceID)) if (!ChunkManager::inPopulatedChunks(pair.second->viewableChunks))
continue; continue;
// skip mob movement and combat if disabled // skip mob movement and combat if disabled
@ -1115,8 +1113,8 @@ bool MobManager::aggroCheck(Mob *mob, time_t currTime) {
CNSocket *closest = nullptr; CNSocket *closest = nullptr;
int closestDistance = INT_MAX; int closestDistance = INT_MAX;
std::set<Chunk*> chunks = ChunkManager::getViewableChunks(mob->chunkPos); for (auto it = mob->viewableChunks->begin(); it != mob->viewableChunks->end(); it++) {
for (Chunk *chunk : chunks) { Chunk* chunk = *it;
for (CNSocket *s : chunk->players) { for (CNSocket *s : chunk->players) {
Player *plr = s->plr; Player *plr = s->plr;

View File

@ -9,6 +9,7 @@ public:
NPCClass npcClass; NPCClass npcClass;
uint64_t instanceID; uint64_t instanceID;
ChunkPos chunkPos; ChunkPos chunkPos;
std::set<Chunk*>* viewableChunks;
BaseNPC() {}; BaseNPC() {};
BaseNPC(int x, int y, int z, int angle, uint64_t iID, int type, int id) { BaseNPC(int x, int y, int z, int angle, uint64_t iID, int type, int id) {
@ -25,6 +26,7 @@ public:
instanceID = iID; instanceID = iID;
chunkPos = std::make_tuple(0, 0, 0); chunkPos = std::make_tuple(0, 0, 0);
viewableChunks = new std::set<Chunk*>();
}; };
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) { 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; npcClass = classType;

View File

@ -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) { void NPCManager::sendToViewable(BaseNPC *npc, void *buf, uint32_t type, size_t size) {
std::set<Chunk*> chunks = ChunkManager::getViewableChunks(npc->chunkPos); for (auto it = npc->viewableChunks->begin(); it != npc->viewableChunks->end(); it++) {
for (Chunk *chunk : chunks) { Chunk* chunk = *it;
for (CNSocket *s : chunk->players) { for (CNSocket *s : chunk->players) {
s->sendPacket(buf, type, size); 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 // check dead eggs and eggs in inactive chunks
for (auto egg : Eggs) { 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; continue;
if (egg.second->deadUntil <= timeStamp) { if (egg.second->deadUntil <= timeStamp) {
// respawn it // respawn it

View File

@ -78,5 +78,6 @@ struct Player {
int64_t buddyIDs[50]; int64_t buddyIDs[50];
ChunkPos chunkPos; ChunkPos chunkPos;
std::set<Chunk*>* viewableChunks;
time_t lastHeartbeat; time_t lastHeartbeat;
}; };

View File

@ -54,6 +54,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
players[key] = p; players[key] = p;
p->chunkPos = std::make_tuple(0, 0, 0); p->chunkPos = std::make_tuple(0, 0, 0);
p->viewableChunks = new std::set<Chunk*>();
p->lastHeartbeat = 0; p->lastHeartbeat = 0;
key->plr = p; 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) { void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) {
Player* plr = getPlayer(sock); Player* plr = getPlayer(sock);
std::set<Chunk*> chunks = ChunkManager::getViewableChunks(plr->chunkPos); for (auto it = plr->viewableChunks->begin(); it != plr->viewableChunks->end(); it++) {
for (Chunk* chunk : chunks) { Chunk* chunk = *it;
for (CNSocket* otherSock : chunk->players) { for (CNSocket* otherSock : chunk->players) {
if (otherSock == sock) if (otherSock == sock)
continue; continue;