Skip to content

Instantly share code, notes, and snippets.

@sixsixnine
Created February 13, 2012 17:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sixsixnine/1818550 to your computer and use it in GitHub Desktop.
Save sixsixnine/1818550 to your computer and use it in GitHub Desktop.
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index 3ec845f..5863de4 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -5344,10 +5344,7 @@ bool ChatHandler::HandleMmapPathCommand(char* args)
static const uint32 WAYPOINT_NPC_ENTRY = 1;
Creature* wp = NULL;
for (uint32 i = 0; i < pointPath.size(); ++i)
- {
wp = player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000);
- // TODO: make creature not sink/fall
- }
return true;
}
@@ -5366,15 +5363,15 @@ bool ChatHandler::HandleMmapLocCommand(char* /*args*/)
PSendSysMessage("gridloc [%i,%i]", gx, gy);
// calculate navmesh tile location
- const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(player->GetMapId());
- const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), player->GetInstanceId());
+ NavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(player->GetMapId());
+ NavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(player->GetMapId(), player->GetInstanceId());
if (!navmesh || !navmeshquery)
{
PSendSysMessage("NavMesh not loaded for current map.");
return true;
}
- const float* min = navmesh->getParams()->orig;
+ const float* min = navmesh->getMesh()->getParams()->orig;
float x, y, z;
player->GetPosition(x, y, z);
@@ -5411,8 +5408,8 @@ bool ChatHandler::HandleMmapLoadedTilesCommand(char* /*args*/)
{
uint32 mapid = m_session->GetPlayer()->GetMapId();
- const dtNavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid);
- const dtNavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, m_session->GetPlayer()->GetInstanceId());
+ NavMesh* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid);
+ NavMeshQuery* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, m_session->GetPlayer()->GetInstanceId());
if (!navmesh || !navmeshquery)
{
PSendSysMessage("NavMesh not loaded for current map.");
@@ -5420,7 +5417,6 @@ bool ChatHandler::HandleMmapLoadedTilesCommand(char* /*args*/)
}
PSendSysMessage("mmap loadedtiles:");
-
for (int32 i = 0; i < navmesh->getMaxTiles(); ++i)
{
const dtMeshTile* tile = navmesh->getTile(i);
@@ -5441,7 +5437,7 @@ bool ChatHandler::HandleMmapStatsCommand(char* /*args*/)
MMAP::MMapManager *manager = MMAP::MMapFactory::createOrGetMMapManager();
PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
- const dtNavMesh* navmesh = manager->GetNavMesh(m_session->GetPlayer()->GetMapId());
+ NavMesh* navmesh = manager->GetNavMesh(m_session->GetPlayer()->GetMapId());
if (!navmesh)
{
PSendSysMessage("NavMesh not loaded for current map.");
@@ -5455,6 +5451,7 @@ bool ChatHandler::HandleMmapStatsCommand(char* /*args*/)
uint32 triCount = 0;
uint32 triVertCount = 0;
uint32 dataSize = 0;
+
for (int32 i = 0; i < navmesh->getMaxTiles(); ++i)
{
const dtMeshTile* tile = navmesh->getTile(i);
diff --git a/src/game/MoveMap.cpp b/src/game/MoveMap.cpp
index 0ee3e92..e2698d4 100644
--- a/src/game/MoveMap.cpp
+++ b/src/game/MoveMap.cpp
@@ -21,7 +21,6 @@
#include "World.h"
#include "MoveMap.h"
-#include "MoveMapSharedDefines.h"
namespace MMAP
{
@@ -45,7 +44,7 @@ namespace MMAP
if(!g_mmapDisabledIds)
g_mmapDisabledIds = new std::set<uint32>();
- uint32 strLenght = strlen(ignoreMapIds)+1;
+ uint32 strLenght = strlen(ignoreMapIds) + 1;
char* mapList = new char[strLenght];
memcpy(mapList, ignoreMapIds, sizeof(char)*strLenght);
@@ -85,9 +84,6 @@ namespace MMAP
{
for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
delete i->second;
-
- // by now we should not have maps loaded
- // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost!
}
bool MMapManager::loadMapData(uint32 mapId)
@@ -96,131 +92,25 @@ namespace MMAP
if (loadedMMaps.find(mapId) != loadedMMaps.end())
return true;
- // load and init dtNavMesh - read parameters from file
- uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i.mmap")+1;
- char *fileName = new char[pathLen];
- snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId);
-
- FILE* file = fopen(fileName, "rb");
- if (!file)
- {
- sLog.outDebug("MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName);
- delete [] fileName;
- return false;
- }
-
- dtNavMeshParams params;
- fread(&params, sizeof(dtNavMeshParams), 1, file);
- fclose(file);
-
- dtNavMesh* mesh = dtAllocNavMesh();
- MANGOS_ASSERT(mesh);
- if (DT_SUCCESS != mesh->init(&params))
+ // create mmap data
+ MMapData* mmap_data = new MMapData(mapId);
+ if(!mmap_data->init())
{
- dtFreeNavMesh(mesh);
- sLog.outError("MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
- delete [] fileName;
+ delete mmap_data;
return false;
}
- delete [] fileName;
-
- sLog.outDetail("MMAP:loadMapData: Loaded %03i.mmap", mapId);
-
- // store inside our map list
- MMapData* mmap_data = new MMapData(mesh);
- mmap_data->mmapLoadedTiles.clear();
-
loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data));
return true;
}
- uint32 MMapManager::packTileID(int32 x, int32 y)
- {
- return uint32(x << 16 | y);
- }
-
bool MMapManager::loadMap(uint32 mapId, int32 x, int32 y)
{
// make sure the mmap is loaded and ready to load tiles
if(!loadMapData(mapId))
return false;
- // get this mmap data
- MMapData* mmap = loadedMMaps[mapId];
- MANGOS_ASSERT(mmap->navMesh);
-
- // check if we already have this tile loaded
- uint32 packedGridPos = packTileID(x, y);
- if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end())
- {
- sLog.outError("MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
- return false;
- }
-
- // load this tile :: mmaps/MMMXXYY.mmtile
- uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
- char *fileName = new char[pathLen];
- snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
-
- FILE *file = fopen(fileName, "rb");
- if (!file)
- {
- sLog.outDebug("MMAP:loadMap: Could not open mmtile file '%s'", fileName);
- delete [] fileName;
- return false;
- }
- delete [] fileName;
-
- // read header
- MmapTileHeader fileHeader;
- fread(&fileHeader, sizeof(MmapTileHeader), 1, file);
-
- if (fileHeader.mmapMagic != MMAP_MAGIC)
- {
- sLog.outError("MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
- return false;
- }
-
- if (fileHeader.mmapVersion != MMAP_VERSION)
- {
- sLog.outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
- mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
- return false;
- }
-
- unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
- MANGOS_ASSERT(data);
-
- size_t result = fread(data, fileHeader.size, 1, file);
- if(!result)
- {
- sLog.outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
- fclose(file);
- return false;
- }
-
- fclose(file);
-
- dtMeshHeader* header = (dtMeshHeader*)data;
- dtTileRef tileRef = 0;
-
- // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
- if(DT_SUCCESS == mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef))
- {
- mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
- ++loadedTiles;
- sLog.outDetail("MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
- return true;
- }
- else
- {
- sLog.outError("MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
- dtFree(data);
- return false;
- }
-
- return false;
+ return loadedMMaps[mapId]->loadTile(x, y);
}
bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y)
@@ -233,37 +123,7 @@ namespace MMAP
return false;
}
- MMapData* mmap = loadedMMaps[mapId];
-
- // check if we have this tile loaded
- uint32 packedGridPos = packTileID(x, y);
- if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end())
- {
- // file may not exist, therefore not loaded
- sLog.outDebug("MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
- return false;
- }
-
- dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos];
-
- // unload, and mark as non loaded
- if(DT_SUCCESS != mmap->navMesh->removeTile(tileRef, NULL, NULL))
- {
- // 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
- sLog.outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
- MANGOS_ASSERT(false);
- }
- else
- {
- mmap->mmapLoadedTiles.erase(packedGridPos);
- --loadedTiles;
- sLog.outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
- return true;
- }
-
- return false;
+ return loadedMMaps[mapId]->unloadTile(x, y);
}
bool MMapManager::unloadMap(uint32 mapId)
@@ -275,22 +135,7 @@ namespace MMAP
return false;
}
- // unload all tiles from given map
- MMapData* mmap = loadedMMaps[mapId];
- for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i)
- {
- uint32 x = (i->first >> 16);
- uint32 y = (i->first & 0x0000FFFF);
- if(DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL))
- sLog.outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
- else
- {
- --loadedTiles;
- sLog.outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
- }
- }
-
- delete mmap;
+ delete loadedMMaps[mapId];
loadedMMaps.erase(mapId);
sLog.outDetail("MMAP:unloadMap: Unloaded %03i.mmap", mapId);
@@ -307,52 +152,31 @@ namespace MMAP
return false;
}
- MMapData* mmap = loadedMMaps[mapId];
- if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
- {
- sLog.outDebug("MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
- return false;
- }
-
- dtNavMeshQuery* query = mmap->navMeshQueries[instanceId];
-
- dtFreeNavMeshQuery(query);
- mmap->navMeshQueries.erase(instanceId);
- sLog.outDetail("MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
-
- return true;
+ return loadedMMaps[mapId]->unloadInstance(instanceId);
}
- dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId)
+ NavMesh* MMapManager::GetNavMesh(uint32 mapId)
{
if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
- return loadedMMaps[mapId]->navMesh;
+ return loadedMMaps[mapId]->getMapNavMesh();
}
-
- dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
+
+ NavMeshQuery* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId)
{
if (loadedMMaps.find(mapId) == loadedMMaps.end())
return NULL;
- MMapData* mmap = loadedMMaps[mapId];
- if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
- {
- // allocate mesh query
- dtNavMeshQuery* query = dtAllocNavMeshQuery();
- MANGOS_ASSERT(query);
- if(DT_SUCCESS != query->init(mmap->navMesh, 1024))
- {
- dtFreeNavMeshQuery(query);
- sLog.outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
- return NULL;
- }
+ return loadedMMaps[mapId]->getInstanceNavMeshQuery(instanceId);
+ }
- sLog.outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
- mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
- }
+ uint32 MMapManager::getLoadedTilesCount() const
+ {
+ uint32 loadedTiles = 0;
+ for (MMapDataSet::const_iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i)
+ loadedTiles += i->second->getLoadedTilesCount();
- return mmap->navMeshQueries[instanceId];
+ return loadedTiles;
}
}
diff --git a/src/game/MoveMap.h b/src/game/MoveMap.h
index 5c4bcc7..02930ec 100644
--- a/src/game/MoveMap.h
+++ b/src/game/MoveMap.h
@@ -21,10 +21,11 @@
#include "Utilities/UnorderedMapSet.h"
+#include "MoveMapData.h"
+
#include "../../dep/recastnavigation/Detour/Include/DetourAlloc.h"
-#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
-#include "../../dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h"
+/******************************************************************/
// memory management
inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/)
{
@@ -36,41 +37,18 @@ inline void dtCustomFree(void* ptr)
delete [] (unsigned char*)ptr;
}
-// move map related classes
+/******************************************************************/
namespace MMAP
{
- typedef UNORDERED_MAP<uint32, dtTileRef> MMapTileSet;
- typedef UNORDERED_MAP<uint32, dtNavMeshQuery*> NavMeshQuerySet;
-
- // dummy struct to hold map's mmap data
- struct MMapData
- {
- MMapData(dtNavMesh* mesh) : navMesh(mesh) {}
- ~MMapData()
- {
- for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
- dtFreeNavMeshQuery(i->second);
-
- if (navMesh)
- dtFreeNavMesh(navMesh);
- }
-
- dtNavMesh* navMesh;
-
- // we have to use single dtNavMeshQuery for every instance, since those are not thread safe
- NavMeshQuerySet navMeshQueries; // instanceId to query
- MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile]
- };
-
-
typedef UNORDERED_MAP<uint32, MMapData*> MMapDataSet;
+ /******************************************************************/
// singelton class
// holds all all access to mmap loading unloading and meshes
class MMapManager
{
public:
- MMapManager() : loadedTiles(0) {}
+ MMapManager() {}
~MMapManager();
bool loadMap(uint32 mapId, int32 x, int32 y);
@@ -78,18 +56,15 @@ namespace MMAP
bool unloadMap(uint32 mapId);
bool unloadMapInstance(uint32 mapId, uint32 instanceId);
- // the returned [dtNavMeshQuery const*] is NOT threadsafe
- dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
- dtNavMesh const* GetNavMesh(uint32 mapId);
+ NavMeshQuery* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
+ NavMesh* GetNavMesh(uint32 mapId);
- uint32 getLoadedTilesCount() const { return loadedTiles; }
+ uint32 getLoadedTilesCount() const;
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
private:
bool loadMapData(uint32 mapId);
- uint32 packTileID(int32 x, int32 y);
MMapDataSet loadedMMaps;
- uint32 loadedTiles;
};
// static class
diff --git a/src/game/MoveMapData.cpp b/src/game/MoveMapData.cpp
new file mode 100644
index 0000000..b6a70dd
--- /dev/null
+++ b/src/game/MoveMapData.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "World.h"
+#include "Log.h"
+#include "MoveMapData.h"
+#include "MoveMapSharedDefines.h"
+
+namespace MMAP
+{
+ /******************************************************************/
+ MMapData::~MMapData()
+ {
+ for (MMapTileSet::iterator i = mmapLoadedTiles.begin(); i != mmapLoadedTiles.end(); ++i)
+ {
+ uint32 x = (i->first >> 16);
+ uint32 y = (i->first & 0x0000FFFF);
+
+ if(DT_SUCCESS != navMesh->removeTile(i->second))
+ sLog.outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
+ else
+ sLog.outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
+ }
+
+ for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i)
+ delete i->second;
+
+ delete navMesh;
+ }
+
+ /******************************************************************/
+ bool MMapData::init()
+ {
+ navMesh = new NavMesh(mapId);
+ if(!navMesh->init())
+ {
+ sLog.outError("MMAP:loadMapData: Failed to initialize NavMesh for mmap %03u", mapId);
+ delete navMesh;
+ return false;
+ }
+ else
+ sLog.outDetail("MMAP:loadMapData: Loaded %03i.mmap", mapId);
+
+ return true;
+ }
+
+ /******************************************************************/
+ bool MMapData::loadTile(uint32 x, uint32 y)
+ {
+ // check if we already have this tile loaded
+ uint32 packedGridPos = packTileID(x, y);
+ if (mmapLoadedTiles.find(packedGridPos) != mmapLoadedTiles.end())
+ {
+ sLog.outError("MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
+ return false;
+ }
+
+ // load this tile :: mmaps/MMMXXYY.mmtile
+ uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
+ char *fileName = new char[pathLen];
+ snprintf(fileName, pathLen, (sWorld.GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
+
+ FILE *file = fopen(fileName, "rb");
+ if (!file)
+ {
+ sLog.outDebug("MMAP:loadMap: Could not open mmtile file '%s'", fileName);
+ delete [] fileName;
+ return false;
+ }
+ delete [] fileName;
+
+ // read header
+ MmapTileHeader fileHeader;
+ fread(&fileHeader, sizeof(MmapTileHeader), 1, file);
+
+ if (fileHeader.mmapMagic != MMAP_MAGIC)
+ {
+ sLog.outError("MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ return false;
+ }
+
+ if (fileHeader.mmapVersion != MMAP_VERSION)
+ {
+ sLog.outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
+ mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
+ return false;
+ }
+
+ unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM);
+ MANGOS_ASSERT(data);
+
+ size_t result = fread(data, fileHeader.size, 1, file);
+ if(!result)
+ {
+ sLog.outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ fclose(file);
+ return false;
+ }
+
+ fclose(file);
+
+ dtMeshHeader* header = (dtMeshHeader*)data;
+ dtTileRef tileRef = 0;
+
+ // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
+ if(DT_SUCCESS == navMesh->addTile(data, fileHeader.size, &tileRef))
+ {
+ mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
+ sLog.outDetail("MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
+ return true;
+ }
+ else
+ {
+ sLog.outError("MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
+ dtFree(data);
+ return false;
+ }
+ }
+
+ /******************************************************************/
+ bool MMapData::unloadTile(uint32 x, uint32 y)
+ {
+ // check if we have this tile loaded
+ uint32 packedGridPos = packTileID(x, y);
+ if (mmapLoadedTiles.find(packedGridPos) == mmapLoadedTiles.end())
+ {
+ // file may not exist, therefore not loaded
+ sLog.outDebug("MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
+ return false;
+ }
+
+ dtTileRef tileRef = mmapLoadedTiles[packedGridPos];
+
+ // unload, and mark as non loaded
+ if(DT_SUCCESS != navMesh->removeTile(tileRef))
+ {
+ // 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
+ sLog.outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
+ MANGOS_ASSERT(false);
+ }
+ else
+ {
+ mmapLoadedTiles.erase(packedGridPos);
+ sLog.outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
+ }
+
+ return true;
+ }
+
+ /******************************************************************/
+ NavMeshQuery* MMapData::getInstanceNavMeshQuery(uint32 instanceId)
+ {
+ if (navMeshQueries.find(instanceId) == navMeshQueries.end())
+ {
+ // allocate mesh query
+ NavMeshQuery* query = new NavMeshQuery(navMesh);
+ if(!query->init())
+ {
+ sLog.outError("MMAP:GetNavMeshQuery: Failed to initialize NavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ return NULL;
+ }
+
+ sLog.outDetail("MMAP:GetNavMeshQuery: created NavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ navMeshQueries.insert(std::pair<uint32, NavMeshQuery*>(instanceId, query));
+ }
+
+ return navMeshQueries[instanceId];
+ }
+
+ /******************************************************************/
+ bool MMapData::unloadInstance(uint32 instanceId)
+ {
+ if (navMeshQueries.find(instanceId) == navMeshQueries.end())
+ {
+ sLog.outDebug("MMAP:unloadMapInstance: Asked to unload not loaded NavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
+ return false;
+ }
+
+ delete navMeshQueries[instanceId];
+ navMeshQueries.erase(instanceId);
+ sLog.outDetail("MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
+ return true;
+ }
+}
diff --git a/src/game/MoveMapData.h b/src/game/MoveMapData.h
new file mode 100644
index 0000000..5ae5ce3
--- /dev/null
+++ b/src/game/MoveMapData.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MOVE_MAP_DATA_H
+#define _MOVE_MAP_DATA_H
+
+#include "Utilities/UnorderedMapSet.h"
+
+#include "../../dep/recastnavigation/Detour/Include/DetourCommon.h"
+
+#include "NavMesh.h"
+#include "NavMeshQuery.h"
+
+/******************************************************************/
+// move map related classes
+namespace MMAP
+{
+ typedef UNORDERED_MAP<uint32, dtTileRef> MMapTileSet;
+ typedef UNORDERED_MAP<uint32, NavMeshQuery*> NavMeshQuerySet;
+
+ /******************************************************************/
+ // hold all data for given mmap
+ class MMapData
+ {
+ uint32 mapId;
+ NavMesh* navMesh;
+
+ // we have to use single dtNavMeshQuery for every instance, since those are not thread safe
+ NavMeshQuerySet navMeshQueries; // instanceId to query
+ MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile]
+
+ public:
+ MMapData(uint32 mId) : mapId(mId), navMesh(NULL) {}
+ ~MMapData();
+ bool init();
+
+ bool loadTile(uint32 x, uint32 y);
+ bool unloadTile(uint32 x, uint32 y);
+
+ NavMeshQuery* getInstanceNavMeshQuery(uint32 instanceId);
+ bool unloadInstance(uint32 instanceId);
+
+ /******************************************************************/
+ NavMesh* getMapNavMesh()
+ {
+ return navMesh;
+ }
+
+ /******************************************************************/
+ inline uint32 getLoadedTilesCount() const
+ {
+ return mmapLoadedTiles.size();
+ }
+
+ private:
+
+ inline uint32 packTileID(int32 x, int32 y)
+ {
+ return uint32(x << 16 | y);
+ }
+ };
+}
+
+#endif // _MOVE_MAP_DATA_H
diff --git a/src/game/NavMesh.cpp b/src/game/NavMesh.cpp
new file mode 100644
index 0000000..56bfd56
--- /dev/null
+++ b/src/game/NavMesh.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Log.h"
+#include "World.h"
+
+#include "NavMesh.h"
+
+namespace MMAP
+{
+ /******************************************************************/
+ bool NavMesh::init()
+ {
+ // load and init dtNavMesh - read parameters from file
+ uint32 pathLen = sWorld.GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1;
+ char *fileName = new char[pathLen];
+ snprintf(fileName, pathLen, (sWorld.GetDataPath() + "mmaps/%03i.mmap").c_str(), mapId);
+
+ FILE* file = fopen(fileName, "rb");
+ if (!file)
+ {
+ sLog.outDebug("MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName);
+ delete [] fileName;
+ return false;
+ }
+
+ dtNavMeshParams params;
+ fread(&params, sizeof(dtNavMeshParams), 1, file);
+ fclose(file);
+ delete [] fileName;
+
+ navMesh = dtAllocNavMesh();
+ MANGOS_ASSERT(navMesh);
+ if (DT_SUCCESS != navMesh->init(&params))
+ {
+ dtFreeNavMesh(navMesh);
+ return false;
+ }
+
+ return true;
+ }
+
+ /******************************************************************/
+ dtStatus NavMesh::addTile(unsigned char* data, int dataSize, dtTileRef* result)
+ {
+ ACE_Write_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return navMesh->addTile(data, dataSize, DT_TILE_FREE_DATA, 0, result);
+ }
+
+ /******************************************************************/
+ dtStatus NavMesh::removeTile(dtTileRef ref)
+ {
+ ACE_Write_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return navMesh->removeTile(ref, NULL, NULL);
+ }
+
+ /******************************************************************/
+ bool NavMesh::haveTileAt(const Vector3 &p)
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ int tx, ty;
+ const float point[VERTEX_SIZE] = {p.y, p.z, p.x};
+
+ navMesh->calcTileLoc(point, &tx, &ty);
+ return (navMesh->getTileAt(tx, ty) != NULL);
+ }
+
+ /******************************************************************/
+ int NavMesh::getMaxTiles()
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return navMesh->getMaxTiles();
+ }
+
+ /******************************************************************/
+ const dtMeshTile* NavMesh::getTile(int i)
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return ((const dtNavMesh*)navMesh)->getTile(i);;
+ }
+
+ /******************************************************************/
+ dtStatus NavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly)
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return navMesh->getTileAndPolyByRef(ref, tile, poly);
+ }
+
+ /******************************************************************/
+ dtStatus NavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos)
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> guard(navMeshLock);
+ return navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos);
+ }
+}
+
diff --git a/src/game/NavMesh.h b/src/game/NavMesh.h
new file mode 100644
index 0000000..3a696f2
--- /dev/null
+++ b/src/game/NavMesh.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _NAV_MESH_H
+#define _NAV_MESH_H
+
+#include <ace/RW_Mutex.h>
+
+#include "movement/MoveSplineInitArgs.h"
+#include "../../dep/recastnavigation/Detour/Include/DetourNavMesh.h"
+
+#define VERTEX_SIZE 3
+
+using Movement::Vector3;
+
+namespace MMAP
+{
+ // abstraction over dtNavMesh to support thread safety
+ class NavMesh
+ {
+ uint32 mapId;
+ dtNavMesh* navMesh;
+ ACE_RW_Mutex navMeshLock;
+
+ public:
+ NavMesh(uint32 mId) : mapId(mId) {}
+ ~NavMesh()
+ {
+ dtFreeNavMesh(navMesh);
+ }
+
+ bool init();
+
+ dtStatus addTile(unsigned char* data, int dataSize, dtTileRef* result);
+ dtStatus removeTile(dtTileRef ref);
+ bool haveTileAt(const Vector3 &p);
+ int getMaxTiles();
+ const dtMeshTile* getTile(int i);
+ dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly);
+ dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos);
+
+ dtNavMesh const* getMesh() const
+ {
+ return navMesh;
+ };
+
+ /******************************************************************/
+ // use when running NavMeshQuery calls
+ void lock()
+ {
+ navMeshLock.acquire_read();
+ };
+
+ void unlock()
+ {
+ navMeshLock.release();
+ };
+ };
+}
+
+#endif // _NAV_MESH_H
diff --git a/src/game/NavMeshQuery.cpp b/src/game/NavMeshQuery.cpp
new file mode 100644
index 0000000..841cc11
--- /dev/null
+++ b/src/game/NavMeshQuery.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "NavMeshQuery.h"
+
+namespace MMAP
+{
+ /******************************************************************/
+ bool NavMeshQuery::init()
+ {
+ if(DT_SUCCESS != query->init(navMesh->getMesh(), 1024))
+ {
+ dtFreeNavMeshQuery(query);
+ return false;
+ }
+
+ return true;
+ }
+
+ /******************************************************************/
+ dtStatus NavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const
+ {
+ navMesh->lock();
+ dtStatus res = query->closestPointOnPoly(ref, pos, closest);
+ navMesh->unlock();
+ return res;
+ }
+
+ /******************************************************************/
+ dtStatus NavMeshQuery::findNearestPoly(const float* center, const float* extents,
+ const dtQueryFilter* filter,
+ dtPolyRef* nearestRef, float* nearestPt) const
+ {
+ navMesh->lock();
+ dtStatus res = query->findNearestPoly(center, extents, filter, nearestRef, nearestPt);
+ navMesh->unlock();
+ return res;
+ }
+
+ /******************************************************************/
+ dtStatus NavMeshQuery::findPolyPath(dtPolyRef startRef, dtPolyRef endRef,
+ const float* startPos, const float* endPos,
+ const dtQueryFilter* filter,
+ dtPolyRef* path, int* pathCount, const int maxPath) const
+ {
+ navMesh->lock();
+ dtStatus res = query->findPath(startRef, endRef, startPos, endPos, filter, path, pathCount, maxPath);
+ navMesh->unlock();
+ return res;
+ }
+
+ /******************************************************************/
+ dtStatus NavMeshQuery::findStraightPointPath(const float* startPos, const float* endPos,
+ const dtPolyRef* path, const int pathSize,
+ float* straightPath, int* straightPathCount, const int maxStraightPath) const
+ {
+ navMesh->lock();
+ dtStatus res = query->findStraightPath(startPos, endPos, path, pathSize,
+ straightPath, NULL, NULL, straightPathCount, maxStraightPath);
+ navMesh->unlock();
+ return res;
+ }
+
+ /******************************************************************/
+ dtStatus NavMeshQuery::findSmoothPointPath(const float* startPos, const float* endPos,
+ const dtPolyRef* polyPath, const dtQueryFilter* filter, uint32 polyPathSize,
+ float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize)
+ {
+ *smoothPathSize = 0;
+ uint32 nsmoothPath = 0;
+
+ dtPolyRef polys[MAX_PATH_LENGTH];
+ memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize);
+ uint32 npolys = polyPathSize;
+
+ navMesh->lock();
+
+ float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE];
+ if(DT_SUCCESS != query->closestPointOnPolyBoundary(polys[0], startPos, iterPos))
+ return DT_FAILURE;
+
+ if(DT_SUCCESS != query->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))
+ return DT_FAILURE;
+
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
+
+ // Move towards target a small advancement at a time until target reached or
+ // when ran out of memory to store the path.
+ while (npolys && nsmoothPath < maxSmoothPathSize)
+ {
+ // Find location to steer towards.
+ float steerPos[VERTEX_SIZE];
+ unsigned char steerPosFlag;
+ dtPolyRef steerPosRef = INVALID_POLYREF;
+
+ if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef))
+ break;
+
+ bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END);
+ bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION);
+
+ // Find movement delta.
+ float delta[VERTEX_SIZE];
+ dtVsub(delta, steerPos, iterPos);
+ float len = dtSqrt(dtVdot(delta,delta));
+ // If the steer target is end of path or off-mesh link, do not move past the location.
+ if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE)
+ len = 1.0f;
+ else
+ len = SMOOTH_PATH_STEP_SIZE / len;
+
+ float moveTgt[VERTEX_SIZE];
+ dtVmad(moveTgt, iterPos, delta, len);
+
+ // Move
+ float result[VERTEX_SIZE];
+ const static uint32 MAX_VISIT_POLY = 16;
+ dtPolyRef visited[MAX_VISIT_POLY];
+
+ uint32 nvisited = 0;
+ query->moveAlongSurface(polys[0], iterPos, moveTgt, filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY);
+ npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited);
+
+ query->getPolyHeight(polys[0], result, &result[1]);
+ result[1] += 0.5f;
+ dtVcopy(iterPos, result);
+
+ // Handle end of path and off-mesh links when close enough.
+ if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
+ {
+ // Reached end of path.
+ dtVcopy(iterPos, targetPos);
+ if (nsmoothPath < maxSmoothPathSize)
+ {
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
+ }
+ break;
+ }
+ else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
+ {
+ // Advance the path up to and over the off-mesh connection.
+ dtPolyRef prevRef = INVALID_POLYREF;
+ dtPolyRef polyRef = polys[0];
+ uint32 npos = 0;
+ while (npos < npolys && polyRef != steerPosRef)
+ {
+ prevRef = polyRef;
+ polyRef = polys[npos];
+ npos++;
+ }
+
+ for (uint32 i = npos; i < npolys; ++i)
+ polys[i-npos] = polys[i];
+
+ npolys -= npos;
+
+ // Handle the connection.
+ float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
+ if (DT_SUCCESS == navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
+ {
+ if (nsmoothPath < maxSmoothPathSize)
+ {
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
+ nsmoothPath++;
+ }
+ // Move position at the other side of the off-mesh link.
+ dtVcopy(iterPos, endPos);
+
+ query->getPolyHeight(polys[0], iterPos, &iterPos[1]);
+ iterPos[1] += 0.5f;
+ }
+ }
+
+ // Store results.
+ if (nsmoothPath < maxSmoothPathSize)
+ {
+ dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
+ nsmoothPath++;
+ }
+ }
+
+ navMesh->unlock();
+
+ *smoothPathSize = nsmoothPath;
+
+ // this is most likely a loop
+ return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE;
+ }
+
+ /******************************************************************/
+ uint32 NavMeshQuery::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath,
+ const dtPolyRef* visited, uint32 nvisited)
+ {
+ int32 furthestPath = -1;
+ int32 furthestVisited = -1;
+
+ // Find furthest common polygon.
+ for (int32 i = npath-1; i >= 0; --i)
+ {
+ bool found = false;
+ for (int32 j = nvisited-1; j >= 0; --j)
+ {
+ if (path[i] == visited[j])
+ {
+ furthestPath = i;
+ furthestVisited = j;
+ found = true;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ // If no intersection found just return current path.
+ if (furthestPath == -1 || furthestVisited == -1)
+ return npath;
+
+ // Concatenate paths.
+
+ // Adjust beginning of the buffer to include the visited.
+ uint32 req = nvisited - furthestVisited;
+ uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath;
+ uint32 size = npath - orig > 0 ? npath - orig : 0;
+ if (req+size > maxPath)
+ size = maxPath-req;
+
+ if (size)
+ memmove(path+req, path+orig, size*sizeof(dtPolyRef));
+
+ // Store visited
+ for (uint32 i = 0; i < req; ++i)
+ path[i] = visited[(nvisited-1)-i];
+
+ return req+size;
+ }
+
+ /******************************************************************/
+ bool NavMeshQuery::getSteerTarget(const float* startPos, const float* endPos,
+ float minTargetDist, const dtPolyRef* path, uint32 pathSize,
+ float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
+ {
+ // Find steer target.
+ static const uint32 MAX_STEER_POINTS = 3;
+ float steerPath[MAX_STEER_POINTS*VERTEX_SIZE];
+ unsigned char steerPathFlags[MAX_STEER_POINTS];
+ dtPolyRef steerPathPolys[MAX_STEER_POINTS];
+ uint32 nsteerPath = 0;
+ dtStatus dtResult = query->findStraightPath(startPos, endPos, path, pathSize,
+ steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
+ if (!nsteerPath || DT_SUCCESS != dtResult)
+ return false;
+
+ // Find vertex far enough to steer to.
+ uint32 ns = 0;
+ while (ns < nsteerPath)
+ {
+ // Stop at Off-Mesh link or when point is further than slop away.
+ if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
+ !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
+ break;
+ ns++;
+ }
+ // Failed to find good point to steer to.
+ if (ns >= nsteerPath)
+ return false;
+
+ dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]);
+ steerPos[1] = startPos[1]; // keep Z value
+ steerPosFlag = steerPathFlags[ns];
+ steerPosRef = steerPathPolys[ns];
+
+ return true;
+ }
+
+ /******************************************************************/
+ bool NavMeshQuery::inRangeYZX(const float* v1, const float* v2, float r, float h) const
+ {
+ const float dx = v2[0] - v1[0];
+ const float dy = v2[1] - v1[1]; // elevation
+ const float dz = v2[2] - v1[2];
+ return (dx*dx + dz*dz) < r*r && fabsf(dy) < h;
+ }
+}
diff --git a/src/game/NavMeshQuery.h b/src/game/NavMeshQuery.h
new file mode 100644
index 0000000..f5339e2
--- /dev/null
+++ b/src/game/NavMeshQuery.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2005-2012 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _NAV_MESH_QUERY_H
+#define _NAV_MESH_QUERY_H
+
+#include "../../dep/recastnavigation/Detour/Include/DetourCommon.h"
+#include "../../dep/recastnavigation/Detour/Include/DetourNavMeshQuery.h"
+
+#include "NavMesh.h"
+
+// 74*4.0f=296y number_of_points*interval = max_path_len
+// this is way more than actual evade range
+// I think we can safely cut those down even more
+#define MAX_PATH_LENGTH 74
+#define MAX_POINT_PATH_LENGTH 74
+
+#define SMOOTH_PATH_STEP_SIZE 4.0f
+#define SMOOTH_PATH_SLOP 0.3f
+
+#define INVALID_POLYREF 0
+
+namespace MMAP
+{
+ /******************************************************************/
+ class NavMeshQuery
+ {
+ NavMesh* navMesh;
+ dtNavMeshQuery* query;
+
+ public:
+ NavMeshQuery(NavMesh* mesh) : navMesh(mesh), query(NULL)
+ {
+ query = dtAllocNavMeshQuery();
+ MANGOS_ASSERT(query);
+ }
+
+ ~NavMeshQuery()
+ {
+ dtFreeNavMeshQuery(query);
+ }
+
+ bool init();
+
+ dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
+ dtStatus findNearestPoly(const float* center, const float* extents, const dtQueryFilter* filter,
+ dtPolyRef* nearestRef, float* nearestPt) const;
+ dtStatus findPolyPath(dtPolyRef startRef, dtPolyRef endRef,
+ const float* startPos, const float* endPos,
+ const dtQueryFilter* filter,
+ dtPolyRef* path, int* pathCount, const int maxPath) const;
+ dtStatus findStraightPointPath(const float* startPos, const float* endPos,
+ const dtPolyRef* path, const int pathSize,
+ float* straightPath, int* straightPathCount,
+ const int maxStraightPath) const;
+ dtStatus findSmoothPointPath(const float* startPos, const float* endPos,
+ const dtPolyRef* polyPath, const dtQueryFilter* filter, uint32 polyPathSize,
+ float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize);
+ private:
+
+ uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath,
+ const dtPolyRef* visited, uint32 nvisited);
+ bool getSteerTarget(const float* startPos, const float* endPos,
+ float minTargetDist, const dtPolyRef* path, uint32 pathSize,
+ float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef);
+ bool inRangeYZX(const float* v1, const float* v2, float r, float h) const;
+ };
+
+}
+
+#endif // _NAV_MESH_QUERY_H
diff --git a/src/game/PathFinder.cpp b/src/game/PathFinder.cpp
index 1c0b544..3ac1247 100644
--- a/src/game/PathFinder.cpp
+++ b/src/game/PathFinder.cpp
@@ -16,14 +16,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "MoveMap.h"
#include "GridMap.h"
#include "Creature.h"
#include "PathFinder.h"
#include "Log.h"
-#include "../recastnavigation/Detour/Include/DetourCommon.h"
-
////////////////// PathFinder //////////////////
PathFinder::PathFinder(const Unit* owner) :
m_polyLength(0), m_type(PATHFIND_BLANK),
@@ -66,7 +63,7 @@ bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest
// make sure navMesh works - we can run on map w/o mmap
// check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?)
if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) ||
- !HaveTile(start) || !HaveTile(dest))
+ !m_navMesh->haveTileAt(start) || !m_navMesh->haveTileAt(dest))
{
BuildShortcut();
m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
@@ -328,7 +325,7 @@ void PathFinder::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos)
// generate suffix
uint32 suffixPolyLength = 0;
- dtStatus dtResult = m_navMeshQuery->findPath(
+ dtStatus dtResult = m_navMeshQuery->findPolyPath(
suffixStartPoly, // start polygon
endPoly, // end polygon
suffixEndPoint, // start position
@@ -362,7 +359,7 @@ void PathFinder::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos)
// free and invalidate old path data
clear();
- dtStatus dtResult = m_navMeshQuery->findPath(
+ dtStatus dtResult = m_navMeshQuery->findPolyPath(
startPoly, // start polygon
endPoly, // end polygon
startPoint, // start position
@@ -399,23 +396,22 @@ void PathFinder::BuildPointPath(const float *startPoint, const float *endPoint)
dtStatus dtResult = DT_FAILURE;
if (m_useStraightPath)
{
- dtResult = m_navMeshQuery->findStraightPath(
+ dtResult = m_navMeshQuery->findStraightPointPath(
startPoint, // start position
endPoint, // end position
m_pathPolyRefs, // current path
m_polyLength, // lenth of current path
pathPoints, // [out] path corner points
- NULL, // [out] flags
- NULL, // [out] shortened path
(int*)&pointCount,
m_pointPathLimit); // maximum number of points/polygons to use
}
else
{
- dtResult = findSmoothPath(
+ dtResult = m_navMeshQuery->findSmoothPointPath(
startPoint, // start position
endPoint, // end position
m_pathPolyRefs, // current path
+ &m_filter,
m_polyLength, // length of current path
pathPoints, // [out] path corner points
(int*)&pointCount,
@@ -540,229 +536,6 @@ NavTerrain PathFinder::getNavTerrain(float x, float y, float z)
}
}
-bool PathFinder::HaveTile(const Vector3 &p) const
-{
- int tx, ty;
- float point[VERTEX_SIZE] = {p.y, p.z, p.x};
-
- m_navMesh->calcTileLoc(point, &tx, &ty);
- return (m_navMesh->getTileAt(tx, ty) != NULL);
-}
-
-uint32 PathFinder::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath,
- const dtPolyRef* visited, uint32 nvisited)
-{
- int32 furthestPath = -1;
- int32 furthestVisited = -1;
-
- // Find furthest common polygon.
- for (int32 i = npath-1; i >= 0; --i)
- {
- bool found = false;
- for (int32 j = nvisited-1; j >= 0; --j)
- {
- if (path[i] == visited[j])
- {
- furthestPath = i;
- furthestVisited = j;
- found = true;
- }
- }
- if (found)
- break;
- }
-
- // If no intersection found just return current path.
- if (furthestPath == -1 || furthestVisited == -1)
- return npath;
-
- // Concatenate paths.
-
- // Adjust beginning of the buffer to include the visited.
- uint32 req = nvisited - furthestVisited;
- uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath;
- uint32 size = npath-orig > 0 ? npath-orig : 0;
- if (req+size > maxPath)
- size = maxPath-req;
-
- if (size)
- memmove(path+req, path+orig, size*sizeof(dtPolyRef));
-
- // Store visited
- for (uint32 i = 0; i < req; ++i)
- path[i] = visited[(nvisited-1)-i];
-
- return req+size;
-}
-
-bool PathFinder::getSteerTarget(const float* startPos, const float* endPos,
- float minTargetDist, const dtPolyRef* path, uint32 pathSize,
- float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef)
-{
- // Find steer target.
- static const uint32 MAX_STEER_POINTS = 3;
- float steerPath[MAX_STEER_POINTS*VERTEX_SIZE];
- unsigned char steerPathFlags[MAX_STEER_POINTS];
- dtPolyRef steerPathPolys[MAX_STEER_POINTS];
- uint32 nsteerPath = 0;
- dtStatus dtResult = m_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
- steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
- if (!nsteerPath || DT_SUCCESS != dtResult)
- return false;
-
- // Find vertex far enough to steer to.
- uint32 ns = 0;
- while (ns < nsteerPath)
- {
- // Stop at Off-Mesh link or when point is further than slop away.
- if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
- !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f))
- break;
- ns++;
- }
- // Failed to find good point to steer to.
- if (ns >= nsteerPath)
- return false;
-
- dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]);
- steerPos[1] = startPos[1]; // keep Z value
- steerPosFlag = steerPathFlags[ns];
- steerPosRef = steerPathPolys[ns];
-
- return true;
-}
-
-dtStatus PathFinder::findSmoothPath(const float* startPos, const float* endPos,
- const dtPolyRef* polyPath, uint32 polyPathSize,
- float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize)
-{
- *smoothPathSize = 0;
- uint32 nsmoothPath = 0;
-
- dtPolyRef polys[MAX_PATH_LENGTH];
- memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize);
- uint32 npolys = polyPathSize;
-
- float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE];
- if(DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))
- return DT_FAILURE;
-
- if(DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))
- return DT_FAILURE;
-
- dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- nsmoothPath++;
-
- // Move towards target a small advancement at a time until target reached or
- // when ran out of memory to store the path.
- while (npolys && nsmoothPath < maxSmoothPathSize)
- {
- // Find location to steer towards.
- float steerPos[VERTEX_SIZE];
- unsigned char steerPosFlag;
- dtPolyRef steerPosRef = INVALID_POLYREF;
-
- if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef))
- break;
-
- bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END);
- bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION);
-
- // Find movement delta.
- float delta[VERTEX_SIZE];
- dtVsub(delta, steerPos, iterPos);
- float len = dtSqrt(dtVdot(delta,delta));
- // If the steer target is end of path or off-mesh link, do not move past the location.
- if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE)
- len = 1.0f;
- else
- len = SMOOTH_PATH_STEP_SIZE / len;
-
- float moveTgt[VERTEX_SIZE];
- dtVmad(moveTgt, iterPos, delta, len);
-
- // Move
- float result[VERTEX_SIZE];
- const static uint32 MAX_VISIT_POLY = 16;
- dtPolyRef visited[MAX_VISIT_POLY];
-
- uint32 nvisited = 0;
- m_navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &m_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY);
- npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited);
-
- m_navMeshQuery->getPolyHeight(polys[0], result, &result[1]);
- result[1] += 0.5f;
- dtVcopy(iterPos, result);
-
- // Handle end of path and off-mesh links when close enough.
- if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
- {
- // Reached end of path.
- dtVcopy(iterPos, targetPos);
- if (nsmoothPath < maxSmoothPathSize)
- {
- dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- nsmoothPath++;
- }
- break;
- }
- else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f))
- {
- // Advance the path up to and over the off-mesh connection.
- dtPolyRef prevRef = INVALID_POLYREF;
- dtPolyRef polyRef = polys[0];
- uint32 npos = 0;
- while (npos < npolys && polyRef != steerPosRef)
- {
- prevRef = polyRef;
- polyRef = polys[npos];
- npos++;
- }
-
- for (uint32 i = npos; i < npolys; ++i)
- polys[i-npos] = polys[i];
-
- npolys -= npos;
-
- // Handle the connection.
- float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
- if (DT_SUCCESS == m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
- {
- if (nsmoothPath < maxSmoothPathSize)
- {
- dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos);
- nsmoothPath++;
- }
- // Move position at the other side of the off-mesh link.
- dtVcopy(iterPos, endPos);
-
- m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]);
- iterPos[1] += 0.5f;
- }
- }
-
- // Store results.
- if (nsmoothPath < maxSmoothPathSize)
- {
- dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
- nsmoothPath++;
- }
- }
-
- *smoothPathSize = nsmoothPath;
-
- // this is most likely a loop
- return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE;
-}
-
-bool PathFinder::inRangeYZX(const float* v1, const float* v2, float r, float h) const
-{
- const float dx = v2[0] - v1[0];
- const float dy = v2[1] - v1[1]; // elevation
- const float dz = v2[2] - v1[2];
- return (dx*dx + dz*dz) < r*r && fabsf(dy) < h;
-}
-
bool PathFinder::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const
{
Vector3 d = p1-p2;
diff --git a/src/game/PathFinder.h b/src/game/PathFinder.h
index f114521..c578d31 100644
--- a/src/game/PathFinder.h
+++ b/src/game/PathFinder.h
@@ -19,28 +19,17 @@
#ifndef MANGOS_PATH_FINDER_H
#define MANGOS_PATH_FINDER_H
+#include "MoveMap.h"
#include "MoveMapSharedDefines.h"
-#include "../recastnavigation/Detour/Include/DetourNavMesh.h"
-#include "../recastnavigation/Detour/Include/DetourNavMeshQuery.h"
-
#include "movement/MoveSplineInitArgs.h"
using Movement::Vector3;
using Movement::PointsArray;
-class Unit;
-
-// 74*4.0f=296y number_of_points*interval = max_path_len
-// this is way more than actual evade range
-// I think we can safely cut those down even more
-#define MAX_PATH_LENGTH 74
-#define MAX_POINT_PATH_LENGTH 74
+using MMAP::NavMesh;
+using MMAP::NavMeshQuery;
-#define SMOOTH_PATH_STEP_SIZE 4.0f
-#define SMOOTH_PATH_SLOP 0.3f
-
-#define VERTEX_SIZE 3
-#define INVALID_POLYREF 0
+class Unit;
enum PathType
{
@@ -91,8 +80,8 @@ class PathFinder
Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination
const Unit* const m_sourceUnit; // the unit that is moving
- const dtNavMesh* m_navMesh; // the nav mesh
- const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path
+ NavMesh* m_navMesh; // the nav mesh wrapper
+ NavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path
dtQueryFilter m_filter; // use single filter for all movements, update it when needed
@@ -108,11 +97,9 @@ class PathFinder
bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const;
float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const;
- bool inRangeYZX(const float* v1, const float* v2, float r, float h) const;
dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL) const;
dtPolyRef getPolyByLocation(const float* point, float *distance) const;
- bool HaveTile(const Vector3 &p) const;
void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos);
void BuildPointPath(const float *startPoint, const float *endPoint);
@@ -121,16 +108,6 @@ class PathFinder
NavTerrain getNavTerrain(float x, float y, float z);
void createFilter();
void updateFilter();
-
- // smooth path aux functions
- uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath,
- const dtPolyRef* visited, uint32 nvisited);
- bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist,
- const dtPolyRef* path, uint32 pathSize, float* steerPos,
- unsigned char& steerPosFlag, dtPolyRef& steerPosRef);
- dtStatus findSmoothPath(const float* startPos, const float* endPos,
- const dtPolyRef* polyPath, uint32 polyPathSize,
- float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize);
};
#endif
diff --git a/win/VC100/game.vcxproj b/win/VC100/game.vcxproj
index cb2f006..f612fec 100644
--- a/win/VC100/game.vcxproj
+++ b/win/VC100/game.vcxproj
@@ -432,6 +432,7 @@
<ClCompile Include="..\..\src\game\MiscHandler.cpp" />
<ClCompile Include="..\..\src\game\MotionMaster.cpp" />
<ClCompile Include="..\..\src\game\MoveMap.cpp" />
+ <ClCompile Include="..\..\src\game\MoveMapData.cpp" />
<ClCompile Include="..\..\src\game\MovementGenerator.cpp" />
<ClCompile Include="..\..\src\game\MovementHandler.cpp" />
<ClCompile Include="..\..\src\game\movement\MoveSpline.cpp" />
@@ -439,6 +440,8 @@
<ClCompile Include="..\..\src\game\movement\packet_builder.cpp" />
<ClCompile Include="..\..\src\game\movement\spline.cpp" />
<ClCompile Include="..\..\src\game\movement\util.cpp" />
+ <ClCompile Include="..\..\src\game\NavMesh.cpp" />
+ <ClCompile Include="..\..\src\game\NavMeshQuery.cpp" />
<ClCompile Include="..\..\src\game\NPCHandler.cpp" />
<ClCompile Include="..\..\src\game\NullCreatureAI.cpp" />
<ClCompile Include="..\..\src\game\Object.cpp" />
@@ -596,6 +599,7 @@
<ClInclude Include="..\..\src\game\MassMailMgr.h" />
<ClInclude Include="..\..\src\game\MotionMaster.h" />
<ClInclude Include="..\..\src\game\MoveMap.h" />
+ <ClInclude Include="..\..\src\game\MoveMapData.h" />
<ClInclude Include="..\..\src\game\MoveMapSharedDefines.h" />
<ClInclude Include="..\..\src\game\MovementGenerator.h" />
<ClInclude Include="..\..\src\game\movement\MoveSpline.h" />
@@ -606,6 +610,8 @@
<ClInclude Include="..\..\src\game\movement\spline.h" />
<ClInclude Include="..\..\src\game\movement\spline.impl.h" />
<ClInclude Include="..\..\src\game\movement\typedefs.h" />
+ <ClInclude Include="..\..\src\game\NavMesh.h" />
+ <ClInclude Include="..\..\src\game\NavMeshQuery.h" />
<ClInclude Include="..\..\src\game\NPCHandler.h" />
<ClInclude Include="..\..\src\game\NullCreatureAI.h" />
<ClInclude Include="..\..\src\game\Object.h" />
diff --git a/win/VC100/game.vcxproj.filters b/win/VC100/game.vcxproj.filters
index dd1cf6d..488a795 100644
--- a/win/VC100/game.vcxproj.filters
+++ b/win/VC100/game.vcxproj.filters
@@ -31,6 +31,9 @@
<Filter Include="Movement">
<UniqueIdentifier>{0ac140f9-89c1-4830-b673-514c5e8b4d37}</UniqueIdentifier>
</Filter>
+ <Filter Include="pathfinding">
+ <UniqueIdentifier>{8002ee79-9ce4-4282-b8f2-07b46e3d3e36}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\game\AccountMgr.cpp">
@@ -457,12 +460,6 @@
<ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp">
<Filter>Tool</Filter>
</ClCompile>
- <ClCompile Include="..\..\src\game\PathFinder.cpp">
- <Filter>Motion generators</Filter>
- </ClCompile>
- <ClCompile Include="..\..\src\game\MoveMap.cpp">
- <Filter>World/Handlers</Filter>
- </ClCompile>
<ClCompile Include="..\..\src\game\Camera.cpp">
<Filter>Object</Filter>
</ClCompile>
@@ -511,6 +508,21 @@
<ClCompile Include="..\..\src\game\CreatureLinkingMgr.cpp">
<Filter>World/Handlers</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\game\PathFinder.cpp">
+ <Filter>pathfinding</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\game\MoveMap.cpp">
+ <Filter>pathfinding</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\game\NavMesh.cpp">
+ <Filter>pathfinding</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\game\NavMeshQuery.cpp">
+ <Filter>pathfinding</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\game\MoveMapData.cpp">
+ <Filter>pathfinding</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\game\AccountMgr.h">
@@ -898,18 +910,9 @@
<ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h">
<Filter>Tool</Filter>
</ClInclude>
- <ClInclude Include="..\..\src\game\PathFinder.h">
- <Filter>Motion generators</Filter>
- </ClInclude>
<ClInclude Include="..\..\src\game\Camera.h">
<Filter>Object</Filter>
</ClInclude>
- <ClInclude Include="..\..\src\game\MoveMap.h">
- <Filter>World/Handlers</Filter>
- </ClInclude>
- <ClInclude Include="..\..\src\game\MoveMapSharedDefines.h">
- <Filter>World/Handlers</Filter>
- </ClInclude>
<ClInclude Include="..\..\src\game\AuctionHouseBot\AuctionHouseBot.h">
<Filter>AhBot</Filter>
</ClInclude>
@@ -970,5 +973,23 @@
<ClInclude Include="..\..\src\game\CreatureLinkingMgr.h">
<Filter>World/Handlers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\src\game\PathFinder.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\game\MoveMap.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\game\MoveMapSharedDefines.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\game\NavMesh.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\game\NavMeshQuery.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\src\game\MoveMapData.h">
+ <Filter>pathfinding</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
@vermie
Copy link

