From b22ba781c85250a568a295c52bdca2883fb851bc Mon Sep 17 00:00:00 2001 From: Gent S Date: Sat, 14 Nov 2020 18:36:04 -0500 Subject: [PATCH] Possible fix for chunking desyncs + CHUNKPOS macro --- src/CNStructs.hpp | 3 +++ src/ChunkManager.cpp | 40 ++++++++++++++++++++-------------------- src/ChunkManager.hpp | 21 +++++++++++---------- src/NPC.hpp | 2 +- src/NPCManager.cpp | 2 +- src/PlayerManager.cpp | 7 +++++-- src/PlayerManager.hpp | 2 +- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/CNStructs.hpp b/src/CNStructs.hpp index 28b4954..2233635 100644 --- a/src/CNStructs.hpp +++ b/src/CNStructs.hpp @@ -32,6 +32,9 @@ #define MAPNUM(x) ((x) & 0xffffffff) #define PLAYERID(x) ((x) >> 32) +// macro for chunk position type +#define CHUNKPOS std::tuple + // TODO: rewrite U16toU8 & U8toU16 to not use codecvt std::string U16toU8(char16_t* src); diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index e5c11d7..45a9b38 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -4,11 +4,11 @@ #include "settings.hpp" #include "MobManager.hpp" -std::map, Chunk*> ChunkManager::chunks; +std::map ChunkManager::chunks; void ChunkManager::init() {} // stubbed -void ChunkManager::newChunk(std::tuple pos) { +void ChunkManager::newChunk(CHUNKPOS pos) { Chunk *chunk = new Chunk(); chunk->players = std::set(); @@ -17,7 +17,7 @@ void ChunkManager::newChunk(std::tuple pos) { chunks[pos] = chunk; } -void ChunkManager::populateNewChunk(Chunk* chunk, std::tuple pos) {// add the new chunk to every player and mob that's near it +void ChunkManager::populateNewChunk(Chunk* chunk, CHUNKPOS pos) {// add the new chunk to every player and mob that's near it for (Chunk *c : grabChunks(pos)) { if (c == chunk) continue; @@ -31,7 +31,7 @@ void ChunkManager::populateNewChunk(Chunk* chunk, std::tuple } void ChunkManager::addNPC(int posX, int posY, uint64_t instanceID, int32_t id) { - std::tuple pos = grabChunk(posX, posY, instanceID); + CHUNKPOS pos = grabChunk(posX, posY, instanceID); bool newChunkUsed = false; @@ -54,7 +54,7 @@ void ChunkManager::addNPC(int posX, int posY, uint64_t instanceID, int32_t id) { } void ChunkManager::addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* sock) { - std::tuple pos = grabChunk(posX, posY, instanceID); + CHUNKPOS pos = grabChunk(posX, posY, instanceID); bool newChunkUsed = false; @@ -76,7 +76,7 @@ void ChunkManager::addPlayer(int posX, int posY, uint64_t instanceID, CNSocket* populateNewChunk(chunk, pos); } -bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocket* sock) { +bool ChunkManager::removePlayer(CHUNKPOS chunkPos, CNSocket* sock) { if (!checkChunk(chunkPos)) return false; // do nothing if chunk doesn't even exist @@ -96,7 +96,7 @@ bool ChunkManager::removePlayer(std::tuple chunkPos, CNSocke return false; } -bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id) { +bool ChunkManager::removeNPC(CHUNKPOS chunkPos, int32_t id) { if (!checkChunk(chunkPos)) return false; // do nothing if chunk doesn't even exist @@ -116,7 +116,7 @@ bool ChunkManager::removeNPC(std::tuple chunkPos, int32_t id return false; } -void ChunkManager::destroyChunk(std::tuple chunkPos) { +void ChunkManager::destroyChunk(CHUNKPOS chunkPos) { if (!checkChunk(chunkPos)) return; // chunk doesn't exist, we don't need to do anything @@ -158,15 +158,15 @@ void ChunkManager::destroyChunk(std::tuple chunkPos) { delete chunk; } -bool ChunkManager::checkChunk(std::tuple chunk) { +bool ChunkManager::checkChunk(CHUNKPOS chunk) { return chunks.find(chunk) != chunks.end(); } -std::tuple ChunkManager::grabChunk(int posX, int posY, uint64_t instanceID) { +CHUNKPOS 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(CHUNKPOS chunk) { std::vector chnks; chnks.reserve(9); @@ -177,7 +177,7 @@ std::vector ChunkManager::grabChunks(std::tuple chun // 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); + CHUNKPOS pos = std::make_tuple(x+i, y+z, inst); // if chunk exists, add it to the vector if (checkChunk(pos)) @@ -214,8 +214,8 @@ std::vector ChunkManager::getDeltaChunks(std::vector from, std:: /* * inefficient algorithm to get all chunks from a specific instance */ -std::vector> ChunkManager::getChunksInMap(uint64_t mapNum) { - std::vector> chnks; +std::vector ChunkManager::getChunksInMap(uint64_t mapNum) { + std::vector chnks; for (auto it = ChunkManager::chunks.begin(); it != ChunkManager::chunks.end(); it++) { if (std::get<2>(it->first) == mapNum) { @@ -240,10 +240,10 @@ bool ChunkManager::inPopulatedChunks(int posX, int posY, uint64_t instanceID) { void ChunkManager::createInstance(uint64_t instanceID) { - std::vector> templateChunks = ChunkManager::getChunksInMap(MAPNUM(instanceID)); // base instance chunks + std::vector templateChunks = ChunkManager::getChunksInMap(MAPNUM(instanceID)); // 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 &coords : templateChunks) { + for (CHUNKPOS &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++; @@ -268,9 +268,9 @@ void ChunkManager::createInstance(uint64_t instanceID) { void ChunkManager::destroyInstance(uint64_t instanceID) { - std::vector> instanceChunks = ChunkManager::getChunksInMap(instanceID); + std::vector instanceChunks = ChunkManager::getChunksInMap(instanceID); std::cout << "Deleting instance " << instanceID << " (" << instanceChunks.size() << " chunks)" << std::endl; - for (std::tuple& coords : instanceChunks) { + for (CHUNKPOS& coords : instanceChunks) { destroyChunk(coords); } } @@ -279,9 +279,9 @@ void ChunkManager::destroyInstanceIfEmpty(uint64_t instanceID) { if (PLAYERID(instanceID) == 0) return; // don't clean up overworld/IZ chunks - std::vector> sourceChunkCoords = getChunksInMap(instanceID); + std::vector sourceChunkCoords = getChunksInMap(instanceID); - for (std::tuple& coords : sourceChunkCoords) { + for (CHUNKPOS& coords : sourceChunkCoords) { Chunk* chunk = chunks[coords]; if (chunk->players.size() > 0) diff --git a/src/ChunkManager.hpp b/src/ChunkManager.hpp index 2c5e986..68349bc 100644 --- a/src/ChunkManager.hpp +++ b/src/ChunkManager.hpp @@ -1,6 +1,7 @@ #pragma once #include "CNProtocol.hpp" +#include "CNStructs.hpp" #include #include @@ -24,20 +25,20 @@ namespace ChunkManager { void init(); void cleanup(); - extern std::map, Chunk*> chunks; + extern std::map chunks; - void newChunk(std::tuple pos); - void populateNewChunk(Chunk* chunk, std::tuple pos); + void newChunk(CHUNKPOS pos); + void populateNewChunk(Chunk* chunk, CHUNKPOS 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); - 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); + bool removePlayer(CHUNKPOS chunkPos, CNSocket* sock); + bool removeNPC(CHUNKPOS chunkPos, int32_t id); + bool checkChunk(CHUNKPOS chunk); + void destroyChunk(CHUNKPOS chunkPos); + CHUNKPOS grabChunk(int posX, int posY, uint64_t instanceID); + std::vector grabChunks(CHUNKPOS chunkPos); std::vector getDeltaChunks(std::vector from, std::vector to); - std::vector> getChunksInMap(uint64_t mapNum); + std::vector getChunksInMap(uint64_t mapNum); bool inPopulatedChunks(int posX, int posY, uint64_t instanceID); void createInstance(uint64_t); diff --git a/src/NPC.hpp b/src/NPC.hpp index 384fc15..3d38028 100644 --- a/src/NPC.hpp +++ b/src/NPC.hpp @@ -8,7 +8,7 @@ public: sNPCAppearanceData appearanceData; NPCClass npcClass; uint64_t instanceID; - std::tuple chunkPos; + CHUNKPOS chunkPos; std::vector currentChunks; BaseNPC() {}; diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index d049d17..162cb87 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -185,7 +185,7 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) { npc->appearanceData.iY = Y; npc->appearanceData.iZ = Z; - std::tuple newPos = ChunkManager::grabChunk(X, Y, npc->instanceID); + 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) { diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index e04386b..27d6413 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -175,6 +175,9 @@ void PlayerManager::addPlayerToChunks(std::vector chunks, CNSocket* sock // add players for (CNSocket* otherSock : chunk->players) { + if (sock == otherSock) + continue; + Player *otherPlr = players[otherSock].plr; Player *plr = players[sock].plr; @@ -226,13 +229,14 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) { 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); + CHUNKPOS newPos = ChunkManager::grabChunk(X, Y, view.plr->instanceID); // nothing to be done if (newPos == view.chunkPos) return; // add player to chunk + ChunkManager::addPlayer(X, Y, view.plr->instanceID, sock); std::vector allChunks = ChunkManager::grabChunks(newPos); Chunk *chunk = nullptr; @@ -249,7 +253,6 @@ void PlayerManager::updatePlayerChunk(CNSocket* sock, int X, int Y, uint64_t ins view.chunkPos = newPos; view.currentChunks = allChunks; - ChunkManager::addPlayer(X, Y, view.plr->instanceID, sock); // takes care of adding the player to the chunk if it exists or not } void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I) { diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index 6214988..fe24c28 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -13,7 +13,7 @@ struct WarpLocation; struct PlayerView { - std::tuple chunkPos; + CHUNKPOS chunkPos; std::vector currentChunks; Player *plr; time_t lastHeartbeat;