AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
MMAP::MMapMgr Class Reference

#include "MMapMgr.h"

Public Member Functions

 MMapMgr ()=default
 
 ~MMapMgr ()
 
void InitializeThreadUnsafe (const std::vector< uint32 > &mapIds)
 
bool loadMap (uint32 mapId, int32 x, int32 y)
 
bool unloadMap (uint32 mapId, int32 x, int32 y)
 
bool unloadMap (uint32 mapId)
 
bool unloadMapInstance (uint32 mapId, uint32 instanceId)
 
dtNavMeshQuery const * GetNavMeshQuery (uint32 mapId, uint32 instanceId)
 
dtNavMesh const * GetNavMesh (uint32 mapId)
 
uint32 getLoadedTilesCount () const
 
uint32 getLoadedMapsCount () const
 

Private Member Functions

bool loadMapData (uint32 mapId)
 
uint32 packTileID (int32 x, int32 y)
 
MMapDataSet::const_iterator GetMMapData (uint32 mapId) const
 

Private Attributes

MMapDataSet loadedMMaps
 
uint32 loadedTiles {0}
 
bool thread_safe_environment {true}
 

Detailed Description

Constructor & Destructor Documentation

◆ MMapMgr()

MMAP::MMapMgr::MMapMgr ( )
default

◆ ~MMapMgr()

MMAP::MMapMgr::~MMapMgr ( )
31 {
32 for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
33 {
34 delete i->second;
35 }
36
37 // by now we should not have maps loaded
38 // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
39 }
MMapDataSet loadedMMaps
Definition: MMapMgr.h:98

References loadedMMaps.

Member Function Documentation

◆ getLoadedMapsCount()

uint32 MMAP::MMapMgr::getLoadedMapsCount ( ) const
inline
91{ return loadedMMaps.size(); }

References loadedMMaps.

Referenced by mmaps_commandscript::HandleMmapStatsCommand().

◆ getLoadedTilesCount()

uint32 MMAP::MMapMgr::getLoadedTilesCount ( ) const
inline
90{ return loadedTiles; }
uint32 loadedTiles
Definition: MMapMgr.h:99

References loadedTiles.

Referenced by mmaps_commandscript::HandleMmapStatsCommand().

◆ GetMMapData()

MMapDataSet::const_iterator MMAP::MMapMgr::GetMMapData ( uint32  mapId) const
private
53 {
54 // return the iterator if found or end() if not found/NULL
55 MMapDataSet::const_iterator itr = loadedMMaps.find(mapId);
56 if (itr != loadedMMaps.cend() && !itr->second)
57 {
58 itr = loadedMMaps.cend();
59 }
60
61 return itr;
62 }

References loadedMMaps.

Referenced by GetNavMesh(), GetNavMeshQuery(), unloadMap(), and unloadMapInstance().

◆ GetNavMesh()

dtNavMesh const * MMAP::MMapMgr::GetNavMesh ( uint32  mapId)
307 {
308 MMapDataSet::const_iterator itr = GetMMapData(mapId);
309 if (itr == loadedMMaps.end())
310 {
311 return nullptr;
312 }
313
314 return itr->second->navMesh;
315 }
MMapDataSet::const_iterator GetMMapData(uint32 mapId) const
Definition: MMapMgr.cpp:52

References GetMMapData(), and loadedMMaps.

Referenced by misc_commandscript::HandleGPSCommand(), mmaps_commandscript::HandleMmapLoadedTilesCommand(), mmaps_commandscript::HandleMmapLocCommand(), mmaps_commandscript::HandleMmapStatsCommand(), and PathGenerator::PathGenerator().

◆ GetNavMeshQuery()

