Implement instance copying

and make respawn points match the player instance
This commit is contained in:
Gent 2020-10-12 23:42:47 -04:00
parent b87f20e2dc
commit 85530ef57f
5 changed files with 58 additions and 7 deletions

View File

@ -171,6 +171,21 @@ std::vector<Chunk*> ChunkManager::getDeltaChunks(std::vector<Chunk*> from, std::
return delta; return delta;
} }
/*
* inefficient algorithm to get all chunks from a specific instance
*/
std::vector<std::tuple<int, int, uint64_t>> ChunkManager::getChunksInMap(uint64_t mapNum) {
std::vector<std::tuple<int, int, uint64_t>> chnks;
for (auto it = ChunkManager::chunks.begin(); it != ChunkManager::chunks.end(); it++) {
if (std::get<2>(it->first) == mapNum) {
chnks.push_back(it->first);
}
}
return chnks;
}
bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) { bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) {
auto chunk = ChunkManager::grabChunk(posX, posY, instanceID); auto chunk = ChunkManager::grabChunk(posX, posY, instanceID);
auto nearbyChunks = ChunkManager::grabChunks(chunk); auto nearbyChunks = ChunkManager::grabChunks(chunk);
@ -182,3 +197,33 @@ bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) {
return false; return false;
} }
void ChunkManager::createInstance(uint64_t instanceID) {
std::vector<std::tuple<int, int, uint64_t>> templateChunks = ChunkManager::getChunksInMap(instanceID & 0xffffffff); // base instance chunks
if (ChunkManager::getChunksInMap(instanceID).size() == 0) { // only instantiate if the instance doesn't exist already
std::cout << "Creating instance " << instanceID << std::endl;
for (std::tuple<int, int, uint64_t> &coords : templateChunks) {
for (int npcID : chunks[coords]->NPCs) {
// make a copy of each NPC in the template chunks and put them in the new instance
int newID = NPCManager::nextId++;
BaseNPC* newNPC = new BaseNPC();
memcpy(newNPC, NPCManager::NPCs[npcID], sizeof(BaseNPC));
newNPC->appearanceData.iNPC_ID = newID;
NPCManager::NPCs[newID] = newNPC;
NPCManager::updateNPCInstance(newID, instanceID);
}
}
}
else {
std::cout << "Instance " << instanceID << " already exists" << std::endl;
}
}
void ChunkManager::destroyInstance(uint64_t instanceID) {
std::cout << "Deleting instance " << instanceID << std::endl;
std::vector<std::tuple<int, int, uint64_t>> instanceChunks = ChunkManager::getChunksInMap(instanceID);
for (std::tuple<int, int, uint64_t>& coords : instanceChunks) {
destroyChunk(coords);
}
}

View File

@ -16,8 +16,8 @@ public:
enum { enum {
INSTANCE_OVERWORLD, // default instance every player starts in INSTANCE_OVERWORLD, // default instance every player starts in
INSTANCE_IZ, // all infected zones share an instance //INSTANCE_IZ, // all infected zones share an instance
INSTANCE_UNIQUE // fusion lairs are generated as requested (+ uid) //INSTANCE_UNIQUE // fusion lairs are generated as requested (+ uid)
}; };
namespace ChunkManager { namespace ChunkManager {
@ -35,5 +35,9 @@ namespace ChunkManager {
std::tuple<int, int, uint64_t> grabChunk(int posX, int posY, uint64_t instanceID); std::tuple<int, int, uint64_t> grabChunk(int posX, int posY, uint64_t instanceID);
std::vector<Chunk*> grabChunks(std::tuple<int, int, uint64_t> chunkPos); std::vector<Chunk*> grabChunks(std::tuple<int, int, uint64_t> chunkPos);
std::vector<Chunk*> getDeltaChunks(std::vector<Chunk*> from, std::vector<Chunk*> to); std::vector<Chunk*> getDeltaChunks(std::vector<Chunk*> from, std::vector<Chunk*> to);
std::vector<std::tuple<int, int, uint64_t>> getChunksInMap(uint64_t mapNum);
bool inPopulatedChunks(int posX, int posY, uint64_t instanceID); bool inPopulatedChunks(int posX, int posY, uint64_t instanceID);
void createInstance(uint64_t);
void destroyInstance(uint64_t);
} }

View File

@ -3,6 +3,7 @@
#include "settings.hpp" #include "settings.hpp"
#include "MobManager.hpp" #include "MobManager.hpp"
#include "MissionManager.hpp" #include "MissionManager.hpp"
#include "ChunkManager.hpp"
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
@ -608,8 +609,9 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) {
if (Warps[warpId].isInstance) if (Warps[warpId].isInstance)
{ {
uint64_t instanceID = Warps[warpId].instanceID; uint64_t instanceID = Warps[warpId].instanceID;
if (false) { // TODO check if instance is unique and make a copy if (Warps[warpId].limitTaskID != 0) { // if warp requires you to be on a mission, it's gotta be a unique instance
instanceID += ((uint64_t)plrv.plr->iIDGroup << 32); // upper 32 bits are leader ID instanceID += ((uint64_t)plrv.plr->iIDGroup << 32); // upper 32 bits are leader ID
ChunkManager::createInstance(instanceID);
} }
PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID); PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID);