vermie commented Feb 14, 2012

this is really nice. Do you think we should just wrapper all functions, and not expose the dtNavMesh at all? Might benefit people (mangosR2), they won't have to worry about what kind of lock scope/type

After this diff... MoveMap.cpp line 122, fileName is a invalid reference

@rsa
Copy link

rsa commented Feb 14, 2012

this style of locking not fit to "default mangos-style" (your mean his "ugly") :)
also investigating new lock type in any new production method - not good idea. i make lock method in R2 some time ago (by this template) - works fine.

@vermie
Copy link

vermie commented Feb 14, 2012

You (more than anyone) know mangos can benefit from change.
I haven't looked at what came after Undergarun's crash log, glad to hear you sorted it out

@rsa
Copy link

rsa commented Feb 14, 2012

unfortunately, mangos are almost useless to try to change - too late...
I have not tried to solve the problem (in the mmaps I do not understand nothing, sorry) - just drove this code block under the locking standart of R2 (derived from pure mangos).

@cyberium
Copy link

<< unfortunately, mangos are almost useless to try to change - too late...>> what is useless is that kinds of words coming from you :)
You are good dev but not enought to say shit about all dev involved in MaNGOS.
So keep following MaNGOS, take what you need from it, have a good technical exchange, but stop say your opinion about it where ever you can. We all know it.
Cheers

