mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-04 22:40:05 +00:00
Add support for unique instances
This commit is contained in:
parent
c1fd51b721
commit
d4aed0abf4
@ -329,6 +329,7 @@ void instanceCommand(std::string full, std::vector<std::string>& 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;
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,12 @@
|
||||
#include "NPCManager.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
std::map<std::tuple<int, int, int>, Chunk*> ChunkManager::chunks;
|
||||
std::map<std::tuple<int, int, uint64_t>, Chunk*> ChunkManager::chunks;
|
||||
|
||||
void ChunkManager::init() {} // stubbed
|
||||
|
||||
void ChunkManager::addNPC(int posX, int posY, int instanceID, int32_t id) {
|
||||
std::tuple<int, int, int> pos = grabChunk(posX, posY, instanceID);
|
||||
void ChunkManager::addNPC(int posX, int posY, uint64_t instanceID, int32_t id) {
|
||||
std::tuple<int, int, uint64_t> 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<int, int, int> pos = grabChunk(posX, posY, instanceID);
|
||||
void ChunkManager::addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* sock) {
|
||||
std::tuple<int, int, uint64_t> 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<int, int, int> chunkPos, CNSocket* sock) {
|
||||
bool ChunkManager::removePlayer(std::tuple<int, int, uint64_t> 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<int, int, int> chunkPos, CNSocket* so
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChunkManager::removeNPC(std::tuple<int, int, int> chunkPos, int32_t id) {
|
||||
bool ChunkManager::removeNPC(std::tuple<int, int, uint64_t> 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<int, int, int> chunkPos, int32_t id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChunkManager::destroyChunk(std::tuple<int, int, int> chunkPos) {
|
||||
void ChunkManager::destroyChunk(std::tuple<int, int, uint64_t> 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<int, int, int> chunkPos) {
|
||||
delete chunk;
|
||||
}
|
||||
|
||||
bool ChunkManager::checkChunk(std::tuple<int, int, int> chunk) {
|
||||
bool ChunkManager::checkChunk(std::tuple<int, int, uint64_t> chunk) {
|
||||
return chunks.find(chunk) != chunks.end();
|
||||
}
|
||||
|
||||
std::tuple<int, int, int> ChunkManager::grabChunk(int posX, int posY, int instanceID) {
|
||||
std::tuple<int, int, uint64_t> ChunkManager::grabChunk(int posX, int posY, uint64_t instanceID) {
|
||||
return std::make_tuple(posX / (settings::VIEWDISTANCE / 3), posY / (settings::VIEWDISTANCE / 3), instanceID);
|
||||
}
|
||||
|
||||
std::vector<Chunk*> ChunkManager::grabChunks(std::tuple<int, int, int> chunk) {
|
||||
std::vector<Chunk*> ChunkManager::grabChunks(std::tuple<int, int, uint64_t> chunk) {
|
||||
std::vector<Chunk*> 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<int, int, int> pos = std::make_tuple(x+i, y+z, inst);
|
||||
std::tuple<int, int, uint64_t> 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<Chunk*> ChunkManager::getDeltaChunks(std::vector<Chunk*> 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);
|
||||
|
||||
|
@ -24,16 +24,16 @@ namespace ChunkManager {
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
extern std::map<std::tuple<int, int, int>, Chunk*> chunks;
|
||||
extern std::map<std::tuple<int, int, uint64_t>, 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<int, int, int> chunkPos, CNSocket* sock);
|
||||
bool removeNPC(std::tuple<int, int, int> chunkPos, int32_t id);
|
||||
bool checkChunk(std::tuple<int, int, int> chunk);
|
||||
void destroyChunk(std::tuple<int, int, int> chunkPos);
|
||||
std::tuple<int, int, int> grabChunk(int posX, int posY, int instanceID);
|
||||
std::vector<Chunk*> grabChunks(std::tuple<int, int, int> 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<int, int, uint64_t> chunkPos, CNSocket* sock);
|
||||
bool removeNPC(std::tuple<int, int, uint64_t> chunkPos, int32_t id);
|
||||
bool checkChunk(std::tuple<int, int, uint64_t> chunk);
|
||||
void destroyChunk(std::tuple<int, int, uint64_t> chunkPos);
|
||||
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*> getDeltaChunks(std::vector<Chunk*> from, std::vector<Chunk*> to);
|
||||
bool inPopulatedChunks(int posX, int posY, int instanceID);
|
||||
bool inPopulatedChunks(int posX, int posY, uint64_t instanceID);
|
||||
}
|
||||
|
@ -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"];
|
||||
|
@ -7,12 +7,12 @@ class BaseNPC {
|
||||
public:
|
||||
sNPCAppearanceData appearanceData;
|
||||
NPCClass npcClass;
|
||||
int instanceID;
|
||||
std::tuple<int, int, int> chunkPos;
|
||||
uint64_t instanceID;
|
||||
std::tuple<int, int, uint64_t> chunkPos;
|
||||
std::vector<Chunk*> 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;
|
||||
}
|
||||
};
|
||||
|
@ -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<int, int, int> newPos = ChunkManager::grabChunk(X, Y, npc->instanceID);
|
||||
std::tuple<int, int, uint64_t> 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));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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<int, int, int> newPos = ChunkManager::grabChunk(X, Y, view.plr->instanceID);
|
||||
std::tuple<int, int, uint64_t> 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 {
|
||||
|
@ -13,7 +13,7 @@
|
||||
struct WarpLocation;
|
||||
|
||||
struct PlayerView {
|
||||
std::tuple<int, int, int> chunkPos;
|
||||
std::tuple<int, int, uint64_t> chunkPos;
|
||||
std::vector<Chunk*> 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);
|
||||
|
@ -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)++);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user