View File

@ -361,7 +361,7 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
response.PCLoadData2CL.iFirstUseFlag2 = UINT64_MAX; response.PCLoadData2CL.iFirstUseFlag2 = UINT64_MAX;
plr.SerialKey = enter->iEnterSerialKey; plr.SerialKey = enter->iEnterSerialKey;
plr.instanceID = INSTANCE_OVERWORLD; // TODO: load this from the database (as long as it's not a unique instance) plr.instanceID = INSTANCE_OVERWORLD; // the player should never be in an instance on enter
sock->setEKey(CNSocketEncryption::createNewKey(response.uiSvrTime, response.iID + 1, response.PCLoadData2CL.iFusionMatter + 1)); sock->setEKey(CNSocketEncryption::createNewKey(response.uiSvrTime, response.iID + 1, response.PCLoadData2CL.iFusionMatter + 1));
sock->setFEKey(plr.FEKey); sock->setFEKey(plr.FEKey);
@ -929,7 +929,7 @@ WarpLocation PlayerManager::getRespawnPoint(Player *plr) {
for (auto targ : NPCManager::RespawnPoints) { for (auto targ : NPCManager::RespawnPoints) {
curDist = sqrt(pow(plr->x - targ.x, 2) + pow(plr->y - targ.y, 2)); curDist = sqrt(pow(plr->x - targ.x, 2) + pow(plr->y - targ.y, 2));
if (curDist < bestDist) { if (curDist < bestDist && targ.instanceID == (plr->instanceID & 0xffffffff)) { // only mapNum needs to match
best = targ; best = targ;
bestDist = curDist; bestDist = curDist;
} }

View File

@ -29,7 +29,7 @@ void TableData::init() {
inFile >> npcData; inFile >> npcData;
for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) { for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) {
auto npc = _npc.value(); auto npc = _npc.value();
uint64_t instanceID = npc.find("mapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["mapNum"]; int instanceID = npc.find("mapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["mapNum"];
BaseNPC *tmp = new BaseNPC(npc["x"], npc["y"], npc["z"], npc["angle"], instanceID, npc["id"], nextId); BaseNPC *tmp = new BaseNPC(npc["x"], npc["y"], npc["z"], npc["angle"], instanceID, npc["id"], nextId);
NPCManager::NPCs[nextId] = tmp; NPCManager::NPCs[nextId] = tmp;
@ -37,7 +37,7 @@ void TableData::init() {
nextId++; nextId++;
if (npc["id"] == 641 || npc["id"] == 642) if (npc["id"] == 641 || npc["id"] == 642)
NPCManager::RespawnPoints.push_back({ npc["x"], npc["y"], ((int)npc["z"]) + RESURRECT_HEIGHT }); NPCManager::RespawnPoints.push_back({ npc["x"], npc["y"], ((int)npc["z"]) + RESURRECT_HEIGHT, instanceID });
} }
} }
catch (const std::exception& err) { catch (const std::exception& err) {