aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/Collision/Management/MMapManager.cpp84
-rw-r--r--src/common/Collision/Management/MMapManager.h14
-rw-r--r--src/server/game/Maps/TerrainMgr.cpp21
-rw-r--r--src/server/scripts/Commands/cs_mmaps.cpp7
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp16
5 files changed, 93 insertions, 49 deletions
diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp
index b07642edbda..3b5431e1cc7 100644
--- a/src/common/Collision/Management/MMapManager.cpp
+++ b/src/common/Collision/Management/MMapManager.cpp
@@ -19,6 +19,7 @@
#include "Errors.h"
#include "Log.h"
#include "MMapDefines.h"
+#include "Memory.h"
namespace MMAP
{
@@ -58,14 +59,14 @@ namespace MMAP
return itr;
}
- bool MMapManager::loadMapData(std::string const& basePath, uint32 mapId)
+ LoadResult MMapManager::loadMapData(std::string const& basePath, uint32 mapId)
{
// we already have this map loaded?
MMapDataSet::iterator itr = loadedMMaps.find(mapId);
if (itr != loadedMMaps.end())
{
if (itr->second)
- return true;
+ return LoadResult::AlreadyLoaded;
}
else
{
@@ -77,20 +78,19 @@ namespace MMAP
// load and init dtNavMesh - read parameters from file
std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, basePath, mapId);
- FILE* file = fopen(fileName.c_str(), "rb");
+ auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
if (!file)
{
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '{}'", fileName);
- return false;
+ return LoadResult::FileNotFound;
}
dtNavMeshParams params;
- uint32 count = uint32(fread(&params, sizeof(dtNavMeshParams), 1, file));
- fclose(file);
+ uint32 count = uint32(fread(&params, sizeof(dtNavMeshParams), 1, file.get()));
if (count != 1)
{
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
- return false;
+ return LoadResult::ReadFromFileFailed;
}
dtNavMesh* mesh = dtAllocNavMesh();
@@ -99,7 +99,7 @@ namespace MMAP
{
dtFreeNavMesh(mesh);
TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04} from file {}", mapId, fileName);
- return false;
+ return LoadResult::LibraryError;
}
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:04}.mmap", mapId);
@@ -108,7 +108,7 @@ namespace MMAP
MMapData* mmap_data = new MMapData(mesh);
itr->second = mmap_data;
- return true;
+ return LoadResult::Success;
}
uint32 MMapManager::packTileID(int32 x, int32 y)
@@ -116,11 +116,17 @@ namespace MMAP
return uint32(x << 16 | y);
}
- bool MMapManager::loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y)
+ LoadResult MMapManager::loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y)
{
// make sure the mmap is loaded and ready to load tiles
- if (!loadMapData(basePath, mapId))
- return false;
+ switch (LoadResult mapResult = loadMapData(basePath, mapId))
+ {
+ case LoadResult::Success:
+ case LoadResult::AlreadyLoaded:
+ break;
+ default:
+ return mapResult;
+ }
// get this mmap data
MMapData* mmap = loadedMMaps[mapId];
@@ -129,68 +135,68 @@ namespace MMAP
// check if we already have this tile loaded
uint32 packedGridPos = packTileID(x, y);
if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
- return false;
+ return LoadResult::AlreadyLoaded;
// load this tile :: mmaps/MMMMXXYY.mmtile
std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, basePath, mapId, x, y);
- FILE* file = fopen(fileName.c_str(), "rb");
+ auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
if (!file)
{
auto parentMapItr = parentMapData.find(mapId);
if (parentMapItr != parentMapData.end())
{
fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, basePath, parentMapItr->second, x, y);
- file = fopen(fileName.c_str(), "rb");
+ file.reset(fopen(fileName.c_str(), "rb"));
}
}
if (!file)
{
TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '{}'", fileName);
- return false;
+ return LoadResult::FileNotFound;
}
// read header
MmapTileHeader fileHeader;
- if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC)
+ if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file.get()) != 1)
{
TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:04}{:02}{:02}.mmtile", mapId, x, y);
- fclose(file);
- return false;
+ return LoadResult::ReadFromFileFailed;
+ }
+
+ if (fileHeader.mmapMagic != MMAP_MAGIC)
+ {
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:04}{:02}{:02}.mmtile", mapId, x, y);
+ return LoadResult::VersionMismatch;
}
if (fileHeader.mmapVersion != MMAP_VERSION)
{
TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}{:02}{:02}.mmtile was built with generator v{}, expected v{}",
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
- fclose(file);
- return false;
+ return LoadResult::VersionMismatch;
}
- long pos = ftell(file);
- fseek(file, 0, SEEK_END);
- if (pos < 0 || static_cast<int32>(fileHeader.size) > ftell(file) - pos)
+ long pos = ftell(file.get());
+ fseek(file.get(), 0, SEEK_END);
+ if (pos < 0 || static_cast<int32>(fileHeader.size) > ftell(file.get()) - pos)
{
TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}{:02}{:02}.mmtile has corrupted data size", mapId, x, y);
- fclose(file);
- return false;
+ return LoadResult::ReadFromFileFailed;
}
- fseek(file, pos, SEEK_SET);
+ fseek(file.get(), pos, SEEK_SET);
unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
ASSERT(data);
- size_t result = fread(data, fileHeader.size, 1, file);
+ size_t result = fread(data, fileHeader.size, 1, file.get());
if (!result)
{
TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap {:04}{:02}{:02}.mmtile", mapId, x, y);
- fclose(file);
- return false;
+ return LoadResult::ReadFromFileFailed;
}
- fclose(file);
-
dtMeshHeader* header = (dtMeshHeader*)data;
dtTileRef tileRef = 0;
@@ -200,20 +206,26 @@ namespace MMAP
mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
++loadedTiles;
TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile {:04}[{:02}, {:02}] into {:04}[{:02}, {:02}]", mapId, x, y, mapId, header->x, header->y);
- return true;
+ return LoadResult::Success;
}
else
{
TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load {:04}{:02}{:02}.mmtile into navmesh", mapId, x, y);
dtFree(data);
- return false;
+ return LoadResult::LibraryError;
}
}
bool MMapManager::loadMapInstance(std::string const& basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
{
- if (!loadMapData(basePath, meshMapId))
- return false;
+ switch (loadMapData(basePath, meshMapId))
+ {
+ case LoadResult::Success:
+ case LoadResult::AlreadyLoaded:
+ break;
+ default:
+ return false;
+ }
MMapData* mmap = loadedMMaps[meshMapId];
auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId }, nullptr);
diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h
index fe32152e138..45c0466e687 100644
--- a/src/common/Collision/Management/MMapManager.h
+++ b/src/common/Collision/Management/MMapManager.h
@@ -54,6 +54,16 @@ namespace MMAP
typedef std::unordered_map<uint32, MMapData*> MMapDataSet;
+ enum class LoadResult : uint8
+ {
+ Success,
+ AlreadyLoaded,
+ FileNotFound,
+ VersionMismatch,
+ ReadFromFileFailed,
+ LibraryError
+ };
+
// singleton class
// holds all all access to mmap loading unloading and meshes
class TC_COMMON_API MMapManager
@@ -63,7 +73,7 @@ namespace MMAP
~MMapManager();
void InitializeThreadUnsafe(std::unordered_map<uint32, std::vector<uint32>> const& mapData);
- bool loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y);
+ LoadResult loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y);
bool loadMapInstance(std::string const& basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
bool unloadMap(uint32 mapId, int32 x, int32 y);
bool unloadMap(uint32 mapId);
@@ -76,7 +86,7 @@ namespace MMAP
uint32 getLoadedTilesCount() const { return loadedTiles; }
uint32 getLoadedMapsCount() const { return uint32(loadedMMaps.size()); }
private:
- bool loadMapData(std::string const& basePath, uint32 mapId);
+ LoadResult loadMapData(std::string const& basePath, uint32 mapId);
uint32 packTileID(int32 x, int32 y);
MMapDataSet::const_iterator GetMMapData(uint32 mapId) const;
diff --git a/src/server/game/Maps/TerrainMgr.cpp b/src/server/game/Maps/TerrainMgr.cpp
index a18373dc248..2e6d8e184b9 100644
--- a/src/server/game/Maps/TerrainMgr.cpp
+++ b/src/server/game/Maps/TerrainMgr.cpp
@@ -239,12 +239,21 @@ void TerrainInfo::LoadMMap(int32 gx, int32 gy)
if (!DisableMgr::IsPathfindingEnabled(GetId()))
return;
- bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(sWorld->GetDataPath(), GetId(), gx, gy);
-
- if (mmapLoadResult)
- TC_LOG_DEBUG("mmaps.tiles", "MMAP loaded name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
- else
- TC_LOG_WARN("mmaps.tiles", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
+ switch (MMAP::LoadResult mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(sWorld->GetDataPath(), GetId(), gx, gy))
+ {
+ case MMAP::LoadResult::Success:
+ TC_LOG_DEBUG("mmaps.tiles", "MMAP loaded name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{})", GetMapName(), GetId(), gx, gy, gx, gy);
+ break;
+ case MMAP::LoadResult::AlreadyLoaded:
+ break;
+ case MMAP::LoadResult::FileNotFound:
+ if (_parentTerrain)
+ break; // don't log tile not found errors for child maps
+ [[fallthrough]];
+ default:
+ TC_LOG_WARN("mmaps.tiles", "Could not load MMAP name:{}, id:{}, x:{}, y:{} (mmap rep.: x:{}, y:{}) result: {}", GetMapName(), GetId(), gx, gy, gx, gy, AsUnderlyingType(mmapLoadResult));
+ break;
+ }
}
void TerrainInfo::UnloadMap(int32 gx, int32 gy)
diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp
index 94004eb8125..2b4fc01675e 100644
--- a/src/server/scripts/Commands/cs_mmaps.cpp
+++ b/src/server/scripts/Commands/cs_mmaps.cpp
@@ -138,11 +138,12 @@ public:
float x, y, z;
player->GetPosition(x, y, z);
- handler->PSendSysMessage("%04u%02i%02i.mmtile", player->GetMapId(), gx, gy);
- handler->PSendSysMessage("tileloc [%i, %i]", gy, gx);
-
// calculate navmesh tile location
uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMapId(), player->GetMap()->GetTerrain(), x, y);
+
+ handler->PSendSysMessage("%04u%02i%02i.mmtile", terrainMapId, gx, gy);
+ handler->PSendSysMessage("tileloc [%i, %i]", gy, gx);
+
dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(terrainMapId);
dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetMapId(), player->GetInstanceId());
if (!navmesh || !navmeshquery)
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index 03e8e88c763..a133b364059 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -866,7 +866,7 @@ namespace MMAP
// DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
// is removed via removeTile()
dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
- if (!tileRef || dtResult != DT_SUCCESS)
+ if (!tileRef || !dtStatusSucceed(dtResult))
{
printf("%s Failed adding tile to navmesh! \n", tileString.c_str());
break;
@@ -942,7 +942,19 @@ namespace MMAP
bool MapBuilder::shouldSkipMap(uint32 mapID) const
{
if (m_mapid >= 0)
- return static_cast<uint32>(m_mapid) != mapID;
+ {
+ int32 parentMapId = m_mapid;
+ do
+ {
+ if (static_cast<uint32>(parentMapId) == mapID)
+ return false;
+
+ parentMapId = sMapStore[parentMapId].ParentMapID;
+
+ } while (parentMapId != -1);
+
+ return true;
+ }
if (m_skipContinents)
if (isContinentMap(mapID))