diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index cbb10923fe..db9f2f5099 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -19,6 +19,7 @@ #include "MMapManager.h" #include "Log.h" #include "World.h" +#include "DBCStores.h" namespace MMAP { @@ -157,6 +158,9 @@ namespace MMAP mmap->mmapLoadedTiles.insert(std::pair(packedGridPos, tileRef)); ++loadedTiles; TC_LOG_INFO("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); + + LoadPhaseTiles(mapId, x, y); + return true; } else @@ -169,6 +173,101 @@ namespace MMAP return false; } + unsigned char* MMapManager::LoadTile(uint32 mapId, int32 x, int32 y) + { + // load this tile :: mmaps/MMMXXYY.mmtile + uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1; + char *fileName = new char[pathLen]; + + snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); + + FILE* file = fopen(fileName, "rb"); + if (!file) + { + TC_LOG_DEBUG("phase", "MMAP:LoadTile: Could not open mmtile file '%s'", fileName); + delete[] fileName; + return NULL; + } + delete[] fileName; + + // read header + MmapTileHeader fileHeader; + if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) + { + TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); + fclose(file); + return NULL; + } + + if (fileHeader.mmapVersion != MMAP_VERSION) + { + TC_LOG_ERROR("phase", "MMAP:LoadTile: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); + fclose(file); + return NULL; + } + + unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM); + ASSERT(data); + + size_t result = fread(data, fileHeader.size, 1, file); + if (!result) + { + TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); + fclose(file); + return NULL; + } + + fclose(file); + + return data; + } + + void MMapManager::LoadPhaseTiles(uint32 mapId, int32 x, int32 y) + { + TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loading phased mmtiles for map %u, x: %i, y: %i", mapId, x, y); + + uint32 packedGridPos = packTileID(x, y); + + for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) + { + if (const MapEntry* const map = sMapStore.LookupEntry(i)) + { + if (map->rootPhaseMap == mapId) + { + unsigned char* data = LoadTile(mapId, x, y); + if (!data) + { + // only a few tiles have terrain swaps, do not write error for them + //TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Could not load phased %03u%02i%02i.mmtile for root phase map %u", map->MapID, x, y, mapId); + } + else + { + TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %03u%02i%02i.mmtile for root phase map %u", map->MapID, x, y, mapId); + _phaseTiles[map->MapID][packedGridPos] = data; + } + } + } + } + } + + void MMapManager::UnloadPhaseTile(uint32 mapId, int32 x, int32 y) + { + TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloading phased mmtiles for map %u, x: %i, y: %i", mapId, x, y); + + uint32 packedGridPos = packTileID(x, y); + + const MapEntry* const map = sMapStore.LookupEntry(mapId); // map existence already checked when loading + uint32 rootMapId = map->rootPhaseMap; + + if (_phaseTiles[mapId][packedGridPos]) + { + TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %03u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId); + delete _phaseTiles[mapId][packedGridPos]; + _phaseTiles[mapId].erase(packedGridPos); + } + } + bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) { // check if we have this map loaded @@ -206,6 +305,8 @@ namespace MMAP mmap->mmapLoadedTiles.erase(packedGridPos); --loadedTiles; TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); + + UnloadPhaseTile(mapId, x, y); return true; } @@ -231,6 +332,7 @@ namespace MMAP TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); else { + UnloadPhaseTile(mapId, x, y); --loadedTiles; TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); } diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h index 798d020653..45b3db3dfd 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/server/collision/Management/MMapManager.h @@ -25,6 +25,7 @@ #include "DetourNavMeshQuery.h" #include #include +#include // move map related classes namespace MMAP @@ -55,6 +56,9 @@ namespace MMAP typedef std::unordered_map MMapDataSet; + typedef std::unordered_map PhaseTileContainer; + typedef std::unordered_map PhaseTileMap; + // singleton class // holds all all access to mmap loading unloading and meshes class MMapManager @@ -74,12 +78,21 @@ namespace MMAP uint32 getLoadedTilesCount() const { return loadedTiles; } uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } + + void LoadPhaseTiles(uint32 mapId, int32 x, int32 y); + void UnloadPhaseTile(uint32 mapId, int32 x, int32 y); + PhaseTileMap& GetPhaseTileStore() { return _phaseTiles; } + PhaseTileContainer& GetPhaseTileContainer(uint32 mapId) { return _phaseTiles[mapId]; } + private: bool loadMapData(uint32 mapId); uint32 packTileID(int32 x, int32 y); MMapDataSet loadedMMaps; uint32 loadedTiles; + + unsigned char* LoadTile(uint32 mapId, int32 x, int32 y); + PhaseTileMap _phaseTiles; }; } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index de62005642..ebb3a60779 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3122,6 +3122,7 @@ Logger.sql.sql=5,Console DBErrors #Logger.network.opcode=3,Console Server #Logger.network.soap=3,Console Server #Logger.outdoorpvp=3,Console Server +#Logger.phase=3,Console Server #Logger.pool=3,Console Server #Logger.rbac=3,Console Server #Logger.scripts=3,Console Server