dtNavMeshQuery const * MMAP::MMapMgr::GetNavMeshQuery ( uint32  mapId,
uint32  instanceId 
)
318 {
319 MMapDataSet::const_iterator itr = GetMMapData(mapId);
320 if (itr == loadedMMaps.end())
321 {
322 return nullptr;
323 }
324
325 MMapData* mmap = itr->second;
326 if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
327 {
328 // check again after acquiring mutex
329 if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
330 {
331 // allocate mesh query
332 dtNavMeshQuery* query = dtAllocNavMeshQuery();
333 ASSERT(query);
334
335 if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
336 {
337 dtFreeNavMeshQuery(query);
338 LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:03} instanceId {}", mapId, instanceId);
339 return nullptr;
340 }
341
342 LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {:03} instanceId {}", mapId, instanceId);
343 mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
344 }
345 }
346
347 return mmap->navMeshQueries[instanceId];
348 }
#define ASSERT
Definition: Errors.h:68
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:169

References ASSERT, GetMMapData(), loadedMMaps, LOG_DEBUG, LOG_ERROR, MMAP::MMapData::navMesh, and MMAP::MMapData::navMeshQueries.

Referenced by mmaps_commandscript::HandleMmapLoadedTilesCommand(), mmaps_commandscript::HandleMmapLocCommand(), and PathGenerator::PathGenerator().

◆ InitializeThreadUnsafe()

void MMAP::MMapMgr::InitializeThreadUnsafe ( const std::vector< uint32 > &  mapIds)
42 {
43 // the caller must pass the list of all mapIds that will be used in the VMapMgr2 lifetime
44 for (const uint32& mapId : mapIds)
45 {
46 loadedMMaps.emplace(mapId, nullptr);
47 }
48
50 }
std::uint32_t uint32
Definition: Define.h:108
bool thread_safe_environment
Definition: MMapMgr.h:100

References loadedMMaps, and thread_safe_environment.

Referenced by World::SetInitialWorldSettings().

◆ loadMap()

