Experimental chunk refactor.

This commit is contained in:
Gent S
2020-11-17 19:07:04 -05:00
parent 5cbb8538c0
commit e50a4c2edd
12 changed files with 441 additions and 529 deletions

View File

@@ -54,90 +54,6 @@ void NPCManager::init() {
REGISTER_SHARD_TIMER(eggStep, 1000);
}
void NPCManager::removeNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
BaseNPC* npc = NPCs[id];
switch (npc->npcClass) {
case NPC_BUS:
INITSTRUCT(sP_FE2CL_TRANSPORTATION_EXIT, exitBusData);
exitBusData.eTT = 3;
exitBusData.iT_ID = id;
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&exitBusData, P_FE2CL_TRANSPORTATION_EXIT, sizeof(sP_FE2CL_TRANSPORTATION_EXIT));
}
}
break;
case NPC_EGG:
INITSTRUCT(sP_FE2CL_SHINY_EXIT, exitEggData);
exitEggData.iShinyID = id;
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&exitEggData, P_FE2CL_SHINY_EXIT, sizeof(sP_FE2CL_SHINY_EXIT));
}
}
break;
default:
// create struct
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
exitData.iNPC_ID = id;
// remove it from the clients
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
}
}
break;
}
}
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
BaseNPC* npc = NPCs[id];
switch (npc->npcClass) {
case NPC_BUS:
INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, enterBusData);
enterBusData.AppearanceData = { 3, npc->appearanceData.iNPC_ID, npc->appearanceData.iNPCType, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ };
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&enterBusData, P_FE2CL_TRANSPORTATION_ENTER, sizeof(sP_FE2CL_TRANSPORTATION_ENTER));
}
}
break;
case NPC_EGG:
INITSTRUCT(sP_FE2CL_SHINY_ENTER, enterEggData);
npcDataToEggData(&npc->appearanceData, &enterEggData.ShinyAppearanceData);
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&enterEggData, P_FE2CL_SHINY_ENTER, sizeof(sP_FE2CL_SHINY_ENTER));
}
}
break;
default:
// create struct
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
enterData.NPCAppearanceData = npc->appearanceData;
for (Chunk* chunk : viewableChunks) {
for (CNSocket* sock : chunk->players) {
// send to socket
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
}
}
break;
}
}
void NPCManager::destroyNPC(int32_t id) {
// sanity check
if (NPCs.find(id) == NPCs.end()) {
@@ -146,19 +62,19 @@ void NPCManager::destroyNPC(int32_t id) {
}
BaseNPC* entity = NPCs[id];
ChunkPos chunkPos = ChunkManager::chunkPosAt(entity->appearanceData.iX, entity->appearanceData.iY, entity->instanceID);
// sanity check
if (ChunkManager::chunks.find(entity->chunkPos) == ChunkManager::chunks.end()) {
if (!ChunkManager::chunkExists(chunkPos)) {
std::cout << "chunk not found!" << std::endl;
return;
}
// remove NPC from the chunk
Chunk* chunk = ChunkManager::chunks[entity->chunkPos];
chunk->NPCs.erase(id);
ChunkManager::untrackNPC(chunkPos, id);
// remove from viewable chunks
removeNPC(entity->currentChunks, id);
ChunkManager::removeNPCFromChunks(ChunkManager::getViewableChunks(chunkPos), id);
// remove from mob manager
if (MobManager::Mobs.find(id) != MobManager::Mobs.end())
@@ -173,58 +89,23 @@ void NPCManager::destroyNPC(int32_t id) {
delete entity;
}
void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z, int angle) {
NPCs[id]->appearanceData.iAngle = angle;
updateNPCPosition(id, X, Y, Z);
}
void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) {
void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z, uint64_t I, int angle) {
BaseNPC* npc = NPCs[id];
npc->appearanceData.iAngle = angle;
ChunkPos oldChunk = ChunkManager::chunkPosAt(npc->appearanceData.iX, npc->appearanceData.iY, npc->instanceID);
ChunkPos newChunk = ChunkManager::chunkPosAt(X, Y, I);
npc->appearanceData.iX = X;
npc->appearanceData.iY = Y;
npc->appearanceData.iZ = Z;
ChunkPos newPos = ChunkManager::grabChunk(X, Y, npc->instanceID);
// nothing to be done (but we should also update currentChunks to add/remove stale chunks)
if (newPos == npc->chunkPos) {
npc->currentChunks = ChunkManager::grabChunks(newPos);
return;
}
ChunkManager::addNPC(X, Y, npc->instanceID, id);
std::vector<Chunk*> allChunks = ChunkManager::grabChunks(newPos);
// send npc exit to stale chunks
removeNPC(ChunkManager::getDeltaChunks(npc->currentChunks, allChunks), id);
// send npc enter to new chunks
addNPC(ChunkManager::getDeltaChunks(allChunks, npc->currentChunks), 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());
}
npc->chunkPos = newPos;
npc->currentChunks = allChunks;
}
void NPCManager::updateNPCInstance(int32_t npcID, uint64_t instanceID) {
BaseNPC* npc = NPCs[npcID];
npc->instanceID = instanceID;
updateNPCPosition(npcID, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ);
npc->instanceID = I;
if (oldChunk == newChunk)
return; // didn't change chunks
ChunkManager::updateNPCChunk(id, oldChunk, newChunk);
}
void NPCManager::sendToViewable(BaseNPC *npc, void *buf, uint32_t type, size_t size) {
for (Chunk *chunk : npc->currentChunks) {
std::set<Chunk*> chunks = ChunkManager::getViewableChunks(ChunkManager::chunkPosAt(npc->appearanceData.iX, npc->appearanceData.iY, npc->instanceID));
for (Chunk *chunk : chunks) {
for (CNSocket *s : chunk->players) {
s->sendPacket(buf, type, size);
}
@@ -602,7 +483,9 @@ void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) {
} else
NPCs[id] = new BaseNPC(plr->x, plr->y, plr->z, 0, plr->instanceID, req->iNPCType, id);
updateNPCPosition(id, plr->x, plr->y, plr->z);
updateNPCPosition(id, plr->x, plr->y, plr->z, plr->instanceID, 0);
// force chunk update
ChunkManager::updateNPCChunk(id, { 0, 0, 0 }, ChunkManager::chunkPosAt(plr->x, plr->y, plr->instanceID));
}
}
@@ -655,16 +538,15 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) {
}
else
{
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp); //Can only be used for exiting instances because it sets the instance flag to false
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp); // Can only be used for exiting instances because it sets the instance flag to false
resp.iX = Warps[warpId].x;
resp.iY = Warps[warpId].y;
resp.iZ = Warps[warpId].z;
resp.iCandy = plr->money;
resp.eIL = 4; // do not take away any items
PlayerManager::removePlayerFromChunks(*plr->currentChunks, sock);
plr->currentChunks->clear();
plr->instanceID = INSTANCE_OVERWORLD;
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC));
PlayerManager::updatePlayerPosition(sock, resp.iX, resp.iY, resp.iZ, INSTANCE_OVERWORLD, plr->angle);
}
}
@@ -844,7 +726,9 @@ void NPCManager::eggStep(CNServer* serv, time_t currTime) {
egg.second->dead = false;
egg.second->deadUntil = 0;
egg.second->appearanceData.iHP = 400;
addNPC(egg.second->currentChunks, egg.first);
ChunkManager::addNPCToChunks(ChunkManager::getViewableChunks(ChunkManager::chunkPosAt(egg.second->appearanceData.iX, egg.second->appearanceData.iY, egg.second->instanceID)),
egg.first);
}
}
@@ -1012,7 +896,8 @@ void NPCManager::eggPickup(CNSocket* sock, CNPacketData* data) {
if (egg->summoned)
destroyNPC(eggId);
else {
removeNPC(egg->currentChunks, eggId);
ChunkManager::removeNPCFromChunks(ChunkManager::getViewableChunks(ChunkManager::chunkPosAt(egg->appearanceData.iX, egg->appearanceData.iY, egg->instanceID)),
eggId);
egg->dead = true;
egg->deadUntil = getTime() + (time_t)type->regen * 1000;
egg->appearanceData.iHP = 0;