From c9f9b093f45cebdf0b7725cc76dce2b7831f5f67 Mon Sep 17 00:00:00 2001 From: dongresource Date: Wed, 21 Oct 2020 00:55:58 +0200 Subject: [PATCH] Bugfixes. * Add newly created chunks to nearby players and NPCs. This fixes the slider/static path mob pop-in problem. * Update a player's chunks when resurrecting. This fixes a mob desync problem. * Use a private instance for the Time Lab * Spawn a slider for every stop * Fix mobs in private lairs using the template chunk mobs's current health for their max health * Don't call into the JSON lib in the loop in aggroCheck(). This is an optimization found after using gprof. * Don't print NPC deletions to console. This stops the spam when a private instance is deleted. * Changed default view distance to half the length of a map tile, so chunks are aligned to map tiles * Update tdata reference --- .gitignore | 1 + config.ini | 2 +- src/ChunkManager.cpp | 37 ++++++++++++++++++++++++++----------- src/ChunkManager.hpp | 1 + src/MobManager.cpp | 2 +- src/MobManager.hpp | 5 ++++- src/NPCManager.cpp | 8 ++++---- src/PlayerManager.cpp | 4 +--- src/TableData.cpp | 13 ++++++------- src/settings.cpp | 2 +- 10 files changed, 46 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index c895922..c109250 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ build/ *.db version.h infer-out +gmon.out diff --git a/config.ini b/config.ini index 6b6c650..ed3d154 100644 --- a/config.ini +++ b/config.ini @@ -21,7 +21,7 @@ port=8002 ip=127.0.0.1 # distance at which other players and NPCs become visible. # this value is used for calculating chunk size -viewdistance=30000 +viewdistance=25600 # time, in milliseconds, to wait before kicking a non-responsive client # default is 1 minute timeout=60000 diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index 4424dc9..413159e 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -8,15 +8,33 @@ std::map, Chunk*> ChunkManager::chunks; void ChunkManager::init() {} // stubbed +void ChunkManager::newChunk(std::tuple pos) { + Chunk *chunk = new Chunk(); + + chunk->players = std::set(); + chunk->NPCs = std::set(); + + // add the new chunk to every player and mob that's near it + for (Chunk *c : grabChunks(pos)) { + if (c == chunk) + continue; + + for (CNSocket *s : c->players) + PlayerManager::players[s].currentChunks.push_back(chunk); + + for (int32_t id : c->NPCs) + NPCManager::NPCs[id]->currentChunks.push_back(chunk); + } + + chunks[pos] = chunk; +} + 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()) { - chunks[pos] = new Chunk(); - chunks[pos]->players = std::set(); - chunks[pos]->NPCs = std::set(); - } + if (chunks.find(pos) == chunks.end()) + newChunk(pos); Chunk* chunk = chunks[pos]; @@ -27,11 +45,8 @@ void ChunkManager::addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* std::tuple pos = grabChunk(posX, posY, instanceID); // make chunk if it doesn't exist! - if (chunks.find(pos) == chunks.end()) { - chunks[pos] = new Chunk(); - chunks[pos]->players = std::set(); - chunks[pos]->NPCs = std::set(); - } + if (chunks.find(pos) == chunks.end()) + newChunk(pos); Chunk* chunk = chunks[pos]; @@ -212,7 +227,7 @@ void ChunkManager::createInstance(uint64_t instanceID) { BaseNPC* baseNPC = NPCManager::NPCs[npcID]; if (baseNPC->npcClass == NPC_MOB) { Mob* newMob = new Mob(baseNPC->appearanceData.iX, baseNPC->appearanceData.iY, baseNPC->appearanceData.iZ, baseNPC->appearanceData.iAngle, - instanceID, baseNPC->appearanceData.iNPCType, baseNPC->appearanceData.iHP, NPCManager::NPCData[baseNPC->appearanceData.iNPCType], newID); + instanceID, baseNPC->appearanceData.iNPCType, ((Mob*)baseNPC)->maxHealth, NPCManager::NPCData[baseNPC->appearanceData.iNPCType], newID); NPCManager::NPCs[newID] = newMob; MobManager::Mobs[newID] = newMob; } else { diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 67e59d6..db6633d 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -26,6 +26,7 @@ namespace ChunkManager { extern std::map, Chunk*> chunks; + void newChunk(std::tuple pos); 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); diff --git a/src/MobManager.cpp b/src/MobManager.cpp index d9e0d63..ed2c4f6 100644 --- a/src/MobManager.cpp +++ b/src/MobManager.cpp @@ -1046,7 +1046,7 @@ bool MobManager::aggroCheck(Mob *mob, time_t currTime) { if (plr->HP <= 0) continue; - int mobRange = mob->data["m_iSightRange"]; + int mobRange = mob->sightRange; if (plr->iConditionBitFlag & CSB_BIT_UP_STEALTH) mobRange /= 3; diff --git a/src/MobManager.hpp b/src/MobManager.hpp index 136d52b..b79f84e 100644 --- a/src/MobManager.hpp +++ b/src/MobManager.hpp @@ -35,6 +35,7 @@ struct Mob : public BaseNPC { // roaming int idleRange; + const int sightRange; time_t nextMovement = 0; bool staticPath = false; @@ -50,7 +51,9 @@ struct Mob : public BaseNPC { nlohmann::json data; 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) { + : BaseNPC(x, y, z, angle, iID, type, id), + maxHealth(hp), + sightRange(d["m_iSightRange"]) { state = MobState::ROAMING; data = d; diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index d8645c3..2892020 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -107,7 +107,7 @@ void NPCManager::addNPC(std::vector viewableChunks, int32_t id) { void NPCManager::destroyNPC(int32_t id) { // sanity check if (NPCs.find(id) == NPCs.end()) { - std::cout << "npc not found : " << id << std::endl; + std::cout << "npc not found: " << id << std::endl; return; } @@ -133,8 +133,6 @@ void NPCManager::destroyNPC(int32_t id) { // finally, remove it from the map and free it NPCs.erase(id); delete entity; - - std::cout << "npc removed!" << std::endl; } void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z, int angle) { @@ -601,7 +599,9 @@ 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) { uint64_t instanceID = Warps[warpId].instanceID; - if (Warps[warpId].limitTaskID != 0) { // if warp requires you to be on a mission, it's gotta be a unique instance + + // if warp requires you to be on a mission, it's gotta be a unique instance + if (Warps[warpId].limitTaskID != 0 || instanceID == 14) { // 14 is a special case for the Time Lab instanceID += ((uint64_t)plrv.plr->iIDGroup << 32); // upper 32 bits are leader ID ChunkManager::createInstance(instanceID); } diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index c3a441e..b43d377 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -793,9 +793,7 @@ void PlayerManager::revivePlayer(CNSocket* sock, CNPacketData* data) { NanoManager::nanoUnbuff(sock, CSB_BIT_PHOENIX, ECSB_PHOENIX, 0, false); plr->HP = PC_MAXHEALTH(plr->level); } else { - plr->x = target.x; - plr->y = target.y; - plr->z = target.z; + updatePlayerPosition(sock, target.x, target.y, target.z); if (reviveData->iRegenType != 5) plr->HP = PC_MAXHEALTH(plr->level); diff --git a/src/TableData.cpp b/src/TableData.cpp index e350274..8cddda3 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -264,14 +264,13 @@ void TableData::loadPaths(int* nextId) { for (nlohmann::json::iterator _sliderPoint = pathDataSlider.begin(); _sliderPoint != pathDataSlider.end(); _sliderPoint++) { auto sliderPoint = _sliderPoint.value(); if (sliderPoint["stop"]) { // check if this point in the circuit is a stop - if (stops % 2 == 0) { // on;y put a slider down every other stop // spawn a slider - BaseNPC* slider = new BaseNPC(sliderPoint["iX"], sliderPoint["iY"], sliderPoint["iZ"], 0, INSTANCE_OVERWORLD, 1, (*nextId)++, NPC_BUS); - NPCManager::NPCs[slider->appearanceData.iNPC_ID] = slider; - NPCManager::updateNPCPosition(slider->appearanceData.iNPC_ID, slider->appearanceData.iX, slider->appearanceData.iY, slider->appearanceData.iZ); - // set slider path to a rotation of the circuit - constructPathSlider(pathDataSlider, pos, slider->appearanceData.iNPC_ID); - } + BaseNPC* slider = new BaseNPC(sliderPoint["iX"], sliderPoint["iY"], sliderPoint["iZ"], 0, INSTANCE_OVERWORLD, 1, (*nextId)++, NPC_BUS); + NPCManager::NPCs[slider->appearanceData.iNPC_ID] = slider; + NPCManager::updateNPCPosition(slider->appearanceData.iNPC_ID, slider->appearanceData.iX, slider->appearanceData.iY, slider->appearanceData.iZ); + // set slider path to a rotation of the circuit + constructPathSlider(pathDataSlider, pos, slider->appearanceData.iNPC_ID); + stops++; } pos++; diff --git a/src/settings.cpp b/src/settings.cpp index b11beea..a8b85ff 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -12,7 +12,7 @@ int settings::DBSAVEINTERVAL = 240; int settings::SHARDPORT = 8002; std::string settings::SHARDSERVERIP = "127.0.0.1"; time_t settings::TIMEOUT = 60000; -int settings::VIEWDISTANCE = 40000; +int settings::VIEWDISTANCE = 25600; bool settings::SIMULATEMOBS = true; // default spawn point is Sector V (future)