bool MMAP::MMapMgr::loadMap ( uint32  mapId,
int32  x,
int32  y 
)
129 {
130 // make sure the mmap is loaded and ready to load tiles
131 if (!loadMapData(mapId))
132 {
133 return false;
134 }
135
136 // get this mmap data
137 MMapData* mmap = loadedMMaps[mapId];
138 ASSERT(mmap->navMesh);
139
140 // check if we already have this tile loaded
141 uint32 packedGridPos = packTileID(x, y);
142 if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
143 {
144 LOG_ERROR("maps", "MMAP:loadMap: Asked to load already loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
145 return false;
146 }
147
148 // load this tile :: mmaps/MMMXXYY.mmtile
149 std::string fileName = Acore::StringFormat(TILE_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", ".").c_str(), mapId, x, y);
150 FILE* file = fopen(fileName.c_str(), "rb");
151 if (!file)
152 {
153 LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '{}'", fileName);
154 return false;
155 }
156
157 // read header
158 MmapTileHeader fileHeader;
159 if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC)
160 {
161 LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap {:03}{:02}{:02}.mmtile", mapId, x, y);
162 fclose(file);
163 return false;
164 }
165
166 if (fileHeader.mmapVersion != MMAP_VERSION)
167 {
168 LOG_ERROR("maps", "MMAP:loadMap: {:03}{:02}{:02}.mmtile was built with generator v{}, expected v{}",
169 mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
170 fclose(file);
171 return false;
172 }
173
174 unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
175 ASSERT(data);
176
177 size_t result = fread(data, fileHeader.size, 1, file);
178 if (!result)
179 {
180 LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap {:03}{:02}{:02}.mmtile", mapId, x, y);
181 fclose(file);
182 return false;
183 }
184
185 fclose(file);
186
187 dtTileRef tileRef = 0;
188
189 // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
190 if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
191 {
192 mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
193 ++loadedTiles;
194 dtMeshHeader* header = (dtMeshHeader*)data;
195 LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile {:03}[{:02},{:02}] into {:03}[{:02},{:02}]", mapId, x, y, mapId, header->x, header->y);
196 return true;
197 }
198
199 LOG_ERROR("maps", "MMAP:loadMap: Could not load {:03}{:02}{:02}.mmtile into navmesh", mapId, x, y);
200 dtFree(data);
201 return false;
202 }
#define MMAP_VERSION
Definition: MapDefines.h:28
#define MMAP_MAGIC
Definition: MapDefines.h:27
#define sConfigMgr
Definition: Config.h:95
std::string StringFormat(Format &&fmt, Args &&... args)
Default AC string format function.
Definition: StringFormat.h:30
static char const *const TILE_FILE_NAME_FORMAT
Definition: MMapMgr.cpp:27
bool loadMapData(uint32 mapId)
Definition: MMapMgr.cpp:64
uint32 packTileID(int32 x, int32 y)
Definition: MMapMgr.cpp:123
Definition: MapDefines.h:31
uint32 mmapVersion
Definition: MapDefines.h:34
uint32 size
Definition: MapDefines.h:35
uint32 mmapMagic
Definition: MapDefines.h:32

References ASSERT, loadedMMaps, MMAP::MMapData::loadedTileRefs, loadedTiles, loadMapData(), LOG_DEBUG, LOG_ERROR, MMAP_MAGIC, MMAP_VERSION, MmapTileHeader::mmapMagic, MmapTileHeader::mmapVersion, MMAP::MMapData::navMesh, packTileID(), sConfigMgr, MmapTileHeader::size, Acore::StringFormat(), and MMAP::TILE_FILE_NAME_FORMAT.

Referenced by Map::LoadMMap().

◆ loadMapData()

bool MMAP::MMapMgr::loadMapData ( uint32  mapId)
private
65 {
66 // we already have this map loaded?
67 MMapDataSet::iterator itr = loadedMMaps.find(mapId);
68 if (itr != loadedMMaps.end())
69 {
70 if (itr->second)
71 {
72 return true;
73 }
74 }
75 else
76 {
78 {
79 itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first;
80 }
81 else
82 {
83 ABORT("Invalid mapId {} passed to MMapMgr after startup in thread unsafe environment", mapId);
84 }
85 }
86
87 // load and init dtNavMesh - read parameters from file
88 std::string fileName = Acore::StringFormat(MAP_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", ".").c_str(), mapId);
89
90 FILE* file = fopen(fileName.c_str(), "rb");
91 if (!file)
92 {
93 LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '{}'", fileName);
94 return false;
95 }
96
97 dtNavMeshParams params;
98 uint32 count = uint32(fread(&params, sizeof(dtNavMeshParams), 1, file));
99 fclose(file);
100 if (count != 1)
101 {
102 LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '{}'", fileName);
103 return false;
104 }
105
106 dtNavMesh* mesh = dtAllocNavMesh();
107 ASSERT(mesh);
108 if (DT_SUCCESS != mesh->init(&params))
109 {
110 dtFreeNavMesh(mesh);
111 LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap {:03} from file {}", mapId, fileName);
112 return false;
113 }
114
115 LOG_DEBUG("maps", "MMAP:loadMapData: Loaded {:03}.mmap", mapId);
116
117 // store inside our map list
118 MMapData* mmap_data = new MMapData(mesh);
119 itr->second = mmap_data;
120 return true;
121 }
#define ABORT
Definition: Errors.h:76
static char const *const MAP_FILE_NAME_FORMAT
Definition: MMapMgr.cpp:26

References ABORT, ASSERT, loadedMMaps, LOG_DEBUG, LOG_ERROR, MMAP::MAP_FILE_NAME_FORMAT, sConfigMgr, Acore::StringFormat(), and thread_safe_environment.

Referenced by loadMap().

◆ packTileID()

uint32 MMAP::MMapMgr::packTileID ( int32  x,
int32  y 
)
private
124 {
125 return uint32(x << 16 | y);
126 }

Referenced by loadMap(), and unloadMap().

◆ unloadMap() [1/2]

bool MMAP::MMapMgr::unloadMap ( uint32  mapId)
245 {
246 MMapDataSet::iterator itr = loadedMMaps.find(mapId);
247 if (itr == loadedMMaps.end() || !itr->second)
248 {
249 // file may not exist, therefore not loaded
250 LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map {:03}", mapId);
251 return false;
252 }
253
254 // unload all tiles from given map
255 MMapData* mmap = itr->second;
256 for (auto& i : mmap->loadedTileRefs)
257 {
258 uint32 x = (i.first >> 16);
259 uint32 y = (i.first & 0x0000FFFF);
260
261 if (dtStatusFailed(mmap->navMesh->removeTile(i.second, nullptr, nullptr)))
262 {
263 LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:03}{:02}{:02}.mmtile from navmesh", mapId, x, y);
264 }
265 else
266 {
267 --loadedTiles;
268 LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:03}[{:02},{:02}] from {:03}", mapId, x, y, mapId);
269 }
270 }
271
272 delete mmap;
273 itr->second = nullptr;
274 LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded {:03}.mmap", mapId);
275
276 return true;
277 }

References loadedMMaps, MMAP::MMapData::loadedTileRefs, loadedTiles, LOG_DEBUG, LOG_ERROR, and MMAP::MMapData::navMesh.

◆ unloadMap() [2/2]

bool MMAP::MMapMgr::unloadMap ( uint32  mapId,
int32  x,
int32  y 
)
205 {
206 // check if we have this map loaded
207 MMapDataSet::const_iterator itr = GetMMapData(mapId);
208 if (itr == loadedMMaps.end())
209 {
210 // file may not exist, therefore not loaded
211 LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. {:03}{:02}{:02}.mmtile", mapId, x, y);
212 return false;
213 }
214
215 MMapData* mmap = itr->second;
216
217 // check if we have this tile loaded
218 uint32 packedGridPos = packTileID(x, y);
219 if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end())
220 {
221 // file may not exist, therefore not loaded
222 LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. {:03}{:02}{:02}.mmtile", mapId, x, y);
223 return false;
224 }
225
226 dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos];
227
228 // unload, and mark as non loaded
229 if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr)))
230 {
231 // this is technically a memory leak
232 // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
233 // we cannot recover from this error - assert out
234 LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:03}{:02}{:02}.mmtile from navmesh", mapId, x, y);
235 ABORT();
236 }
237
238 mmap->loadedTileRefs.erase(packedGridPos);
239 --loadedTiles;
240 LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:03}[{:02},{:02}] from {:03}", mapId, x, y, mapId);
241 return true;
242 }

