mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 21:40:05 +00:00
Reimplement chunk data caching
This commit is contained in:
parent
82b505a737
commit
95b385dee1
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user