@sixsixnine
Copy link
Author

@faramir118 : you are right about deleting fileName too early, missed it!
Encapsulating dtNavMesh was the idea, but once I checked all the use cases, it became clear that it won't be very pretty (all those debug commands dig pretty deep).
For now, only mutators are encapsulated, all readers can use constant reference only.
In next iteration I want to make dtNavMesh completely invisible to outside world. That means that the data will have to be loaded from NavMesh etc.
Next step maybe dtNavMeshQuery. This way we wont have such strong coupling with DT code; making version updating much, much easier (possible in our case).

PS: I'll try to be civil about side-notes and not comment.

@rsa
Copy link

rsa commented Feb 14, 2012

@cyberium, better not to meddle in disputes in which you do not understand. best finish at least any one of his work for mangos.
PS went for the second year, I have nothing to take from mangos. you, perhaps it is nothing said, but I'm sad ...

@cyberium
Copy link

@rsa You right, iam not finished any project (no time and not enought knowledge) but IMHO i have contributed to some. You right iam not always understaind all technical data, but it's why iam here to learn. Has i said you are good dev, probably better than me but it's not enought to assume your decision is better than other. If some mangos dev didn't followed you it's for some raison...
Finaly i think all guys are too much polite with your repetly words always say the same. That's why i am doing middle man in this topic.
Sorry for the offtopic, it was my latest words.