References ABORT, GetMMapData(), loadedMMaps, MMAP::MMapData::loadedTileRefs, loadedTiles, LOG_DEBUG, LOG_ERROR, MMAP::MMapData::navMesh, and packTileID().

Referenced by Map::UnloadGrid().

◆ unloadMapInstance()

bool MMAP::MMapMgr::unloadMapInstance ( uint32  mapId,
uint32  instanceId 
)
280 {
281 // check if we have this map loaded
282 MMapDataSet::const_iterator itr = GetMMapData(mapId);
283 if (itr == loadedMMaps.end())
284 {
285 // file may not exist, therefore not loaded
286 LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map {:03}", mapId);
287 return false;
288 }
289
290 MMapData* mmap = itr->second;
291 if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
292 {
293 LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:03} instanceId {}", mapId, instanceId);
294 return false;
295 }
296
297 dtNavMeshQuery* query = mmap->navMeshQueries[instanceId];
298
299 dtFreeNavMeshQuery(query);
300 mmap->navMeshQueries.erase(instanceId);
301 LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId {:03} instanceId {}", mapId, instanceId);
302
303 return true;
304 }

References GetMMapData(), loadedMMaps, LOG_DEBUG, and MMAP::MMapData::navMeshQueries.

Referenced by Map::~Map().

Member Data Documentation

◆ loadedMMaps

◆ loadedTiles

uint32 MMAP::MMapMgr::loadedTiles {0}
private

◆ thread_safe_environment

bool MMAP::MMapMgr::thread_safe_environment {true}
private