32 using NavMeshQuerySet = std::unordered_map<std::pair<uint32, uint32>, dtNavMeshQuery>;
55 case 0:
case 1:
case 571:
case 603:
case 607:
case 609:
case 616:
case 628:
case 631:
case 644:
case 649:
case 720:
56 case 732:
case 754:
case 755:
case 861:
case 938:
case 940:
case 962:
case 967:
case 1064:
case 1076:
case 1098:
57 case 1122:
case 1126:
case 1182:
case 1205:
case 1220:
case 1265:
case 1492:
case 1523:
case 1530:
case 1579:
case 1676:
58 case 1704:
case 1705:
case 1706:
case 1707:
case 1734:
case 1756:
case 1943:
case 2076:
case 2118:
case 2160:
case 2161:
59 case 2187:
case 2212:
case 2235:
case 2237:
case 2264:
case 2450:
case 2512:
case 2586:
case 2601:
case 2654:
case 2657:
60 case 2660:
case 2669:
case 2819:
case 2828:
99 for (
auto const& [mapId, childMapIds] : mapData)
102 for (
uint32 childMapId : childMapIds)
110 MMapDataSet::const_iterator itr =
loadedMMaps.find(mapId);
125 MMapDataSet::iterator itr =
loadedMMaps.find(mapId);
126 ASSERT(itr !=
loadedMMaps.end(),
"Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId);
128 auto [meshItr, needsLoading] = itr->second->GetMeshData(mapId, instanceId);
134 itr->second->meshData.erase(*m);
142 if (dtStatusFailed(meshItr->second.navMesh.init(&
params)))
144 TC_LOG_ERROR(
"maps",
"MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:04}", mapId);
148 TC_LOG_DEBUG(
"maps",
"MMAP:loadMapData: Loaded {:04}.mmap", mapId);
149 (void)loadGuard.release();
155 std::vector<OffMeshData>* offmeshConnections )
158 auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(),
"rb"));
161 TC_LOG_DEBUG(
"maps",
"MMAP:loadMapData: Error: Could not open mmap file '{}'", fileName);
168 TC_LOG_DEBUG(
"maps",
"MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
174 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: Bad header in mmap {:04}.mmap", mapId);
180 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: {:04}.mmap was built with generator v{}, expected v{}",
185 memcpy(
params, &fileHeader.
params,
sizeof(dtNavMeshParams));
187 if (offmeshConnections)
190 if (fread(offmeshConnections->data(),
sizeof(
OffMeshData), offmeshConnections->size(), file.get()) != offmeshConnections->size())
192 offmeshConnections->clear();
193 TC_LOG_DEBUG(
"maps",
"MMAP:loadMapData: Error: Could not read offmesh connections from file '{}'", fileName);
203 return uint32(x << 16 | y);
229 auto file = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(fileName.c_str(),
"rb"));
236 file.reset(fopen(fileName.c_str(),
"rb"));
242 TC_LOG_DEBUG(
"maps",
"MMAP:loadMap: Could not open mmtile file '{}'", fileName);
248 if (fread(&fileHeader,
sizeof(
MmapTileHeader), 1, file.get()) != 1)
250 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: Bad header in mmap {:04}_{:02}_{:02}.mmtile", mapId, x, y);
256 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: Bad header in mmap {:04}_{:02}_{:02}.mmtile", mapId, x, y);
262 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: {:04}_{:02}_{:02}.mmtile was built with generator v{}, expected v{}",
267 long pos = ftell(file.get());
268 fseek(file.get(), 0, SEEK_END);
269 if (pos < 0 ||
static_cast<int32>(fileHeader.
size) > ftell(file.get()) - pos)
271 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: {:04}_{:02}_{:02}.mmtile has corrupted data size", mapId, x, y);
275 fseek(file.get(), pos, SEEK_SET);
277 auto data = Trinity::make_unique_ptr_with_deleter<&::dtFree>(dtAlloc(fileHeader.
size, DT_ALLOC_PERM));
280 size_t result = fread(data.get(), fileHeader.
size, 1, file.get());
283 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: Bad header or data in mmap {:04}_{:02}_{:02}.mmtile", mapId, x, y);
287 dtMeshHeader* header =
static_cast<dtMeshHeader*
>(data.get());
288 dtTileRef tileRef = 0;
291 if (dtStatusSucceed(meshData.
navMesh.addTile(
static_cast<unsigned char*
>(data.release()), fileHeader.
size, DT_TILE_FREE_DATA, 0, &tileRef)))
295 TC_LOG_DEBUG(
"maps",
"MMAP:loadMap: Loaded mmtile {:04}[{:02}, {:02}] into {:04}[{:02}, {:02}]", mapId, x, y, mapId, header->x, header->y);
300 TC_LOG_ERROR(
"maps",
"MMAP:loadMap: Could not load {:04}_{:02}_{:02}.mmtile into navmesh", mapId, x, y);
307 switch (
loadMapData(basePath, meshMapId, instanceId))
317 auto [queryItr, inserted] = mmap->
navMeshQueries.try_emplace({ instanceMapId, instanceId });
327 if (dtStatusFailed(queryItr->second.init(&mmap->
GetMeshData(meshMapId, instanceId).first->second.navMesh, 1024)))
329 TC_LOG_ERROR(
"maps",
"MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId);
333 TC_LOG_DEBUG(
"maps",
"MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId);
334 (void)loadGuard.release();
341 MMapDataSet::const_iterator itr =
GetMMapData(mapId);
345 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Asked to unload not loaded navmesh map. {:04}_{:02}_{:02}.mmtile", mapId, x, y);
351 for (
auto& [instanceId, meshData] : mmap->
meshData)
354 auto tileRef = meshData.loadedTileRefs.extract(packedGridPos);
359 if (dtStatusFailed(meshData.navMesh.removeTile(tileRef.mapped(),
nullptr,
nullptr)))
364 TC_LOG_ERROR(
"maps",
"MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y);
370 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:03}", mapId, x, y, mapId);
377 MMapDataSet::iterator itr =
loadedMMaps.find(mapId);
381 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Asked to unload not loaded navmesh map {:04}", mapId);
387 if (MeshDataMap::node_type meshNode = itr->second->RemoveMeshData(mapId, 0))
389 for (
auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs)
391 uint32 x = (tileId >> 16);
392 uint32 y = (tileId & 0x0000FFFF);
393 if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef,
nullptr,
nullptr)))
394 TC_LOG_ERROR(
"maps",
"MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y);
398 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId);
406 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Unloaded {:04}.mmap", mapId);
412 MMapDataSet::const_iterator itr =
GetMMapData(meshMapId);
416 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMapInstance: Asked to unload not loaded navmesh map {:04}", meshMapId);
421 std::size_t erased = mmap->
navMeshQueries.erase({ instanceMapId, instanceId });
423 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:04} instanceId {}", instanceMapId, instanceId);
427 if (MeshDataMap::node_type meshNode = mmap->
RemoveMeshData(meshMapId, instanceId))
430 for (
auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs)
432 uint32 x = (tileId >> 16);
433 uint32 y = (tileId & 0x0000FFFF);
434 if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef,
nullptr,
nullptr)))
435 TC_LOG_ERROR(
"maps",
"MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y);
439 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId);
445 TC_LOG_DEBUG(
"maps",
"MMAP:unloadMapInstance: Unloaded mapId {:04} instanceId {}", instanceMapId, instanceId);
450 MMapDataSet::const_iterator itr =
GetMMapData(mapId);
454 MeshDataMap::iterator meshItr = itr->second->FindMeshData(mapId, instanceId);
455 if (meshItr == itr->second->meshData.end())
458 return &meshItr->second.navMesh;
463 MMapDataSet::const_iterator itr =
GetMMapData(meshMapId);
467 auto queryItr = itr->second->navMeshQueries.find({ instanceMapId, instanceId });
468 if (queryItr == itr->second->navMeshQueries.end())
471 return &queryItr->second;
std::unordered_set< uint32 > params[2]
#define TC_LOG_DEBUG(filterType__, message__,...)
#define TC_LOG_ERROR(filterType__, message__,...)
uint32 constexpr MMAP_VERSION
uint32 constexpr MMAP_MAGIC
static bool isRebuildingTilesEnabledOnMap(uint32 mapId)
static MMapManager * instance()
dtNavMesh * GetNavMesh(uint32 mapId, uint32 instanceId)
bool loadMapInstance(std::string_view basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
LoadResult loadMap(std::string_view basePath, uint32 mapId, uint32 instanceId, int32 x, int32 y)
std::unordered_map< uint32, uint32 > parentMapData
void unloadMap(uint32 mapId, int32 x, int32 y)
void unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
MMapDataSet::const_iterator GetMMapData(uint32 mapId) const
void InitializeThreadUnsafe(std::unordered_map< uint32, std::vector< uint32 > > const &mapData)
LoadResult loadMapData(std::string_view basePath, uint32 mapId, uint32 instanceId)
dtNavMeshQuery const * GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
uint32 packTileID(int32 x, int32 y)
static LoadResult parseNavMeshParamsFile(std::string_view basePath, uint32 mapId, dtNavMeshParams *params, std::vector< OffMeshData > *offmeshConnections=nullptr)
std::unordered_map< uint32, MMapMapData > MeshDataMap
std::unordered_map< uint32, dtTileRef > MMapTileSet
constexpr char TILE_FILE_NAME_FORMAT[]
std::unordered_map< std::pair< uint32, uint32 >, dtNavMeshQuery > NavMeshQuerySet
constexpr char MAP_FILE_NAME_FORMAT[]
auto MapGetValuePtr(M &map, typename M::key_type const &key)
std::unique_ptr< T, Impl::stateful_unique_ptr_deleter< Ptr, Del > > make_unique_ptr_with_deleter(Ptr ptr, Del deleter)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
static uint32 GetInstanceIdForMeshLookup(uint32 mapId, uint32 instanceId)
MeshDataMap::node_type RemoveMeshData(uint32 mapId, uint32 instanceId)
MeshDataMap::iterator FindMeshData(uint32 mapId, uint32 instanceId)
NavMeshQuerySet navMeshQueries
std::pair< MeshDataMap::iterator, bool > GetMeshData(uint32 mapId, uint32 instanceId)
MMapTileSet loadedTileRefs