mirror of
https://github.com/mangosfour/server.git
synced 2025-12-15 10:37:02 +00:00
[10727] Map system re-engineered. Special thanks to Blueboy for tests.
Signed-off-by: Ambal <pogrebniak@gala.net>
This commit is contained in:
parent
f5e40a5fda
commit
f67d89f109
43 changed files with 1254 additions and 1128 deletions
|
|
@ -26,6 +26,8 @@
|
|||
#include "GridMap.h"
|
||||
#include "VMapFactory.h"
|
||||
#include "World.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Util.h"
|
||||
|
||||
char const* MAP_MAGIC = "MAPS";
|
||||
char const* MAP_VERSION_MAGIC = "v1.1";
|
||||
|
|
@ -614,3 +616,597 @@ bool GridMap::ExistVMap(uint32 mapid,int gx,int gy)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
TerrainInfo::TerrainInfo(uint32 mapid) : m_mapId(mapid)
|
||||
{
|
||||
for (int k = 0; k < MAX_NUMBER_OF_GRIDS; ++k)
|
||||
{
|
||||
for (int i = 0; i < MAX_NUMBER_OF_GRIDS; ++i)
|
||||
{
|
||||
m_GridMaps[i][k] = NULL;
|
||||
m_GridRef[i][k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//clean up GridMap objects every minute
|
||||
const uint32 iCleanUpInterval = 60;
|
||||
//schedule start randlomly
|
||||
const uint32 iRandomStart = urand(20, 40);
|
||||
|
||||
i_timer.SetInterval(iCleanUpInterval * 1000);
|
||||
i_timer.SetCurrent(iRandomStart * 1000);
|
||||
}
|
||||
|
||||
TerrainInfo::~TerrainInfo()
|
||||
{
|
||||
for (int k = 0; k < MAX_NUMBER_OF_GRIDS; ++k)
|
||||
for (int i = 0; i < MAX_NUMBER_OF_GRIDS; ++i)
|
||||
delete m_GridMaps[i][k];
|
||||
|
||||
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(m_mapId);
|
||||
}
|
||||
|
||||
GridMap * TerrainInfo::Load(const uint32 x, const uint32 y)
|
||||
{
|
||||
MANGOS_ASSERT(x < MAX_NUMBER_OF_GRIDS);
|
||||
MANGOS_ASSERT(y < MAX_NUMBER_OF_GRIDS);
|
||||
|
||||
//reference grid as a first step
|
||||
RefGrid(x, y);
|
||||
|
||||
//quick check if GridMap already loaded
|
||||
GridMap * pMap = m_GridMaps[x][y];
|
||||
if(!pMap)
|
||||
pMap = LoadMapAndVMap(x, y);
|
||||
|
||||
return pMap;
|
||||
}
|
||||
|
||||
//schedule lazy GridMap object cleanup
|
||||
void TerrainInfo::Unload(const uint32 x, const uint32 y)
|
||||
{
|
||||
MANGOS_ASSERT(x < MAX_NUMBER_OF_GRIDS);
|
||||
MANGOS_ASSERT(y < MAX_NUMBER_OF_GRIDS);
|
||||
|
||||
if(m_GridMaps[x][y])
|
||||
{
|
||||
//decrease grid reference count...
|
||||
if(UnrefGrid(x, y) == 0)
|
||||
{
|
||||
//TODO: add your additional logic here
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//call this method only
|
||||
void TerrainInfo::CleanUpGrids(const uint32 diff)
|
||||
{
|
||||
i_timer.Update(diff);
|
||||
if( !i_timer.Passed() )
|
||||
return;
|
||||
|
||||
for (int y = 0; y < MAX_NUMBER_OF_GRIDS; ++y)
|
||||
{
|
||||
for (int x = 0; x < MAX_NUMBER_OF_GRIDS; ++x)
|
||||
{
|
||||
const int16& iRef = m_GridRef[x][y];
|
||||
GridMap * pMap = m_GridMaps[x][y];
|
||||
|
||||
//delete those GridMap objects which have refcount = 0
|
||||
if(pMap && iRef == 0 )
|
||||
{
|
||||
m_GridMaps[x][y] = NULL;
|
||||
//delete grid data if reference count == 0
|
||||
pMap->unloadData();
|
||||
delete pMap;
|
||||
|
||||
//unload VMAPS...
|
||||
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(m_mapId, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i_timer.Reset();
|
||||
}
|
||||
|
||||
int TerrainInfo::RefGrid(const uint32& x, const uint32& y)
|
||||
{
|
||||
MANGOS_ASSERT(x < MAX_NUMBER_OF_GRIDS);
|
||||
MANGOS_ASSERT(y < MAX_NUMBER_OF_GRIDS);
|
||||
|
||||
LOCK_GUARD _lock(m_refMutex);
|
||||
return (m_GridRef[x][y] += 1);
|
||||
}
|
||||
|
||||
int TerrainInfo::UnrefGrid(const uint32& x, const uint32& y)
|
||||
{
|
||||
MANGOS_ASSERT(x < MAX_NUMBER_OF_GRIDS);
|
||||
MANGOS_ASSERT(y < MAX_NUMBER_OF_GRIDS);
|
||||
|
||||
int16& iRef = m_GridRef[x][y];
|
||||
|
||||
LOCK_GUARD _lock(m_refMutex);
|
||||
if(iRef > 0)
|
||||
return (iRef -= 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float TerrainInfo::GetHeight(float x, float y, float z, bool pUseVmaps, float maxSearchDist) const
|
||||
{
|
||||
// find raw .map surface under Z coordinates
|
||||
float mapHeight;
|
||||
float z2 = z + 2.f;
|
||||
if (GridMap *gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
float _mapheight = gmap->getHeight(x,y);
|
||||
|
||||
// look from a bit higher pos to find the floor, ignore under surface case
|
||||
if (z2 > _mapheight)
|
||||
mapHeight = _mapheight;
|
||||
else
|
||||
mapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
else
|
||||
mapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
|
||||
float vmapHeight;
|
||||
if (pUseVmaps)
|
||||
{
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
if (vmgr->isHeightCalcEnabled())
|
||||
{
|
||||
// if mapHeight has been found search vmap height at least until mapHeight point
|
||||
// this prevent case when original Z "too high above ground and vmap height search fail"
|
||||
// this will not affect most normal cases (no map in instance, or stay at ground at continent)
|
||||
if (mapHeight > INVALID_HEIGHT && z2 - mapHeight > maxSearchDist)
|
||||
maxSearchDist = z2 - mapHeight + 1.0f; // 1.0 make sure that we not fail for case when map height near but above for vamp height
|
||||
|
||||
// look from a bit higher pos to find the floor
|
||||
vmapHeight = vmgr->getHeight(GetMapId(), x, y, z2, maxSearchDist);
|
||||
}
|
||||
else
|
||||
vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
else
|
||||
vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
|
||||
// mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
|
||||
// vmapheight set for any under Z value or <= INVALID_HEIGHT
|
||||
|
||||
if (vmapHeight > INVALID_HEIGHT)
|
||||
{
|
||||
if (mapHeight > INVALID_HEIGHT)
|
||||
{
|
||||
// we have mapheight and vmapheight and must select more appropriate
|
||||
|
||||
// we are already under the surface or vmap height above map heigt
|
||||
// or if the distance of the vmap height is less the land height distance
|
||||
if (z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z))
|
||||
return vmapHeight;
|
||||
else
|
||||
return mapHeight; // better use .map surface height
|
||||
|
||||
}
|
||||
else
|
||||
return vmapHeight; // we have only vmapHeight (if have)
|
||||
}
|
||||
|
||||
return mapHeight;
|
||||
}
|
||||
|
||||
inline bool IsOutdoorWMO(uint32 mogpFlags, int32 adtId, int32 rootId, int32 groupId,
|
||||
WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
|
||||
{
|
||||
bool outdoor = true;
|
||||
|
||||
if(wmoEntry && atEntry)
|
||||
{
|
||||
if(atEntry->flags & AREA_FLAG_OUTSIDE)
|
||||
return true;
|
||||
if(atEntry->flags & AREA_FLAG_INSIDE)
|
||||
return false;
|
||||
}
|
||||
|
||||
outdoor = mogpFlags&0x8;
|
||||
|
||||
if(wmoEntry)
|
||||
{
|
||||
if(wmoEntry->Flags & 4)
|
||||
return true;
|
||||
|
||||
if((wmoEntry->Flags & 2)!=0)
|
||||
outdoor = false;
|
||||
}
|
||||
return outdoor;
|
||||
}
|
||||
|
||||
bool TerrainInfo::IsOutdoors(float x, float y, float z) const
|
||||
{
|
||||
uint32 mogpFlags;
|
||||
int32 adtId, rootId, groupId;
|
||||
|
||||
// no wmo found? -> outside by default
|
||||
if(!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
|
||||
return true;
|
||||
|
||||
AreaTableEntry const* atEntry = 0;
|
||||
WMOAreaTableEntry const* wmoEntry= GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
|
||||
if(wmoEntry)
|
||||
{
|
||||
DEBUG_LOG("Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId);
|
||||
|
||||
atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
|
||||
}
|
||||
|
||||
return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
|
||||
}
|
||||
|
||||
bool TerrainInfo::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
|
||||
{
|
||||
float vmap_z = z;
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
if (vmgr->getAreaInfo(GetMapId(), x, y, vmap_z, flags, adtId, rootId, groupId))
|
||||
{
|
||||
// check if there's terrain between player height and object height
|
||||
if(GridMap *gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
float _mapheight = gmap->getHeight(x,y);
|
||||
// z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
|
||||
if(z + 2.0f > _mapheight && _mapheight > vmap_z)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 TerrainInfo::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const
|
||||
{
|
||||
uint32 mogpFlags;
|
||||
int32 adtId, rootId, groupId;
|
||||
WMOAreaTableEntry const* wmoEntry = 0;
|
||||
AreaTableEntry const* atEntry = 0;
|
||||
bool haveAreaInfo = false;
|
||||
|
||||
if(GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
|
||||
{
|
||||
haveAreaInfo = true;
|
||||
wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
|
||||
if(wmoEntry)
|
||||
atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
|
||||
}
|
||||
|
||||
uint16 areaflag;
|
||||
if (atEntry)
|
||||
areaflag = atEntry->exploreFlag;
|
||||
else
|
||||
{
|
||||
if(GridMap *gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
areaflag = gmap->getArea(x, y);
|
||||
// this used while not all *.map files generated (instances)
|
||||
else
|
||||
areaflag = GetAreaFlagByMapId(GetMapId());
|
||||
}
|
||||
|
||||
if (isOutdoors)
|
||||
{
|
||||
if (haveAreaInfo)
|
||||
*isOutdoors = IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
|
||||
else
|
||||
*isOutdoors = true;
|
||||
}
|
||||
return areaflag;
|
||||
}
|
||||
|
||||
uint8 TerrainInfo::GetTerrainType(float x, float y ) const
|
||||
{
|
||||
if(GridMap *gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
return gmap->getTerrainType(x, y);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 TerrainInfo::GetAreaId(float x, float y, float z) const
|
||||
{
|
||||
return TerrainManager::GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),m_mapId);
|
||||
}
|
||||
|
||||
uint32 TerrainInfo::GetZoneId(float x, float y, float z) const
|
||||
{
|
||||
return TerrainManager::GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),m_mapId);
|
||||
}
|
||||
|
||||
void TerrainInfo::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
|
||||
{
|
||||
TerrainManager::GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),m_mapId);
|
||||
}
|
||||
|
||||
|
||||
GridMapLiquidStatus TerrainInfo::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, GridMapLiquidData *data) const
|
||||
{
|
||||
GridMapLiquidStatus result = LIQUID_MAP_NO_WATER;
|
||||
VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager();
|
||||
float liquid_level, ground_level = INVALID_HEIGHT;
|
||||
uint32 liquid_type;
|
||||
if (vmgr->GetLiquidLevel(GetMapId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
|
||||
{
|
||||
DEBUG_LOG("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
|
||||
// Check water level and ground level
|
||||
if (liquid_level > ground_level && z > ground_level - 2)
|
||||
{
|
||||
// All ok in water -> store data
|
||||
if (data)
|
||||
{
|
||||
data->type = liquid_type;
|
||||
data->level = liquid_level;
|
||||
data->depth_level = ground_level;
|
||||
}
|
||||
|
||||
// For speed check as int values
|
||||
int delta = int((liquid_level - z) * 10);
|
||||
|
||||
// Get position delta
|
||||
if (delta > 20) // Under water
|
||||
return LIQUID_MAP_UNDER_WATER;
|
||||
if (delta > 0 ) // In water
|
||||
return LIQUID_MAP_IN_WATER;
|
||||
if (delta > -1) // Walk on water
|
||||
return LIQUID_MAP_WATER_WALK;
|
||||
result = LIQUID_MAP_ABOVE_WATER;
|
||||
}
|
||||
}
|
||||
if(GridMap* gmap = const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
GridMapLiquidData map_data;
|
||||
GridMapLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
|
||||
// Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
|
||||
if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
|
||||
{
|
||||
if (data)
|
||||
*data = map_data;
|
||||
return map_result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TerrainInfo::IsInWater(float x, float y, float pZ, GridMapLiquidData *data) const
|
||||
{
|
||||
// Check surface in x, y point for liquid
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
GridMapLiquidData liquid_status;
|
||||
GridMapLiquidData *liquid_ptr = data ? data : &liquid_status;
|
||||
if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr))
|
||||
{
|
||||
//if (liquid_prt->level - liquid_prt->depth_level > 2) //???
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TerrainInfo::IsUnderWater(float x, float y, float z) const
|
||||
{
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function find higher form water or ground height for current floor
|
||||
*
|
||||
* @param x, y, z Coordinates original point at floor level
|
||||
*
|
||||
* @param pGround optional arg for retrun calculated by function work ground height, it let avoid in caller code recalculate height for point if it need
|
||||
*
|
||||
* @param swim z coordinate can be calculated for select above/at or under z coordinate (for fly or swim/walking by bottom)
|
||||
* in last cases for in water returned under water height for avoid client set swimming unit as saty at water.
|
||||
*
|
||||
* @return calculated z coordinate
|
||||
*/
|
||||
float TerrainInfo::GetWaterOrGroundLevel(float x, float y, float z, float* pGround /*= NULL*/, bool swim /*= false*/) const
|
||||
{
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
// we need ground level (including grid height version) for proper return water level in point
|
||||
float ground_z = GetHeight(x, y, z, true, DEFAULT_WATER_SEARCH);
|
||||
if (pGround)
|
||||
*pGround = ground_z;
|
||||
|
||||
GridMapLiquidData liquid_status;
|
||||
|
||||
GridMapLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
|
||||
return res ? ( swim ? liquid_status.level - 2.0f : liquid_status.level) : ground_z;
|
||||
}
|
||||
|
||||
return VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
|
||||
GridMap * TerrainInfo::GetGrid( const float x, const float y )
|
||||
{
|
||||
// half opt method
|
||||
int gx=(int)(32-x/SIZE_OF_GRIDS); //grid x
|
||||
int gy=(int)(32-y/SIZE_OF_GRIDS); //grid y
|
||||
|
||||
//quick check if GridMap already loaded
|
||||
GridMap * pMap = m_GridMaps[gx][gy];
|
||||
if(!pMap)
|
||||
pMap = LoadMapAndVMap(gx, gy);
|
||||
|
||||
return pMap;
|
||||
}
|
||||
|
||||
GridMap * TerrainInfo::LoadMapAndVMap( const uint32 x, const uint32 y )
|
||||
{
|
||||
//double checked lock pattern
|
||||
if(!m_GridMaps[x][y])
|
||||
{
|
||||
LOCK_GUARD lock(m_mutex);
|
||||
|
||||
if(!m_GridMaps[x][y])
|
||||
{
|
||||
GridMap * map = new GridMap();
|
||||
|
||||
// map file name
|
||||
char *tmp=NULL;
|
||||
int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1;
|
||||
tmp = new char[len];
|
||||
snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),m_mapId, x, y);
|
||||
sLog.outDetail("Loading map %s",tmp);
|
||||
|
||||
if(!map->loadData(tmp))
|
||||
{
|
||||
sLog.outError("Error load map file: \n %s\n", tmp);
|
||||
//ASSERT(false);
|
||||
}
|
||||
|
||||
delete [] tmp;
|
||||
m_GridMaps[x][y] = map;
|
||||
|
||||
//load VMAPs for current map/grid...
|
||||
const MapEntry * i_mapEntry = sMapStore.LookupEntry(m_mapId);
|
||||
const char* mapName = i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
|
||||
|
||||
int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), m_mapId, x, y);
|
||||
switch(vmapLoadResult)
|
||||
{
|
||||
case VMAP::VMAP_LOAD_RESULT_OK:
|
||||
sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, m_mapId, x,y,x,y);
|
||||
break;
|
||||
case VMAP::VMAP_LOAD_RESULT_ERROR:
|
||||
sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, m_mapId, x,y,x,y);
|
||||
break;
|
||||
case VMAP::VMAP_LOAD_RESULT_IGNORED:
|
||||
DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", mapName, m_mapId, x,y,x,y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_GridMaps[x][y];
|
||||
}
|
||||
|
||||
float TerrainInfo::GetWaterLevel(float x, float y, float z, float* pGround /*= NULL*/) const
|
||||
{
|
||||
if (const_cast<TerrainInfo*>(this)->GetGrid(x, y))
|
||||
{
|
||||
// we need ground level (including grid height version) for proper return water level in point
|
||||
float ground_z = GetHeight(x, y, z, true, DEFAULT_WATER_SEARCH);
|
||||
if (pGround)
|
||||
*pGround = ground_z;
|
||||
|
||||
GridMapLiquidData liquid_status;
|
||||
|
||||
GridMapLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
|
||||
if (!res)
|
||||
return VMAP_INVALID_HEIGHT_VALUE;
|
||||
|
||||
return liquid_status.level;
|
||||
}
|
||||
|
||||
return VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define CLASS_LOCK MaNGOS::ClassLevelLockable<TerrainManager, ACE_Thread_Mutex>
|
||||
INSTANTIATE_SINGLETON_2(TerrainManager, CLASS_LOCK);
|
||||
INSTANTIATE_CLASS_MUTEX(TerrainManager, ACE_Thread_Mutex);
|
||||
|
||||
TerrainManager::TerrainManager()
|
||||
{
|
||||
}
|
||||
|
||||
TerrainManager::~TerrainManager()
|
||||
{
|
||||
for (TerrainDataMap::iterator it = i_TerrainMap.begin(); it != i_TerrainMap.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
TerrainInfo * TerrainManager::LoadTerrain(const uint32 mapId)
|
||||
{
|
||||
Guard _guard(*this);
|
||||
|
||||
TerrainInfo * ptr = NULL;
|
||||
TerrainDataMap::const_iterator iter = i_TerrainMap.find(mapId);
|
||||
if(iter == i_TerrainMap.end())
|
||||
{
|
||||
ptr = new TerrainInfo(mapId);
|
||||
i_TerrainMap[mapId] = ptr;
|
||||
}
|
||||
else
|
||||
ptr = (*iter).second;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void TerrainManager::UnloadTerrain(const uint32 mapId)
|
||||
{
|
||||
if(sWorld.getConfig(CONFIG_BOOL_GRID_UNLOAD) == 0)
|
||||
return;
|
||||
|
||||
Guard _guard(*this);
|
||||
|
||||
TerrainDataMap::iterator iter = i_TerrainMap.find(mapId);
|
||||
if(iter != i_TerrainMap.end())
|
||||
{
|
||||
TerrainInfo * ptr = (*iter).second;
|
||||
//lets check if this object can be actually freed
|
||||
if(ptr->IsReferenced() == false)
|
||||
{
|
||||
i_TerrainMap.erase(iter);
|
||||
delete ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainManager::Update(const uint32 diff)
|
||||
{
|
||||
//global garbage collection for GridMap objects and VMaps
|
||||
for (TerrainDataMap::iterator iter = i_TerrainMap.begin(); iter != i_TerrainMap.end(); ++iter)
|
||||
iter->second->CleanUpGrids(diff);
|
||||
}
|
||||
|
||||
void TerrainManager::UnloadAll()
|
||||
{
|
||||
for (TerrainDataMap::iterator it = i_TerrainMap.begin(); it != i_TerrainMap.end(); ++it)
|
||||
delete it->second;
|
||||
|
||||
i_TerrainMap.clear();
|
||||
}
|
||||
|
||||
uint32 TerrainManager::GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id)
|
||||
{
|
||||
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
|
||||
|
||||
if (entry)
|
||||
return entry->ID;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 TerrainManager::GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id)
|
||||
{
|
||||
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
|
||||
|
||||
if( entry )
|
||||
return ( entry->zone != 0 ) ? entry->zone : entry->ID;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TerrainManager::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id)
|
||||
{
|
||||
AreaTableEntry const *entry = GetAreaEntryByAreaFlagAndMap(areaflag,map_id);
|
||||
|
||||
areaid = entry ? entry->ID : 0;
|
||||
zoneid = entry ? (( entry->zone != 0 ) ? entry->zone : entry->ID) : 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue