diff --git a/src/ChatManager.cpp b/src/ChatManager.cpp index e7db43b..a689ed4 100644 --- a/src/ChatManager.cpp +++ b/src/ChatManager.cpp @@ -329,6 +329,7 @@ void instanceCommand(std::string full, std::vector& args, CNSocket* // no additional arguments: report current instance ID if (args.size() < 2) { ChatManager::sendServerMessage(sock, "[INST] Current instance ID: " + std::to_string(plr->instanceID)); + ChatManager::sendServerMessage(sock, "[INST] (Map " + std::to_string(plr->instanceID & 0xffffffff) + ", instance " + std::to_string(plr->instanceID >> 32) + ")"); return; } diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index 8e80f53..c9c85b7 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -3,12 +3,12 @@ #include "NPCManager.hpp" #include "settings.hpp" -std::map, Chunk*> ChunkManager::chunks; +std::map, Chunk*> ChunkManager::chunks; void ChunkManager::init() {} // stubbed -void ChunkManager::addNPC(int posX, int posY, int instanceID, int32_t id) { - std::tuple pos = grabChunk(posX, posY, instanceID); +void ChunkManager::addNPC(int posX, int posY, uint64_t instanceID, int32_t id) { + std::tuple pos = grabChunk(posX, posY, instanceID); // make chunk if it doesn't exist! if (chunks.find(pos) == chunks.end()) { @@ -22,8 +22,8 @@ void ChunkManager::addNPC(int posX, int posY, int instanceID, int32_t id) { chunk->NPCs.insert(id); } -void ChunkManager::addPlayer(int posX, int posY, int instanceID, CNSocket* sock) { - std::tuple pos = grabChunk(posX, posY, instanceID); +void ChunkManager::addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* sock) { + std::tuple pos = grabChunk(posX, posY, instanceID); // make chunk if it doesn't exist! if (chunks.find(pos) == chunks.end()) { @@ -37,7 +37,7 @@ void ChunkManager::addPlayer(int posX, int posY, int instanceID, CNSocket* sock) chunk->players.insert(sock); } -bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* sock) { +bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* sock) { if (!checkChunk(chunkPos)) return false; // do nothing if chunk doesn't even exist @@ -57,7 +57,7 @@ bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* so return false; } -bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { +bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { if (!checkChunk(chunkPos)) return false; // do nothing if chunk doesn't even exist @@ -77,7 +77,7 @@ bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { return false; } -void ChunkManager::destroyChunk(std::tuple chunkPos) { +void ChunkManager::destroyChunk(std::tuple chunkPos) { if (!checkChunk(chunkPos)) return; // chunk doesn't exist, we don't need to do anything @@ -118,25 +118,26 @@ void ChunkManager::destroyChunk(std::tuple chunkPos) { delete chunk; } -bool ChunkManager::checkChunk(std::tuple chunk) { +bool ChunkManager::checkChunk(std::tuple chunk) { return chunks.find(chunk) != chunks.end(); } -std::tuple ChunkManager::grabChunk(int posX, int posY, int instanceID) { +std::tuple ChunkManager::grabChunk(int posX, int posY, uint64_t instanceID) { return std::make_tuple(posX / (settings::VIEWDISTANCE / 3), posY / (settings::VIEWDISTANCE / 3), instanceID); } -std::vector ChunkManager::grabChunks(std::tuple chunk) { +std::vector ChunkManager::grabChunks(std::tuple chunk) { std::vector chnks; chnks.reserve(9); - int x, y, inst; + int x, y; + uint64_t inst; std::tie(x, y, inst) = chunk; // grabs surrounding chunks if they exist for (int i = -1; i < 2; i++) { for (int z = -1; z < 2; z++) { - std::tuple pos = std::make_tuple(x+i, y+z, inst); + std::tuple pos = std::make_tuple(x+i, y+z, inst); // if chunk exists, add it to the vector if (checkChunk(pos)) @@ -170,7 +171,7 @@ std::vector ChunkManager::getDeltaChunks(std::vector from, std:: return delta; } -bool ChunkManager::inPopulatedChunks(int posX, int posY, int instanceID) { +bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) { auto chunk = ChunkManager::grabChunk(posX, posY, instanceID); auto nearbyChunks = ChunkManager::grabChunks(chunk); diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 633b658..9ba935f 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -24,16 +24,16 @@ namespace ChunkManager { void init(); void cleanup(); - extern std::map, Chunk*> chunks; + extern std::map, Chunk*> chunks; - void addNPC(int posX, int posY, int instanceID, int32_t id); - void addPlayer(int posX, int posY, int instanceID, CNSocket* sock); - bool removePlayer(std::tuple chunkPos, CNSocket* sock); - bool removeNPC(std::tuple chunkPos, int32_t id); - bool checkChunk(std::tuple chunk); - void destroyChunk(std::tuple chunkPos); - std::tuple grabChunk(int posX, int posY, int instanceID); - std::vector grabChunks(std::tuple chunkPos); + void addNPC(int posX, int posY, uint64_t instanceID, int32_t id); + void addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* sock); + bool removePlayer(std::tuple chunkPos, CNSocket* sock); + bool removeNPC(std::tuple chunkPos, int32_t id); + bool checkChunk(std::tuple chunk); + void destroyChunk(std::tuple chunkPos); + std::tuple grabChunk(int posX, int posY, uint64_t instanceID); + std::vector grabChunks(std::tuple chunkPos); std::vector getDeltaChunks(std::vector from, std::vector to); - bool inPopulatedChunks(int posX, int posY, int instanceID); + bool inPopulatedChunks(int posX, int posY, uint64_t instanceID); } diff --git a/src/MobManager.hpp b/src/MobManager.hpp index 5cb3b9d..ed3f243 100644 --- a/src/MobManager.hpp +++ b/src/MobManager.hpp @@ -45,7 +45,7 @@ struct Mob : public BaseNPC { // temporary; until we're sure what's what nlohmann::json data; - Mob(int x, int y, int z, int angle, int iID, int type, int hp, nlohmann::json d, int32_t id) + Mob(int x, int y, int z, int angle, uint64_t iID, int type, int hp, nlohmann::json d, int32_t id) : BaseNPC(x, y, z, angle, iID, type, id), maxHealth(hp) { state = MobState::ROAMING; @@ -71,7 +71,7 @@ struct Mob : public BaseNPC { } // constructor for /summon - Mob(int x, int y, int z, int iID, int type, nlohmann::json d, int32_t id) + Mob(int x, int y, int z, uint64_t iID, int type, nlohmann::json d, int32_t id) : Mob(x, y, z, 0, iID, type, 0, d, id) { summoned = true; // will be despawned and deallocated when killed appearanceData.iHP = maxHealth = d["m_iHP"]; diff --git a/src/NPC.hpp b/src/NPC.hpp index 724d8de..384fc15 100644 --- a/src/NPC.hpp +++ b/src/NPC.hpp @@ -7,12 +7,12 @@ class BaseNPC { public: sNPCAppearanceData appearanceData; NPCClass npcClass; - int instanceID; - std::tuple chunkPos; + uint64_t instanceID; + std::tuple chunkPos; std::vector currentChunks; BaseNPC() {}; - BaseNPC(int x, int y, int z, int angle, int iID, int type, int id) { + BaseNPC(int x, int y, int z, int angle, uint64_t iID, int type, int id) { appearanceData.iX = x; appearanceData.iY = y; appearanceData.iZ = z; @@ -27,7 +27,7 @@ public: chunkPos = std::make_tuple(0, 0, instanceID); }; - BaseNPC(int x, int y, int z, int angle, int 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; } }; diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 4dfeac3..2af6426 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -146,7 +146,7 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) { npc->appearanceData.iX = X; npc->appearanceData.iY = Y; npc->appearanceData.iZ = Z; - std::tuple newPos = ChunkManager::grabChunk(X, Y, npc->instanceID); + std::tuple 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) { @@ -177,7 +177,7 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) { npc->currentChunks = allChunks; } -void NPCManager::updateNPCInstance(int32_t npcID, int instanceID) { +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); @@ -591,7 +591,12 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) { // std::cerr << "Warped to Map Num:" << Warps[warpId].instanceID << " NPC ID " << Warps[warpId].npcID << std::endl; if (Warps[warpId].isInstance) { - PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, Warps[warpId].instanceID); + uint64_t instanceID = Warps[warpId].instanceID; + if (false) { // TODO check if instance is unique and make a copy + instanceID += ((uint64_t)plrv.plr->iIDGroup << 32); // upper 32 bits are leader ID + } + + PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID); } else { @@ -603,7 +608,7 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) { resp.eIL = 4; // do not take away any items PlayerManager::removePlayerFromChunks(plrv.currentChunks, sock); plrv.currentChunks.clear(); - plrv.plr->instanceID = 0; + plrv.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)); } } diff --git a/src/NPCManager.hpp b/src/NPCManager.hpp index 571b0fc..0c99941 100644 --- a/src/NPCManager.hpp +++ b/src/NPCManager.hpp @@ -29,7 +29,7 @@ namespace NPCManager { void destroyNPC(int32_t); void updateNPCPosition(int32_t, int X, int Y, int Z, int angle); void updateNPCPosition(int32_t, int X, int Y, int Z); - void updateNPCInstance(int32_t, int instanceID); + void updateNPCInstance(int32_t, uint64_t instanceID); void sendToViewable(BaseNPC* npc, void* buf, uint32_t type, size_t size); diff --git a/src/Player.hpp b/src/Player.hpp index 5499812..a7805ee 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -37,7 +37,8 @@ struct Player { int32_t iConditionBitFlag; int8_t iSpecialState; - int x, y, z, angle, instanceID; + int x, y, z, angle; + uint64_t instanceID; sItemBase Equip[AEQUIP_COUNT]; sItemBase Inven[AINVEN_COUNT]; sItemBase Bank[ABANK_COUNT]; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index a20e2f6..fe584ae 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -194,9 +194,9 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) { updatePlayerChunk(sock, X, Y, view.plr->instanceID); } -void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y,int mapNum) { +void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y, uint64_t instanceID) { PlayerView& view = players[sock]; - std::tuple newPos = ChunkManager::grabChunk(X, Y, view.plr->instanceID); + std::tuple newPos = ChunkManager::grabChunk(X, Y, view.plr->instanceID); // nothing to be done if (newPos == view.chunkPos) @@ -222,13 +222,13 @@ void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y,int mapNum) { view.currentChunks = allChunks; } -void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, int I) { +void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I) { PlayerView& plrv = PlayerManager::players[sock]; Player* plr = plrv.plr; plr->instanceID = I; if (I != INSTANCE_OVERWORLD) { INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt); - pkt.iInstanceMapNum = I; + pkt.iInstanceMapNum = (int32_t)(I & 0xffffffff); // lower 32 bits are mapnum sock->sendPacket((void*)&pkt, P_FE2CL_INSTANCE_MAP_INFO, sizeof(sP_FE2CL_INSTANCE_MAP_INFO)); sendPlayerTo(sock, X, Y, Z); } else { diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index f30449c..70f1731 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -13,7 +13,7 @@ struct WarpLocation; struct PlayerView { - std::tuple chunkPos; + std::tuple chunkPos; std::vector currentChunks; Player *plr; time_t lastHeartbeat; @@ -32,9 +32,9 @@ namespace PlayerManager { void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z); void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z, int angle); - void updatePlayerChunk(CNSocket* sock, int X, int Y, int instanceID); + void updatePlayerChunk(CNSocket* sock, int X, int Y, uint64_t instanceID); - void sendPlayerTo(CNSocket* sock, int X, int Y, int Z, int I); + void sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I); void sendPlayerTo(CNSocket* sock, int X, int Y, int Z); void sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size); diff --git a/src/TableData.cpp b/src/TableData.cpp index 16e35b4..09025db 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -29,7 +29,7 @@ void TableData::init() { inFile >> npcData; for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) { auto npc = _npc.value(); - int instanceID = npc.find("mapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["mapNum"]; + uint64_t 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); NPCManager::NPCs[nextId] = tmp; @@ -181,7 +181,7 @@ void TableData::init() { for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) { auto npc = _npc.value(); auto td = NPCManager::NPCData[(int)npc["iNPCType"]]; - int instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"]; + uint64_t instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"]; Mob *tmp = new Mob(npc["iX"], npc["iY"], npc["iZ"], npc["iAngle"], instanceID, npc["iNPCType"], npc["iHP"], td, nextId); NPCManager::NPCs[nextId] = tmp; @@ -409,7 +409,7 @@ void TableData::loadGruntwork(int32_t *nextId) { auto npcMap = gruntwork["instances"]; for (auto _map = npcMap.begin(); _map != npcMap.end(); _map++) { int32_t npcID = _map.value()["iNPCID"]; - int instanceID = _map.value()["iMapNum"]; + uint64_t instanceID = _map.value()["iMapNum"]; if (NPCManager::NPCs.find(npcID) == NPCManager::NPCs.end()) continue; // NPC not found BaseNPC* npc = NPCManager::NPCs[npcID]; @@ -423,7 +423,7 @@ void TableData::loadGruntwork(int32_t *nextId) { for (auto _mob = mobs.begin(); _mob != mobs.end(); _mob++) { auto mob = _mob.value(); - int instanceID = mob.find("iMapNum") == mob.end() ? INSTANCE_OVERWORLD : (int)mob["iMapNum"]; + uint64_t instanceID = mob.find("iMapNum") == mob.end() ? INSTANCE_OVERWORLD : (int)mob["iMapNum"]; Mob *npc = new Mob(mob["iX"], mob["iY"], mob["iZ"], instanceID, mob["iNPCType"], NPCManager::NPCData[(int)mob["iNPCType"]], (*nextId)++);