mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/MMaps: Allow loading mmap meshes per map instance
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "Hash.h"
|
||||
#include "Log.h"
|
||||
#include "MMapDefines.h"
|
||||
#include "MapUtils.h"
|
||||
#include "Memory.h"
|
||||
#include <algorithm>
|
||||
|
||||
@@ -28,22 +29,44 @@ namespace MMAP
|
||||
constexpr char MAP_FILE_NAME_FORMAT[] = "{}mmaps/{:04}.mmap";
|
||||
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>())>;
|
||||
static thread_local bool thread_safe_environment = false;
|
||||
|
||||
typedef std::unordered_map<std::pair<uint32, uint32>, NavMeshQueryPtr> NavMeshQuerySet;
|
||||
typedef std::unordered_map<uint32, dtTileRef> MMapTileSet;
|
||||
using NavMeshQuerySet = std::unordered_map<std::pair<uint32, uint32>, dtNavMeshQuery>;
|
||||
using MMapTileSet = std::unordered_map<uint32, dtTileRef>;
|
||||
|
||||
struct MMapMapData
|
||||
{
|
||||
dtNavMesh navMesh;
|
||||
MMapTileSet loadedTileRefs; // maps [map grid coords] to [dtTile]
|
||||
};
|
||||
|
||||
using MeshDataMap = std::unordered_map<uint32, MMapMapData>;
|
||||
|
||||
// dummy struct to hold map's mmap data
|
||||
struct MMapData
|
||||
{
|
||||
explicit MMapData(NavMeshPtr&& mesh) : navMesh(std::move(mesh)) { }
|
||||
MeshDataMap meshData;
|
||||
|
||||
// we have to use single dtNavMeshQuery for every instance, since those are not thread safe
|
||||
NavMeshQuerySet navMeshQueries; // instanceId to query
|
||||
|
||||
NavMeshPtr navMesh;
|
||||
MMapTileSet loadedTileRefs; // maps [map grid coords] to [dtTile]
|
||||
static uint32 GetInstanceIdForMeshLookup([[maybe_unused]] uint32 mapId, [[maybe_unused]] uint32 instanceId)
|
||||
{
|
||||
// for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::pair<MeshDataMap::iterator, bool> GetMeshData(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
// for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances
|
||||
return meshData.try_emplace(GetInstanceIdForMeshLookup(mapId, instanceId));
|
||||
}
|
||||
|
||||
MeshDataMap::iterator FindMeshData(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
// for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances
|
||||
return meshData.find(GetInstanceIdForMeshLookup(mapId, instanceId));
|
||||
}
|
||||
};
|
||||
|
||||
// ######################## MMapManager ########################
|
||||
@@ -61,12 +84,13 @@ namespace MMAP
|
||||
// the caller must pass the list of all mapIds that will be used in the MMapManager lifetime
|
||||
for (auto const& [mapId, childMapIds] : mapData)
|
||||
{
|
||||
loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr));
|
||||
loadedMMaps[mapId].reset(new MMapData());
|
||||
for (uint32 childMapId : childMapIds)
|
||||
parentMapData[childMapId] = mapId;
|
||||
}
|
||||
|
||||
thread_safe_environment = false;
|
||||
// mark the loading main thread as safe
|
||||
thread_safe_environment = true;
|
||||
}
|
||||
|
||||
MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const
|
||||
@@ -79,40 +103,47 @@ namespace MMAP
|
||||
return itr;
|
||||
}
|
||||
|
||||
LoadResult MMapManager::loadMapData(std::string_view basePath, uint32 mapId)
|
||||
LoadResult MMapManager::loadMapData(std::string_view basePath, uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
// we already have this map loaded?
|
||||
MMapDataSet::iterator itr = loadedMMaps.find(mapId);
|
||||
if (itr != loadedMMaps.end())
|
||||
MMapDataSet::iterator itr;
|
||||
if (thread_safe_environment)
|
||||
{
|
||||
if (itr->second)
|
||||
return LoadResult::AlreadyLoaded;
|
||||
bool needsLoading;
|
||||
std::tie(itr, needsLoading) = loadedMMaps.try_emplace(mapId);
|
||||
if (needsLoading)
|
||||
itr->second.reset(new MMapData());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thread_safe_environment)
|
||||
itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
|
||||
else
|
||||
itr = loadedMMaps.find(mapId);
|
||||
if (itr == loadedMMaps.end())
|
||||
ABORT_MSG("Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId);
|
||||
}
|
||||
|
||||
auto [meshItr, needsLoading] = itr->second->GetMeshData(mapId, instanceId);
|
||||
if (!needsLoading)
|
||||
return LoadResult::AlreadyLoaded;
|
||||
|
||||
auto loadGuard = Trinity::make_unique_ptr_with_deleter(&meshItr, [&](MeshDataMap::iterator* m)
|
||||
{
|
||||
itr->second->meshData.erase(*m);
|
||||
});
|
||||
|
||||
// load and init dtNavMesh - read parameters from file
|
||||
dtNavMeshParams params;
|
||||
if (LoadResult paramsResult = parseNavMeshParamsFile(basePath, mapId, ¶ms); paramsResult != LoadResult::Success)
|
||||
return paramsResult;
|
||||
|
||||
NavMeshPtr mesh(dtAllocNavMesh());
|
||||
ASSERT(mesh);
|
||||
if (dtStatusFailed(mesh->init(¶ms)))
|
||||
if (dtStatusFailed(meshItr->second.navMesh.init(¶ms)))
|
||||
{
|
||||
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);
|
||||
(void)loadGuard.release();
|
||||
|
||||
// store inside our map list
|
||||
itr->second.reset(new MMapData(std::move(mesh)));
|
||||
return LoadResult::Success;
|
||||
}
|
||||
|
||||
@@ -168,10 +199,10 @@ namespace MMAP
|
||||
return uint32(x << 16 | y);
|
||||
}
|
||||
|
||||
LoadResult MMapManager::loadMap(std::string_view basePath, uint32 mapId, int32 x, int32 y)
|
||||
LoadResult MMapManager::loadMap(std::string_view basePath, uint32 mapId, uint32 instanceId, int32 x, int32 y)
|
||||
{
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
switch (LoadResult mapResult = loadMapData(basePath, mapId))
|
||||
switch (LoadResult mapResult = loadMapData(basePath, mapId, instanceId))
|
||||
{
|
||||
case LoadResult::Success:
|
||||
case LoadResult::AlreadyLoaded:
|
||||
@@ -182,11 +213,11 @@ namespace MMAP
|
||||
|
||||
// get this mmap data
|
||||
MMapData* mmap = loadedMMaps[mapId].get();
|
||||
ASSERT(mmap->navMesh);
|
||||
MMapMapData& meshData = mmap->GetMeshData(mapId, instanceId).first->second;
|
||||
|
||||
// check if we already have this tile loaded
|
||||
uint32 packedGridPos = packTileID(x, y);
|
||||
if (mmap->loadedTileRefs.contains(packedGridPos))
|
||||
if (meshData.loadedTileRefs.contains(packedGridPos))
|
||||
return LoadResult::AlreadyLoaded;
|
||||
|
||||
// load this tile :: mmaps/MMMM_XX_YY.mmtile
|
||||
@@ -253,9 +284,9 @@ namespace MMAP
|
||||
dtTileRef tileRef = 0;
|
||||
|
||||
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
|
||||
if (dtStatusSucceed(mmap->navMesh->addTile(static_cast<unsigned char*>(data.release()), fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
|
||||
if (dtStatusSucceed(meshData.navMesh.addTile(static_cast<unsigned char*>(data.release()), fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
|
||||
{
|
||||
mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
|
||||
meshData.loadedTileRefs[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 LoadResult::Success;
|
||||
@@ -269,7 +300,7 @@ namespace MMAP
|
||||
|
||||
bool MMapManager::loadMapInstance(std::string_view basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
|
||||
{
|
||||
switch (loadMapData(basePath, meshMapId))
|
||||
switch (loadMapData(basePath, meshMapId, instanceId))
|
||||
{
|
||||
case LoadResult::Success:
|
||||
case LoadResult::AlreadyLoaded:
|
||||
@@ -279,14 +310,17 @@ namespace MMAP
|
||||
}
|
||||
|
||||
MMapData* mmap = loadedMMaps[meshMapId].get();
|
||||
auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId }, nullptr);
|
||||
auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId });
|
||||
if (!inserted)
|
||||
return true;
|
||||
|
||||
auto loadGuard = Trinity::make_unique_ptr_with_deleter(&queryItr, [&](NavMeshQuerySet::iterator* m)
|
||||
{
|
||||
mmap->navMeshQueries.erase(*m);
|
||||
});
|
||||
|
||||
// allocate mesh query
|
||||
NavMeshQueryPtr query(dtAllocNavMeshQuery());
|
||||
ASSERT(query);
|
||||
if (dtStatusFailed(query->init(mmap->navMesh.get(), 1024)))
|
||||
if (dtStatusFailed(queryItr->second.init(&mmap->GetMeshData(meshMapId, instanceId).first->second.navMesh, 1024)))
|
||||
{
|
||||
mmap->navMeshQueries.erase(queryItr);
|
||||
TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId);
|
||||
@@ -294,11 +328,11 @@ namespace MMAP
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId);
|
||||
queryItr->second = std::move(query);
|
||||
(void)loadGuard.release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
|
||||
void MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
|
||||
{
|
||||
// check if we have this map loaded
|
||||
MMapDataSet::const_iterator itr = GetMMapData(mapId);
|
||||
@@ -306,72 +340,69 @@ namespace MMAP
|
||||
{
|
||||
// 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);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
MMapData* mmap = itr->second.get();
|
||||
|
||||
// check if we have this tile loaded
|
||||
uint32 packedGridPos = packTileID(x, y);
|
||||
auto tileRef = mmap->loadedTileRefs.extract(packedGridPos);
|
||||
if (!tileRef)
|
||||
for (auto& [instanceId, meshData] : mmap->meshData)
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. {:04}{:02}{:02}.mmtile", mapId, x, y);
|
||||
return false;
|
||||
}
|
||||
// check if we have this tile loaded
|
||||
auto tileRef = meshData.loadedTileRefs.extract(packedGridPos);
|
||||
if (!tileRef)
|
||||
continue;
|
||||
|
||||
// unload, and mark as non loaded
|
||||
if (dtStatusFailed(mmap->navMesh->removeTile(tileRef.mapped(), nullptr, nullptr)))
|
||||
{
|
||||
// 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);
|
||||
ABORT();
|
||||
// unload, and mark as non loaded
|
||||
if (dtStatusFailed(meshData.navMesh.removeTile(tileRef.mapped(), nullptr, nullptr)))
|
||||
{
|
||||
// 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);
|
||||
ABORT();
|
||||
}
|
||||
else
|
||||
{
|
||||
--loadedTiles;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:03}", mapId, x, y, mapId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
--loadedTiles;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:03}", mapId, x, y, mapId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MMapManager::unloadMap(uint32 mapId)
|
||||
void MMapManager::unloadMap(uint32 mapId)
|
||||
{
|
||||
MMapDataSet::iterator itr = loadedMMaps.find(mapId);
|
||||
if (itr == loadedMMaps.end() || !itr->second)
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map {:04}", mapId);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// unload all tiles from given map
|
||||
MMapData* mmap = itr->second.get();
|
||||
for (auto const& [tileId, tileRef] : mmap->loadedTileRefs)
|
||||
if (MMapData::GetInstanceIdForMeshLookup(mapId, std::numeric_limits<uint32>::max()) == 0)
|
||||
{
|
||||
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);
|
||||
else
|
||||
// unload all tiles from given map
|
||||
MMapMapData& mesh = itr->second->meshData[0];
|
||||
for (auto const& [tileId, tileRef] : mesh.loadedTileRefs)
|
||||
{
|
||||
--loadedTiles;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId);
|
||||
uint32 x = (tileId >> 16);
|
||||
uint32 y = (tileId & 0x0000FFFF);
|
||||
if (dtStatusFailed(mesh.navMesh.removeTile(tileRef, nullptr, nullptr)))
|
||||
TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y);
|
||||
else
|
||||
{
|
||||
--loadedTiles;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // require all tiles to be already unloaded
|
||||
ASSERT(std::ranges::all_of(itr->second->meshData, [](MMapMapData const& mesh) { return mesh.loadedTileRefs.empty(); }, Trinity::Containers::MapValue));
|
||||
|
||||
itr->second = nullptr;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded {:04}.mmap", mapId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MMapManager::unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
|
||||
void MMapManager::unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
|
||||
{
|
||||
// check if we have this map loaded
|
||||
MMapDataSet::const_iterator itr = GetMMapData(meshMapId);
|
||||
@@ -379,29 +410,48 @@ namespace MMAP
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map {:04}", meshMapId);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
MMapData* mmap = itr->second.get();
|
||||
std::size_t erased = mmap->navMeshQueries.erase({ instanceMapId, instanceId });
|
||||
if (!erased)
|
||||
{
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:04} instanceId {}", instanceMapId, instanceId);
|
||||
return false;
|
||||
|
||||
MeshDataMap::iterator meshItr = mmap->FindMeshData(meshMapId, instanceId);
|
||||
if (meshItr != mmap->meshData.end())
|
||||
{
|
||||
// unload all tiles from given map
|
||||
for (auto const& [tileId, tileRef] : meshItr->second.loadedTileRefs)
|
||||
{
|
||||
uint32 x = (tileId >> 16);
|
||||
uint32 y = (tileId & 0x0000FFFF);
|
||||
if (dtStatusFailed(meshItr->second.navMesh.removeTile(tileRef, nullptr, nullptr)))
|
||||
TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y);
|
||||
else
|
||||
{
|
||||
--loadedTiles;
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId);
|
||||
}
|
||||
}
|
||||
|
||||
mmap->meshData.erase(meshItr);
|
||||
}
|
||||
|
||||
TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId {:04} instanceId {}", instanceMapId, instanceId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
|
||||
dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId, uint32 instanceId)
|
||||
{
|
||||
MMapDataSet::const_iterator itr = GetMMapData(mapId);
|
||||
if (itr == loadedMMaps.end())
|
||||
return nullptr;
|
||||
|
||||
return itr->second->navMesh.get();
|
||||
MeshDataMap::iterator meshItr = itr->second->FindMeshData(mapId, instanceId);
|
||||
if (meshItr == itr->second->meshData.end())
|
||||
return nullptr;
|
||||
|
||||
return &meshItr->second.navMesh;
|
||||
}
|
||||
|
||||
dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId)
|
||||
@@ -414,6 +464,6 @@ namespace MMAP
|
||||
if (queryItr == itr->second->navMeshQueries.end())
|
||||
return nullptr;
|
||||
|
||||
return queryItr->second.get();
|
||||
return &queryItr->second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,26 +59,25 @@ namespace MMAP
|
||||
|
||||
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);
|
||||
LoadResult loadMap(std::string_view basePath, uint32 mapId, uint32 instanceId, int32 x, int32 y);
|
||||
bool loadMapInstance(std::string_view basePath, uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
|
||||
bool unloadMap(uint32 mapId, int32 x, int32 y);
|
||||
bool unloadMap(uint32 mapId);
|
||||
bool unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
|
||||
void unloadMap(uint32 mapId, int32 x, int32 y);
|
||||
void unloadMap(uint32 mapId);
|
||||
void unloadMapInstance(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
|
||||
|
||||
// the returned [dtNavMeshQuery const*] is NOT threadsafe
|
||||
dtNavMeshQuery const* GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId);
|
||||
dtNavMesh const* GetNavMesh(uint32 mapId);
|
||||
dtNavMesh const* GetNavMesh(uint32 mapId, uint32 instanceId);
|
||||
|
||||
uint32 getLoadedTilesCount() const { return loadedTiles; }
|
||||
uint32 getLoadedMapsCount() const { return uint32(loadedMMaps.size()); }
|
||||
private:
|
||||
LoadResult loadMapData(std::string_view basePath, uint32 mapId);
|
||||
LoadResult loadMapData(std::string_view basePath, uint32 mapId, uint32 instanceId);
|
||||
uint32 packTileID(int32 x, int32 y);
|
||||
|
||||
MMapDataSet::const_iterator GetMMapData(uint32 mapId) const;
|
||||
MMapDataSet loadedMMaps;
|
||||
uint32 loadedTiles = 0;
|
||||
bool thread_safe_environment = true;
|
||||
|
||||
std::unordered_map<uint32, uint32> parentMapData;
|
||||
};
|
||||
|
||||
@@ -290,6 +290,7 @@ void Map::EnsureGridCreated(GridCoord const& p)
|
||||
int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
|
||||
|
||||
m_terrain->LoadMapAndVMap(gx, gy);
|
||||
m_terrain->LoadMMap(GetInstanceId(), gx, gy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "MMapManager.h"
|
||||
#include "PhasingHandler.h"
|
||||
#include "Random.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Util.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "VMapManager.h"
|
||||
@@ -144,7 +143,7 @@ bool TerrainInfo::ExistVMap(uint32 mapid, int32 gx, int32 gy)
|
||||
|
||||
bool TerrainInfo::HasChildTerrainGridFile(uint32 mapId, int32 gx, int32 gy) const
|
||||
{
|
||||
auto childMapItr = std::find_if(_childTerrain.begin(), _childTerrain.end(), [mapId](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId() == mapId; });
|
||||
auto childMapItr = std::ranges::find(_childTerrain, mapId, [](std::shared_ptr<TerrainInfo> const& childTerrain) { return childTerrain->GetId(); });
|
||||
return childMapItr != _childTerrain.end() && (*childMapItr)->_gridFileExists[GetBitsetIndex(gx, gy)];
|
||||
}
|
||||
|
||||
@@ -171,11 +170,18 @@ void TerrainInfo::LoadMMapInstance(uint32 mapId, uint32 instanceId)
|
||||
childTerrain->LoadMMapInstanceImpl(mapId, instanceId);
|
||||
}
|
||||
|
||||
void TerrainInfo::LoadMMap(uint32 instanceId, int32 gx, int32 gy)
|
||||
{
|
||||
LoadMMapImpl(instanceId, gx, gy);
|
||||
|
||||
for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
|
||||
childTerrain->LoadMMapImpl(instanceId, gx, gy);
|
||||
}
|
||||
|
||||
void TerrainInfo::LoadMapAndVMapImpl(int32 gx, int32 gy)
|
||||
{
|
||||
LoadMap(gx, gy);
|
||||
LoadVMap(gx, gy);
|
||||
LoadMMap(gx, gy);
|
||||
|
||||
for (std::shared_ptr<TerrainInfo> const& childTerrain : _childTerrain)
|
||||
childTerrain->LoadMapAndVMapImpl(gx, gy);
|
||||
@@ -233,12 +239,12 @@ void TerrainInfo::LoadVMap(int32 gx, int32 gy)
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainInfo::LoadMMap(int32 gx, int32 gy)
|
||||
void TerrainInfo::LoadMMapImpl(uint32 instanceId, int32 gx, int32 gy)
|
||||
{
|
||||
if (!DisableMgr::IsPathfindingEnabled(GetId()))
|
||||
return;
|
||||
|
||||
switch (MMAP::LoadResult mmapLoadResult = MMAP::MMapManager::instance()->loadMap(sWorld->GetDataPath(), GetId(), gx, gy))
|
||||
switch (MMAP::LoadResult mmapLoadResult = MMAP::MMapManager::instance()->loadMap(sWorld->GetDataPath(), GetId(), instanceId, 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);
|
||||
|
||||
@@ -58,13 +58,14 @@ public:
|
||||
|
||||
void LoadMapAndVMap(int32 gx, int32 gy);
|
||||
void LoadMMapInstance(uint32 mapId, uint32 instanceId);
|
||||
void LoadMMap(uint32 instanceId, int32 gx, int32 gy);
|
||||
|
||||
private:
|
||||
void LoadMapAndVMapImpl(int32 gx, int32 gy);
|
||||
void LoadMMapInstanceImpl(uint32 mapId, uint32 instanceId);
|
||||
void LoadMap(int32 gx, int32 gy);
|
||||
void LoadVMap(int32 gx, int32 gy);
|
||||
void LoadMMap(int32 gx, int32 gy);
|
||||
void LoadMMapImpl(uint32 instanceId, int32 gx, int32 gy);
|
||||
|
||||
public:
|
||||
void UnloadMap(int32 gx, int32 gy);
|
||||
|
||||
@@ -43,7 +43,7 @@ PathGenerator::PathGenerator(WorldObject const* owner) :
|
||||
{
|
||||
MMAP::MMapManager* mmap = MMAP::MMapManager::instance();
|
||||
_navMeshQuery = mmap->GetNavMeshQuery(mapId, _source->GetMapId(), _source->GetInstanceId());
|
||||
_navMesh = _navMeshQuery ? _navMeshQuery->getAttachedNavMesh() : mmap->GetNavMesh(mapId);
|
||||
_navMesh = _navMeshQuery ? _navMeshQuery->getAttachedNavMesh() : mmap->GetNavMesh(mapId, _source->GetInstanceId());
|
||||
}
|
||||
|
||||
CreateFilter();
|
||||
|
||||
@@ -258,7 +258,7 @@ public:
|
||||
|
||||
uint32 haveMap = TerrainInfo::ExistMap(mapId, gridX, gridY) ? 1 : 0;
|
||||
uint32 haveVMap = TerrainInfo::ExistVMap(mapId, gridX, gridY) ? 1 : 0;
|
||||
uint32 haveMMap = (DisableMgr::IsPathfindingEnabled(mapId) && MMAP::MMapManager::instance()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) ? 1 : 0;
|
||||
uint32 haveMMap = (DisableMgr::IsPathfindingEnabled(mapId) && MMAP::MMapManager::instance()->GetNavMesh(object->GetMapId(), object->GetInstanceId())) ? 1 : 0;
|
||||
|
||||
if (haveVMap)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,8 @@ public:
|
||||
|
||||
static bool HandleMmapPathCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
if (!MMAP::MMapManager::instance()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()))
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
if (!MMAP::MMapManager::instance()->GetNavMesh(player->GetMapId(), player->GetInstanceId()))
|
||||
{
|
||||
handler->PSendSysMessage("NavMesh not loaded for current map.");
|
||||
return true;
|
||||
@@ -75,7 +76,6 @@ public:
|
||||
handler->PSendSysMessage("mmap path:");
|
||||
|
||||
// units
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
Unit* target = handler->getSelectedUnit();
|
||||
if (!player || !target)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
handler->PSendSysMessage("%04u_%02i_%02i.mmtile", terrainMapId, gx, gy);
|
||||
handler->PSendSysMessage("tileloc [%i, %i]", gy, gx);
|
||||
|
||||
dtNavMesh const* navmesh = MMAP::MMapManager::instance()->GetNavMesh(terrainMapId);
|
||||
dtNavMesh const* navmesh = MMAP::MMapManager::instance()->GetNavMesh(terrainMapId, player->GetInstanceId());
|
||||
dtNavMeshQuery const* navmeshquery = MMAP::MMapManager::instance()->GetNavMeshQuery(terrainMapId, player->GetMapId(), player->GetInstanceId());
|
||||
if (!navmesh || !navmeshquery)
|
||||
{
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
{
|
||||
Player* player = handler->GetSession()->GetPlayer();
|
||||
uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMapId(), player->GetMap()->GetTerrain(), player->GetPositionX(), player->GetPositionY());
|
||||
dtNavMesh const* navmesh = MMAP::MMapManager::instance()->GetNavMesh(terrainMapId);
|
||||
dtNavMesh const* navmesh = MMAP::MMapManager::instance()->GetNavMesh(terrainMapId, player->GetInstanceId());
|
||||
dtNavMeshQuery const* navmeshquery = MMAP::MMapManager::instance()->GetNavMeshQuery(terrainMapId, player->GetMapId(), player->GetInstanceId());
|
||||
if (!navmesh || !navmeshquery)
|
||||
{
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
MMAP::MMapManager* manager = MMAP::MMapManager::instance();
|
||||
handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
|
||||
|
||||
dtNavMesh const* navmesh = manager->GetNavMesh(terrainMapId);
|
||||
dtNavMesh const* navmesh = manager->GetNavMesh(terrainMapId, player->GetInstanceId());
|
||||
if (!navmesh)
|
||||
{
|
||||
handler->PSendSysMessage("NavMesh not loaded for current map.");
|
||||
|
||||
Reference in New Issue
Block a user