@sixsixnine
Copy link
Author

Version 2 added:

  • dtNavMesh fully encapsulated along with almost all its locks.
  • MMapData no longer stupid data-store; it handles all data/calls for single map data management.
  • MMapManager simplified immensely; most logic moved to MMapData where it belogs.

-- TODO1: split files by classes.
-- TODO2: test in-game.
-- TODO3: encapsulate dtNavMeshQuery.

@vermie
Copy link

vermie commented Feb 14, 2012

IIRC, ACE docs say that just declaring a Guard object isn't sufficient - it can fail to acquire the lock, which will probably result in crash in some locations. Not saying it's likely, but possible.
They provide some macros to acquire, test, and [perform action | return a value]

Otherwise, this is great stuff.

@sixsixnine
Copy link
Author

I don't think there's a point in using those macros (ACE_WRITE_GUARD_RETURN etc).
The only thing those macros do is returning unless the mutex is locked.

Our guard is blocking, therefore, the only two ways we can pass that line is by having acquired the lock or on fatal error from which we cannot recover.
Returning at that point is useless, we better take our chances with unsynchronized access, which will not cause issues in 99.9% of cases, other than returning error code and checking something outside/retrying.

Maybe I'm wrong here, but that's what I understood by looking at their doc
http://books.google.co.il/books?id=V43ubgzakIAC&pg=PA216&lpg=PA216&dq=ACE_Read_Guard+macro&source=bl&ots=bv0sZQQ7-5&sig=X5iESeT2FCS9N_L5AofuUrndldU&hl=iw&sa=X&ei=bJ46T_v5PInwsgaxzLCQBw&ved=0CB4Q6AEwAA#v=onepage&q=ACE_Read_Guard%20macro&f=false

@vermie
Copy link

vermie commented Feb 14, 2012

You are right, it looks like the warning I read is only applicable if you use ACE_Guard(lock, false).

@sixsixnine
Copy link
Author

Version 3 (first draft):

  • Encapsulate dtNavMeshQuery and all its helper functions.
  • Split files properly.
  • Adding project filter for pathfinding related files.
  • It is now thread-safe on instance level, completely invisible to outside world.

TODO1: test in-game
TODO2: fix other projects (*nix makes and VSv9)
TODO3: make detour completely invisible to outside code (there's some leftovers like defines, etc)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment