aboutsummaryrefslogtreecommitdiff
path: root/src/common/Collision
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Collision')
-rw-r--r--src/common/Collision/Management/MMapManager.cpp79
-rw-r--r--src/common/Collision/Management/MMapManager.h3
-rw-r--r--src/common/Collision/Maps/MMapDefines.h51
3 files changed, 97 insertions, 36 deletions
diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp
index c10d64bfd36..d0862a49156 100644
--- a/src/common/Collision/Management/MMapManager.cpp
+++ b/src/common/Collision/Management/MMapManager.cpp
@@ -26,7 +26,7 @@
namespace MMAP
{
constexpr char MAP_FILE_NAME_FORMAT[] = "{}mmaps/{:04}.mmap";
- constexpr char TILE_FILE_NAME_FORMAT[] = "{}mmaps/{:04}{:02}{:02}.mmtile";
+ constexpr char TILE_FILE_NAME_FORMAT[] = "{}mmaps/{:04}_{:02}_{:02}.mmtile";
using NavMeshPtr = std::unique_ptr<dtNavMesh, decltype(Trinity::unique_ptr_deleter<dtNavMesh*, &::dtFreeNavMesh>())>;
using NavMeshQueryPtr = std::unique_ptr<dtNavMeshQuery, decltype(Trinity::unique_ptr_deleter<dtNavMeshQuery*, &::dtFreeNavMeshQuery>())>;
@@ -97,6 +97,28 @@ namespace MMAP
}
// load and init dtNavMesh - read parameters from file
+ dtNavMeshParams params;
+ if (LoadResult paramsResult = parseNavMeshParamsFile(basePath, mapId, &params); paramsResult != LoadResult::Success)
+ return paramsResult;
+
+ NavMeshPtr mesh(dtAllocNavMesh());
+ ASSERT(mesh);
+ if (dtStatusFailed(mesh->init(&params)))
+ {
+ TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04}", mapId);
+ return LoadResult::LibraryError;
+ }
+
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:04}.mmap", mapId);
+
+ // store inside our map list
+ itr->second.reset(new MMapData(std::move(mesh)));
+ return LoadResult::Success;
+ }
+
+ LoadResult MMapManager::parseNavMeshParamsFile(std::string_view basePath, uint32 mapId, dtNavMeshParams* params,
+ std::vector<OffMeshData>* offmeshConnections /*= nullptr*/)
+ {
std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, basePath, mapId);
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
if (!file)
@@ -105,26 +127,39 @@ namespace MMAP
return LoadResult::FileNotFound;
}
- dtNavMeshParams params;
- uint32 count = uint32(fread(&params, sizeof(dtNavMeshParams), 1, file.get()));
- if (count != 1)
+ MmapNavMeshHeader fileHeader;
+ if (fread(&fileHeader, sizeof(MmapNavMeshHeader), 1, file.get()) != 1)
{
TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
return LoadResult::ReadFromFileFailed;
}
- NavMeshPtr mesh(dtAllocNavMesh());
- ASSERT(mesh);
- if (dtStatusFailed(mesh->init(&params)))
+ if (fileHeader.mmapMagic != MMAP_MAGIC)
{
- TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04} from file {}", mapId, fileName);
- return LoadResult::LibraryError;
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:04}.mmap", mapId);
+ return LoadResult::VersionMismatch;
}
- TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:04}.mmap", mapId);
+ if (fileHeader.mmapVersion != MMAP_VERSION)
+ {
+ TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}.mmap was built with generator v{}, expected v{}",
+ mapId, fileHeader.mmapVersion, MMAP_VERSION);
+ return LoadResult::VersionMismatch;
+ }
+
+ memcpy(params, &fileHeader.params, sizeof(dtNavMeshParams));
+
+ if (offmeshConnections)
+ {
+ offmeshConnections->resize(fileHeader.offmeshConnectionCount);
+ if (fread(offmeshConnections->data(), sizeof(OffMeshData), offmeshConnections->size(), file.get()) != offmeshConnections->size())
+ {
+ offmeshConnections->clear();
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read offmesh connections from file '{}'", fileName);
+ return LoadResult::ReadFromFileFailed;
+ }
+ }
- // store inside our map list
- itr->second.reset(new MMapData(std::move(mesh)));
return LoadResult::Success;
}
@@ -154,7 +189,7 @@ namespace MMAP
if (mmap->loadedTileRefs.contains(packedGridPos))
return LoadResult::AlreadyLoaded;
- // load this tile :: mmaps/MMMMXXYY.mmtile
+ // load this tile :: mmaps/MMMM_XX_YY.mmtile
std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, basePath, mapId, x, y);
auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(), "rb"));
if (!file)
@@ -177,19 +212,19 @@ namespace MMAP
MmapTileHeader fileHeader;
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);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:04}_{:02}_{:02}.mmtile", mapId, x, y);
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);
+ 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{}",
+ TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}_{:02}_{:02}.mmtile was built with generator v{}, expected v{}",
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
return LoadResult::VersionMismatch;
}
@@ -198,7 +233,7 @@ namespace MMAP
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);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: {:04}_{:02}_{:02}.mmtile has corrupted data size", mapId, x, y);
return LoadResult::ReadFromFileFailed;
}
@@ -210,7 +245,7 @@ namespace MMAP
size_t result = fread(data.get(), 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);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap {:04}_{:02}_{:02}.mmtile", mapId, x, y);
return LoadResult::ReadFromFileFailed;
}
@@ -227,7 +262,7 @@ namespace MMAP
}
else
{
- TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load {:04}{:02}{:02}.mmtile into navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load {:04}_{:02}_{:02}.mmtile into navmesh", mapId, x, y);
return LoadResult::LibraryError;
}
}
@@ -270,7 +305,7 @@ namespace MMAP
if (itr == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. {:04}{:02}{:02}.mmtile", mapId, x, y);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. {:04}_{:02}_{:02}.mmtile", mapId, x, y);
return false;
}
@@ -292,7 +327,7 @@ namespace MMAP
// this is technically a memory leak
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
// we cannot recover from this error - assert out
- TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}{:02}{:02}.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y);
ABORT();
}
else
@@ -322,7 +357,7 @@ namespace MMAP
uint32 x = (tileId >> 16);
uint32 y = (tileId & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr)))
- TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}{:02}{:02}.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y);
else
{
--loadedTiles;
diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h
index 9973f37d51c..b48b773555b 100644
--- a/src/common/Collision/Management/MMapManager.h
+++ b/src/common/Collision/Management/MMapManager.h
@@ -19,7 +19,7 @@
#define _MMAP_MANAGER_H
#include "Define.h"
-#include <DetourNavMesh.h>
+#include "MMapDefines.h"
#include <DetourNavMeshQuery.h>
#include <memory>
#include <string_view>
@@ -58,6 +58,7 @@ namespace MMAP
static MMapManager* instance();
void InitializeThreadUnsafe(std::unordered_map<uint32, std::vector<uint32>> const& mapData);
+ static LoadResult parseNavMeshParamsFile(std::string_view basePath, uint32 mapId, dtNavMeshParams* params, std::vector<OffMeshData>* offmeshConnections = nullptr);
LoadResult loadMap(std::string_view basePath, uint32 mapId, int32 x, int32 y);
bool loadMapInstance(std::string_view basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
bool unloadMap(uint32 mapId, int32 x, int32 y);
diff --git a/src/common/Collision/Maps/MMapDefines.h b/src/common/Collision/Maps/MMapDefines.h
index 368281543a2..522112ebe62 100644
--- a/src/common/Collision/Maps/MMapDefines.h
+++ b/src/common/Collision/Maps/MMapDefines.h
@@ -19,22 +19,29 @@
#define MMapDefines_h__
#include "Define.h"
-#include "DetourNavMesh.h"
+#include <DetourNavMesh.h>
-const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
-#define MMAP_VERSION 15
+inline uint32 constexpr MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
+inline uint32 constexpr MMAP_VERSION = 16;
-struct MmapTileHeader
+struct MmapNavMeshHeader
{
- uint32 mmapMagic;
- uint32 dtVersion;
- uint32 mmapVersion;
- uint32 size;
- char usesLiquids;
- char padding[3];
+ uint32 mmapMagic = MMAP_MAGIC;
+ uint32 mmapVersion = MMAP_VERSION;
+ dtNavMeshParams params = { };
+ uint32 offmeshConnectionCount = 0;
+};
+
+static_assert(sizeof(MmapNavMeshHeader) == 40);
- MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION),
- mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() { }
+struct MmapTileHeader
+{
+ uint32 mmapMagic = MMAP_MAGIC;
+ uint32 dtVersion = DT_NAVMESH_VERSION;
+ uint32 mmapVersion = MMAP_VERSION;
+ uint32 size = 0;
+ char usesLiquids = true;
+ char padding[3] = { };
};
// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files
@@ -60,7 +67,7 @@ enum NavArea
NAV_AREA_ALL_MASK = 0x3F // max allowed value
};
-enum NavTerrainFlag
+enum NavTerrainFlag : uint16
{
NAV_EMPTY = 0x00,
NAV_GROUND = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_GROUND),
@@ -69,4 +76,22 @@ enum NavTerrainFlag
NAV_MAGMA_SLIME = 1 << (NAV_AREA_MAX_VALUE - NAV_AREA_MAGMA_SLIME)
};
+enum OffMeshConnectionFlag : uint8
+{
+ OFFMESH_CONNECTION_FLAG_BIDIRECTIONAL = 0x01
+};
+
+struct OffMeshData
+{
+ uint32 MapId;
+ uint32 TileX;
+ uint32 TileY;
+ float From[3];
+ float To[3];
+ float Radius;
+ OffMeshConnectionFlag ConnectionFlags;
+ uint8 AreaId;
+ NavTerrainFlag Flags;
+};
+
#endif // MMapDefines_h__