Core/Entities: Phasing rewrite
This commit is contained in:
@@ -43,6 +43,7 @@ namespace Game.Maps
|
||||
if (!File.Exists(filename))
|
||||
return true;
|
||||
|
||||
_fileExists = true;
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
mapFileHeader header = reader.ReadStruct<mapFileHeader>();
|
||||
@@ -72,6 +73,7 @@ namespace Game.Maps
|
||||
_liquidFlags = null;
|
||||
_liquidMap = null;
|
||||
_gridGetHeight = getHeightFromFlat;
|
||||
_fileExists = false;
|
||||
}
|
||||
|
||||
void LoadAreaData(BinaryReader reader, uint offset)
|
||||
@@ -435,8 +437,8 @@ namespace Game.Maps
|
||||
};
|
||||
|
||||
Cell cell = new Cell(x, y);
|
||||
float gx = x - (cell.GetGridX() - MapConst.CenterGridId + 1) *MapConst.SizeofGrids;
|
||||
float gy = y - (cell.GetGridY() - MapConst.CenterGridId + 1) *MapConst.SizeofGrids;
|
||||
float gx = x - (cell.GetGridX() - MapConst.CenterGridId + 1) * MapConst.SizeofGrids;
|
||||
float gy = y - (cell.GetGridY() - MapConst.CenterGridId + 1) * MapConst.SizeofGrids;
|
||||
|
||||
uint quarterIndex = 0;
|
||||
if (cell.GetCellY() < MapConst.MaxCells / 2)
|
||||
@@ -595,6 +597,8 @@ namespace Game.Maps
|
||||
|
||||
public float getHeight(float x, float y) { return _gridGetHeight(x, y); }
|
||||
|
||||
public bool fileExists() { return _fileExists; }
|
||||
|
||||
#region Fields
|
||||
delegate float GetHeight(float x, float y);
|
||||
|
||||
@@ -627,6 +631,7 @@ namespace Game.Maps
|
||||
byte _liquidOffY;
|
||||
byte _liquidWidth;
|
||||
byte _liquidHeight;
|
||||
bool _fileExists;
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -727,7 +727,7 @@ namespace Game.Maps
|
||||
{
|
||||
var players = instance.GetPlayers();
|
||||
foreach (var player in players)
|
||||
player.SendUpdatePhasing();
|
||||
PhasingHandler.SendToPlayer(player);
|
||||
}
|
||||
|
||||
public void UpdateCombatResurrection(uint diff)
|
||||
|
||||
@@ -34,19 +34,27 @@ namespace Game
|
||||
const string MAP_FILE_NAME_FORMAT = "{0}/mmaps/{1:D4}.mmap";
|
||||
const string TILE_FILE_NAME_FORMAT = "{0}/mmaps/{1:D4}{2:D2}{3:D2}.mmtile";
|
||||
|
||||
public void Initialize(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
childMapData = mapData;
|
||||
|
||||
foreach (var pair in mapData)
|
||||
parentMapData[pair.Value] = pair.Key;
|
||||
}
|
||||
|
||||
MMapData GetMMapData(uint mapId)
|
||||
{
|
||||
return loadedMMaps.LookupByKey(mapId);
|
||||
}
|
||||
|
||||
bool loadMapData(uint mapId)
|
||||
bool loadMapData(string basePath, uint mapId)
|
||||
{
|
||||
// we already have this map loaded?
|
||||
if (loadedMMaps.ContainsKey(mapId) && loadedMMaps[mapId] != null)
|
||||
return true;
|
||||
|
||||
// load and init dtNavMesh - read parameters from file
|
||||
string filename = string.Format(MAP_FILE_NAME_FORMAT, Global.WorldMgr.GetDataPath(), mapId);
|
||||
string filename = string.Format(MAP_FILE_NAME_FORMAT, basePath, mapId);
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "Could not open mmap file {0}", filename);
|
||||
@@ -80,15 +88,30 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
uint packTileID(int x, int y)
|
||||
uint packTileID(uint x, uint y)
|
||||
{
|
||||
return (uint)(x << 16 | y);
|
||||
return (x << 16 | y);
|
||||
}
|
||||
|
||||
public bool loadMap(uint mapId, int x, int y)
|
||||
public bool loadMap(string basePath, uint mapId, uint x, uint y)
|
||||
{
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
if (!loadMapData(mapId))
|
||||
if (!loadMapImpl(basePath, mapId, x, y))
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadMapImpl(basePath, childMapId, x, y))
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool loadMapImpl(string basePath, uint mapId, uint x, uint y)
|
||||
{
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
if (!loadMapData(basePath, mapId))
|
||||
return false;
|
||||
|
||||
// get this mmap data
|
||||
@@ -101,14 +124,20 @@ namespace Game
|
||||
return false;
|
||||
|
||||
// load this tile . mmaps/MMMXXYY.mmtile
|
||||
string filename = string.Format(TILE_FILE_NAME_FORMAT, Global.WorldMgr.GetDataPath(), mapId, x, y);
|
||||
if (!File.Exists(filename))
|
||||
string fileName = string.Format(TILE_FILE_NAME_FORMAT, basePath, mapId, x, y);
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "MMAP:loadMap: Could not open mmtile file '{0}'", filename);
|
||||
if (parentMapData.ContainsKey(mapId))
|
||||
fileName = string.Format(TILE_FILE_NAME_FORMAT, basePath, parentMapData[mapId], x, y);
|
||||
}
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "MMAP:loadMap: Could not open mmtile file '{0}'", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
MmapTileHeader fileHeader = reader.ReadStruct<MmapTileHeader>();
|
||||
Array.Reverse(fileHeader.mmapMagic);
|
||||
@@ -144,7 +173,52 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
public bool loadMapInstance(string basePath, uint mapId, uint instanceId)
|
||||
{
|
||||
if (!loadMapInstanceImpl(basePath, mapId, instanceId))
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadMapInstanceImpl(basePath, childMapId, instanceId))
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool loadMapInstanceImpl(string basePath, uint mapId, uint instanceId)
|
||||
{
|
||||
if (!loadMapData(basePath, mapId))
|
||||
return false;
|
||||
|
||||
MMapData mmap = loadedMMaps[mapId];
|
||||
if (mmap.navMeshQueries.ContainsKey(instanceId))
|
||||
return true;
|
||||
|
||||
// allocate mesh query
|
||||
Detour.dtNavMeshQuery query = new Detour.dtNavMeshQuery();
|
||||
if (Detour.dtStatusFailed(query.init(mmap.navMesh, 1024)))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "MMAP.GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {0:D4} instanceId {1}", mapId, instanceId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "MMAP.GetNavMeshQuery: created dtNavMeshQuery for mapId {0:D4} instanceId {1}", mapId, instanceId);
|
||||
mmap.navMeshQueries.Add(instanceId, query);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadMapImpl(childMapId, x, y);
|
||||
|
||||
return unloadMapImpl(mapId, x, y);
|
||||
}
|
||||
|
||||
bool unloadMapImpl(uint mapId, uint x, uint y)
|
||||
{
|
||||
// check if we have this map loaded
|
||||
MMapData mmap = GetMMapData(mapId);
|
||||
@@ -156,7 +230,7 @@ namespace Game
|
||||
}
|
||||
|
||||
// check if we have this tile loaded
|
||||
uint packedGridPos = packTileID((int)x, (int)y);
|
||||
uint packedGridPos = packTileID(x, y);
|
||||
if (!mmap.loadedTileRefs.ContainsKey(packedGridPos))
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
@@ -164,7 +238,7 @@ namespace Game
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong tileRef = mmap.loadedTileRefs.LookupByKey(packedGridPos);
|
||||
ulong tileRef = mmap.loadedTileRefs[packedGridPos];
|
||||
|
||||
// unload, and mark as non loaded
|
||||
Detour.dtRawTileData data;
|
||||
@@ -256,20 +330,6 @@ namespace Game
|
||||
if (mmap == null)
|
||||
return null;
|
||||
|
||||
if (!mmap.navMeshQueries.ContainsKey(instanceId))
|
||||
{
|
||||
// allocate mesh query
|
||||
Detour.dtNavMeshQuery query = new Detour.dtNavMeshQuery();
|
||||
if (Detour.dtStatusFailed(query.init(mmap.navMesh, 1024)))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {0} instanceId {1}", mapId, instanceId);
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.outInfo(LogFilter.Maps, "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {0} instanceId {1}", mapId, instanceId);
|
||||
mmap.navMeshQueries.Add(instanceId, query);
|
||||
}
|
||||
|
||||
return mmap.navMeshQueries[instanceId];
|
||||
}
|
||||
|
||||
@@ -278,6 +338,9 @@ namespace Game
|
||||
|
||||
Dictionary<uint, MMapData> loadedMMaps = new Dictionary<uint, MMapData>();
|
||||
uint loadedTiles;
|
||||
|
||||
MultiMap<uint, uint> childMapData = new MultiMap<uint, uint>();
|
||||
Dictionary<uint, uint> parentMapData = new Dictionary<uint, uint>();
|
||||
}
|
||||
|
||||
public class MMapData
|
||||
|
||||
+199
-108
@@ -48,7 +48,16 @@ namespace Game.Maps
|
||||
i_gridExpiry = expiry;
|
||||
_defaultLight = Global.DB2Mgr.GetDefaultMapLight(id);
|
||||
|
||||
m_parentMap = parent ?? this;
|
||||
if (parent)
|
||||
{
|
||||
m_parentMap = parent;
|
||||
m_childTerrainMaps = m_parentMap.m_childTerrainMaps;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_parentMap = this;
|
||||
m_childTerrainMaps = new List<Map>();
|
||||
}
|
||||
|
||||
for (uint x = 0; x < MapConst.MaxGrids; ++x)
|
||||
{
|
||||
@@ -69,6 +78,8 @@ namespace Game.Maps
|
||||
|
||||
GetGuidSequenceGenerator(HighGuid.Transport).Set(Global.ObjectMgr.GetGenerator(HighGuid.Transport).GetNextAfterMaxUsed());
|
||||
|
||||
Global.MMapMgr.loadMapInstance(Global.WorldMgr.GetDataPath(), GetId(), i_InstanceId);
|
||||
|
||||
Global.ScriptMgr.OnCreateMap(this);
|
||||
}
|
||||
|
||||
@@ -112,7 +123,10 @@ namespace Game.Maps
|
||||
|
||||
void LoadMMap(uint gx, uint gy)
|
||||
{
|
||||
if (Global.MMapMgr.loadMap(GetId(), (int)gx, (int)gy))
|
||||
if (!Global.DisableMgr.IsPathfindingEnabled(GetId()))
|
||||
return;
|
||||
|
||||
if (Global.MMapMgr.loadMap(Global.WorldMgr.GetDataPath(), GetId(), gx, gy))
|
||||
Log.outInfo(LogFilter.Maps, "MMAP loaded name:{0}, id:{1}, x:{2}, y:{3} (mmap rep.: x:{4}, y:{5})", GetMapName(), GetId(), gx, gy, gx, gy);
|
||||
else
|
||||
Log.outInfo(LogFilter.Maps, "Could not load MMAP name:{0}, id:{1}, x:{2}, y:{3} (mmap rep.: x:{4}, y:{5})", GetMapName(), GetId(), gx, gy, gx, gy);
|
||||
@@ -138,39 +152,62 @@ namespace Game.Maps
|
||||
|
||||
void LoadMap(uint gx, uint gy, bool reload = false)
|
||||
{
|
||||
if (i_InstanceId != 0)
|
||||
LoadMapImpl(this, gx, gy, reload);
|
||||
foreach (Map childBaseMap in m_childTerrainMaps)
|
||||
LoadMapImpl(childBaseMap, gx, gy, reload);
|
||||
}
|
||||
|
||||
void LoadMapImpl(Map map, uint gx, uint gy, bool reload)
|
||||
{
|
||||
if (map.i_InstanceId != 0)
|
||||
{
|
||||
if (GridMaps[gx][gy] != null)
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
return;
|
||||
|
||||
// load grid map for base map
|
||||
if (m_parentMap.GridMaps[gx][gy] == null)
|
||||
m_parentMap.EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
if (map.m_parentMap.GridMaps[gx][gy] == null)
|
||||
map.m_parentMap.EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
|
||||
((MapInstanced)m_parentMap).AddGridMapReference(new GridCoord(gx, gy));
|
||||
GridMaps[gx][gy] = m_parentMap.GridMaps[gx][gy];
|
||||
map.m_parentMap.ToMapInstanced().AddGridMapReference(new GridCoord(gx, gy));
|
||||
map.GridMaps[gx][gy] = map.m_parentMap.GridMaps[gx][gy];
|
||||
return;
|
||||
}
|
||||
|
||||
if (GridMaps[gx][gy] != null && !reload)
|
||||
if (map.GridMaps[gx][gy] != null && !reload)
|
||||
return;
|
||||
|
||||
if (GridMaps[gx][gy] != null)
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
{
|
||||
Log.outInfo(LogFilter.Maps, "Unloading previously loaded map {0} before reloading.", GetId());
|
||||
Global.ScriptMgr.OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy);
|
||||
Log.outInfo(LogFilter.Maps, "Unloading previously loaded map {0} before reloading.", map.GetId());
|
||||
Global.ScriptMgr.OnUnloadGridMap(map, map.GridMaps[gx][gy], gx, gy);
|
||||
|
||||
GridMaps[gx][gy] = null;
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
// map file name
|
||||
string filename = string.Format("{0}/maps/{1:D4}_{2:D2}_{3:D2}.map", Global.WorldMgr.GetDataPath(), GetId(), gx, gy);
|
||||
string filename = string.Format("{0}/maps/{1:D4}_{2:D2}_{3:D2}.map", Global.WorldMgr.GetDataPath(), map.GetId(), gx, gy);
|
||||
Log.outInfo(LogFilter.Maps, "Loading map {0}", filename);
|
||||
// loading data
|
||||
GridMaps[gx][gy] = new GridMap();
|
||||
if (!GridMaps[gx][gy].loadData(filename))
|
||||
map.GridMaps[gx][gy] = new GridMap();
|
||||
if (!map.GridMaps[gx][gy].loadData(filename))
|
||||
Log.outError(LogFilter.Maps, "Error loading map file: {0}", filename);
|
||||
|
||||
Global.ScriptMgr.OnLoadGridMap(this, GridMaps[gx][gy], gx, gy);
|
||||
Global.ScriptMgr.OnLoadGridMap(map, map.GridMaps[gx][gy], gx, gy);
|
||||
}
|
||||
|
||||
void UnloadMap(Map map, uint gx, uint gy)
|
||||
{
|
||||
if (map.i_InstanceId == 0)
|
||||
{
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
{
|
||||
map.GridMaps[gx][gy].unloadData();
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
map.m_parentMap.ToMapInstanced().RemoveGridMapReference(new GridCoord(gx, gy));
|
||||
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
|
||||
void LoadMapAndVMap(uint gx, uint gy)
|
||||
@@ -415,7 +452,7 @@ namespace Game.Maps
|
||||
player.m_clientGUIDs.Clear();
|
||||
|
||||
player.UpdateObjectVisibility(false);
|
||||
player.SendUpdatePhasing();
|
||||
PhasingHandler.SendToPlayer(player);
|
||||
|
||||
if (player.IsAlive())
|
||||
ConvertCorpseToBones(player.GetGUID());
|
||||
@@ -466,8 +503,6 @@ namespace Game.Maps
|
||||
if (obj.isActiveObject())
|
||||
AddToActive(obj);
|
||||
|
||||
obj.RebuildTerrainSwaps();
|
||||
|
||||
//something, such as vehicle, needs to be update immediately
|
||||
//also, trigger needs to cast spell, if not update, cannot see visual
|
||||
obj.UpdateObjectVisibilityOnCreate();
|
||||
@@ -499,6 +534,7 @@ namespace Game.Maps
|
||||
{
|
||||
var data = new UpdateData(GetId());
|
||||
obj.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
player.m_visibleTransports.Add(obj.GetGUID());
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
player.SendPacket(packet);
|
||||
@@ -804,9 +840,14 @@ namespace Game.Maps
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
|
||||
foreach (var pl in players)
|
||||
if (pl.GetTransport() != obj)
|
||||
pl.SendPacket(packet);
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player.GetTransport() != obj)
|
||||
{
|
||||
player.SendPacket(packet);
|
||||
player.m_visibleTransports.Remove(obj.GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_transports.Contains(obj))
|
||||
@@ -1541,20 +1582,19 @@ namespace Game.Maps
|
||||
uint gx = (MapConst.MaxGrids - 1) - x;
|
||||
uint gy = (MapConst.MaxGrids - 1) - y;
|
||||
|
||||
// delete grid map, but don't delete if it is from parent map (and thus only reference)
|
||||
//+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
|
||||
{
|
||||
foreach (Map childBaseMap in m_childTerrainMaps)
|
||||
UnloadMap(childBaseMap, gx, gy);
|
||||
|
||||
UnloadMap(this, gx, gy);
|
||||
|
||||
if (i_InstanceId == 0)
|
||||
{
|
||||
if (GridMaps[gx][gy] != null)
|
||||
{
|
||||
GridMaps[gx][gy].unloadData();
|
||||
}
|
||||
Global.VMapMgr.unloadMap(GetId(), gx, gy);
|
||||
Global.MMapMgr.unloadMap(GetId(), gx, gy);
|
||||
}
|
||||
else
|
||||
((MapInstanced)m_parentMap).RemoveGridMapReference(new GridCoord(gx, gy));
|
||||
|
||||
GridMaps[gx][gy] = null;
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "Unloading grid[{0}, {1}] for map {2} finished", x, y, GetId());
|
||||
return true;
|
||||
@@ -1624,49 +1664,79 @@ namespace Game.Maps
|
||||
if (!m_scriptSchedule.Empty())
|
||||
Global.MapMgr.DecreaseScheduledScriptCount((uint)m_scriptSchedule.Count);
|
||||
|
||||
if (m_parentMap == this)
|
||||
m_childTerrainMaps = null;
|
||||
|
||||
Global.MMapMgr.unloadMapInstance(GetId(), i_InstanceId);
|
||||
}
|
||||
|
||||
private GridMap GetGridMap(float x, float y)
|
||||
{
|
||||
// half opt method
|
||||
var gx = (uint)(32 - x / MapConst.SizeofGrids); //grid x
|
||||
var gy = (uint)(32 - y / MapConst.SizeofGrids); //grid y
|
||||
var gx = (uint)(MapConst.CenterGridId - x / MapConst.SizeofGrids); //grid x
|
||||
var gy = (uint)(MapConst.CenterGridId - y / MapConst.SizeofGrids); //grid y
|
||||
|
||||
// ensure GridMap is loaded
|
||||
EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
EnsureGridCreated(new GridCoord((MapConst.MaxGrids - 1) - gx, (MapConst.MaxGrids - 1) - gy));
|
||||
|
||||
return GridMaps[gx][gy];
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(List<uint> phases, float x, float y, float z)
|
||||
GridMap GetGridMap(uint mapId, float x, float y)
|
||||
{
|
||||
float ground = 0f;
|
||||
return GetWaterOrGroundLevel(phases, x, y, z, ref ground);
|
||||
if (GetId() == mapId)
|
||||
return GetGridMap(x, y);
|
||||
|
||||
// half opt method
|
||||
uint gx = (uint)(MapConst.CenterGridId - x / MapConst.SizeofGrids); //grid x
|
||||
uint gy = (uint)(MapConst.CenterGridId - y / MapConst.SizeofGrids); //grid y
|
||||
|
||||
// ensure GridMap is loaded
|
||||
EnsureGridCreated(new GridCoord((MapConst.MaxGrids - 1) - gx, (MapConst.MaxGrids - 1) - gy));
|
||||
|
||||
GridMap grid = GridMaps[gx][gy];
|
||||
var childMap = m_childTerrainMaps.Find(childTerrainMap => childTerrainMap.GetId() == mapId);
|
||||
if (childMap != null && childMap.GridMaps[gx][gy].fileExists())
|
||||
grid = childMap.GridMaps[gx][gy];
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(List<uint> phases, float x, float y, float z, ref float ground, bool swim = false)
|
||||
public bool HasGridMap(uint mapId, uint gx, uint gy)
|
||||
{
|
||||
var childMap = m_childTerrainMaps.Find(childTerrainMap => childTerrainMap.GetId() == mapId);
|
||||
return childMap != null && childMap.GridMaps[gx][gy] != null && childMap.GridMaps[gx][gy].fileExists();
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
float ground = 0f;
|
||||
return GetWaterOrGroundLevel(phaseShift, x, y, z, ref ground);
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z, ref float ground, bool swim = false)
|
||||
{
|
||||
if (GetGridMap(x, y) != null)
|
||||
{
|
||||
// we need ground level (including grid height version) for proper return water level in point
|
||||
float ground_z = GetHeight(phases, x, y, z, true, 50.0f);
|
||||
float ground_z = GetHeight(phaseShift, x, y, z, true, 50.0f);
|
||||
ground = ground_z;
|
||||
|
||||
LiquidData liquid_status;
|
||||
|
||||
ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
ZLiquidStatus res = getLiquidStatus(phaseShift, x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
return res != ZLiquidStatus.NoWater ? liquid_status.level : ground_z;
|
||||
}
|
||||
|
||||
return MapConst.VMAPInvalidHeightValue;
|
||||
}
|
||||
|
||||
public float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
public float GetStaticHeight(PhaseShift phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
{
|
||||
// find raw .map surface under Z coordinates
|
||||
float mapHeight = MapConst.VMAPInvalidHeightValue;
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
float gridHeight = gmap.getHeight(x, y);
|
||||
@@ -1679,7 +1749,7 @@ namespace Game.Maps
|
||||
if (checkVMap)
|
||||
{
|
||||
if (Global.VMapMgr.isHeightCalcEnabled())
|
||||
vmapHeight = Global.VMapMgr.getHeight(GetId(), x, y, z + 2.0f, maxSearchDist);
|
||||
vmapHeight = Global.VMapMgr.getHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist);
|
||||
// look from a bit higher pos to find the floor
|
||||
}
|
||||
|
||||
@@ -1736,13 +1806,13 @@ namespace Game.Maps
|
||||
return outdoor;
|
||||
}
|
||||
|
||||
public bool IsOutdoors(float x, float y, float z)
|
||||
public bool IsOutdoors(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint mogpFlags;
|
||||
int adtId, rootId, groupId;
|
||||
|
||||
// no wmo found? . outside by default
|
||||
if (!GetAreaInfo(x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
if (!GetAreaInfo(phaseShift, x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
return true;
|
||||
|
||||
AreaTableRecord atEntry = null;
|
||||
@@ -1756,7 +1826,7 @@ namespace Game.Maps
|
||||
return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
|
||||
}
|
||||
|
||||
private bool GetAreaInfo(float x, float y, float z, out uint flags, out int adtId, out int rootId, out int groupId)
|
||||
private bool GetAreaInfo(PhaseShift phaseShift, float x, float y, float z, out uint flags, out int adtId, out int rootId, out int groupId)
|
||||
{
|
||||
flags = 0;
|
||||
adtId = 0;
|
||||
@@ -1764,10 +1834,11 @@ namespace Game.Maps
|
||||
groupId = 0;
|
||||
|
||||
float vmap_z = z;
|
||||
if (Global.VMapMgr.getAreaInfo(GetId(), x, y, ref vmap_z, out flags, out adtId, out rootId, out groupId))
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (Global.VMapMgr.getAreaInfo(terrainMapId, x, y, ref vmap_z, out flags, out adtId, out rootId, out groupId))
|
||||
{
|
||||
// check if there's terrain between player height and object height
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
float _mapheight = gmap.getHeight(x, y);
|
||||
@@ -1781,13 +1852,13 @@ namespace Game.Maps
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetAreaId(float x, float y, float z)
|
||||
public uint GetAreaId(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
bool throwaway;
|
||||
return GetAreaId(x, y, z, out throwaway);
|
||||
return GetAreaId(phaseShift, x, y, z, out throwaway);
|
||||
}
|
||||
|
||||
public uint GetAreaId(float x, float y, float z, out bool isOutdoors)
|
||||
public uint GetAreaId(PhaseShift phaseShift, float x, float y, float z, out bool isOutdoors)
|
||||
{
|
||||
uint mogpFlags;
|
||||
int adtId, rootId, groupId;
|
||||
@@ -1796,7 +1867,7 @@ namespace Game.Maps
|
||||
bool haveAreaInfo = false;
|
||||
uint areaId = 0;
|
||||
|
||||
if (GetAreaInfo(x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
if (GetAreaInfo(phaseShift, x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
{
|
||||
haveAreaInfo = true;
|
||||
wmoEntry = Global.DB2Mgr.GetWMOAreaTable(rootId, adtId, groupId);
|
||||
@@ -1809,7 +1880,7 @@ namespace Game.Maps
|
||||
|
||||
if (areaId == 0)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
areaId = gmap.getArea(x, y);
|
||||
|
||||
@@ -1826,9 +1897,9 @@ namespace Game.Maps
|
||||
return areaId;
|
||||
}
|
||||
|
||||
public uint GetZoneId(float x, float y, float z)
|
||||
public uint GetZoneId(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint areaId = GetAreaId(x, y, z);
|
||||
uint areaId = GetAreaId(phaseShift, x, y, z);
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaId);
|
||||
if (area != null)
|
||||
if (area.ParentAreaID != 0)
|
||||
@@ -1837,38 +1908,38 @@ namespace Game.Maps
|
||||
return areaId;
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid, float x, float y, float z)
|
||||
public void GetZoneAndAreaId(PhaseShift phaseShift, out uint zoneid, out uint areaid, float x, float y, float z)
|
||||
{
|
||||
areaid = zoneid = GetAreaId(x, y, z);
|
||||
areaid = zoneid = GetAreaId(phaseShift, x, y, z);
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaid);
|
||||
if (area != null)
|
||||
if (area.ParentAreaID != 0)
|
||||
zoneid = area.ParentAreaID;
|
||||
}
|
||||
|
||||
private byte GetTerrainType(float x, float y)
|
||||
private byte GetTerrainType(PhaseShift phaseShift, float x, float y)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
return gmap.getTerrainType(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ZLiquidStatus getLiquidStatus(float x, float y, float z, byte ReqLiquidType)
|
||||
public ZLiquidStatus getLiquidStatus(PhaseShift phaseShift, float x, float y, float z, byte ReqLiquidType)
|
||||
{
|
||||
LiquidData throwaway;
|
||||
return getLiquidStatus(x, y, z, ReqLiquidType, out throwaway);
|
||||
return getLiquidStatus(phaseShift, x, y, z, ReqLiquidType, out throwaway);
|
||||
}
|
||||
|
||||
public ZLiquidStatus getLiquidStatus(float x, float y, float z, byte ReqLiquidType, out LiquidData data)
|
||||
public ZLiquidStatus getLiquidStatus(PhaseShift phaseShift, float x, float y, float z, byte ReqLiquidType, out LiquidData data)
|
||||
{
|
||||
data = new LiquidData();
|
||||
var result = ZLiquidStatus.NoWater;
|
||||
float liquid_level = MapConst.InvalidHeight;
|
||||
float ground_level = MapConst.InvalidHeight;
|
||||
uint liquid_type = 0;
|
||||
|
||||
if (Global.VMapMgr.GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, ref liquid_level, ref ground_level, ref liquid_type))
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (Global.VMapMgr.GetLiquidLevel(terrainMapId, x, y, z, ReqLiquidType, ref liquid_level, ref ground_level, ref liquid_type))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "getLiquidStatus(): vmap liquid level: {0} ground: {1} type: {2}",
|
||||
liquid_level, ground_level, liquid_type);
|
||||
@@ -1887,7 +1958,7 @@ namespace Game.Maps
|
||||
|
||||
if (liquid_type != 0 && liquid_type < 21)
|
||||
{
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(GetAreaId(x, y, z));
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(GetAreaId(phaseShift, x, y, z));
|
||||
if (area != null)
|
||||
{
|
||||
uint overrideLiquid = area.LiquidTypeID[liquidFlagType];
|
||||
@@ -1926,7 +1997,7 @@ namespace Game.Maps
|
||||
}
|
||||
}
|
||||
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
var map_data = new LiquidData();
|
||||
@@ -1946,27 +2017,27 @@ namespace Game.Maps
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetWaterLevel(float x, float y)
|
||||
public float GetWaterLevel(PhaseShift phaseShift, float x, float y)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
return gmap.getLiquidLevel(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, List<uint> phases)
|
||||
public bool isInLineOfSight(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
return Global.VMapMgr.isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
|
||||
&& _dynamicTree.isInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phases);
|
||||
return Global.VMapMgr.isInLineOfSight(PhasingHandler.GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2)
|
||||
&& _dynamicTree.isInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phaseShift);
|
||||
}
|
||||
|
||||
public bool getObjectHitPos(List<uint> phases, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
public bool getObjectHitPos(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
var startPos = new Vector3(x1, y1, z1);
|
||||
var dstPos = new Vector3(x2, y2, z2);
|
||||
|
||||
var resultPos = new Vector3();
|
||||
bool result = _dynamicTree.getObjectHitPos(phases, startPos, dstPos, ref resultPos, modifyDist);
|
||||
bool result = _dynamicTree.getObjectHitPos(startPos, dstPos, ref resultPos, modifyDist, phaseShift);
|
||||
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
@@ -1974,22 +2045,19 @@ namespace Game.Maps
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetHeight(List<uint> phases, float x, float y, float z, bool vmap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
public float GetHeight(PhaseShift phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
{
|
||||
return Math.Max(GetHeight(x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phases));
|
||||
return Math.Max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phaseShift));
|
||||
}
|
||||
|
||||
public bool IsInWater(float x, float y, float pZ)
|
||||
public bool IsInWater(PhaseShift phaseShift, float x, float y, float pZ)
|
||||
{
|
||||
return Convert.ToBoolean(getLiquidStatus(x, y, pZ, MapConst.MapAllLiquidTypes) &
|
||||
(ZLiquidStatus.InWater | ZLiquidStatus.UnderWater));
|
||||
return Convert.ToBoolean(getLiquidStatus(phaseShift, x, y, pZ, MapConst.MapAllLiquidTypes) & (ZLiquidStatus.InWater | ZLiquidStatus.UnderWater));
|
||||
}
|
||||
|
||||
public bool IsUnderWater(float x, float y, float z)
|
||||
public bool IsUnderWater(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
return
|
||||
Convert.ToBoolean(getLiquidStatus(x, y, z, MapConst.MapLiquidTypeWater | MapConst.MapLiquidTypeOcean) &
|
||||
ZLiquidStatus.UnderWater);
|
||||
return Convert.ToBoolean(getLiquidStatus(phaseShift, x, y, z, MapConst.MapLiquidTypeWater | MapConst.MapLiquidTypeOcean) & ZLiquidStatus.UnderWater);
|
||||
}
|
||||
|
||||
private bool CheckGridIntegrity(Creature c, bool moved)
|
||||
@@ -2007,30 +2075,32 @@ namespace Game.Maps
|
||||
return i_mapRecord != null ? i_mapRecord.MapName[Global.WorldMgr.GetDefaultDbcLocale()] : "UNNAMEDMAP";
|
||||
}
|
||||
|
||||
public void SendInitSelf(Player pl)
|
||||
public void SendInitSelf(Player player)
|
||||
{
|
||||
var data = new UpdateData(pl.GetMapId());
|
||||
var data = new UpdateData(player.GetMapId());
|
||||
|
||||
// attach to player data current transport data
|
||||
Transport transport = pl.GetTransport();
|
||||
if (transport != null)
|
||||
transport.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
|
||||
pl.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
|
||||
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
|
||||
|
||||
Transport transport = player.GetTransport();
|
||||
if (transport != null)
|
||||
{
|
||||
foreach (WorldObject obj in transport.GetPassengers())
|
||||
transport.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
|
||||
player.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
|
||||
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
|
||||
if (transport != null)
|
||||
{
|
||||
foreach (WorldObject passenger in transport.GetPassengers())
|
||||
{
|
||||
if (pl != obj && pl.HaveAtClient(obj))
|
||||
obj.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
if (player != passenger && player.HaveAtClient(passenger))
|
||||
passenger.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
}
|
||||
}
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
pl.SendPacket(packet);
|
||||
player.SendPacket(packet);
|
||||
}
|
||||
|
||||
void SendInitTransports(Player player)
|
||||
@@ -2040,7 +2110,10 @@ namespace Game.Maps
|
||||
foreach (Transport transport in _transports)
|
||||
{
|
||||
if (transport != player.GetTransport() && player.IsInPhase(transport))
|
||||
{
|
||||
transport.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
@@ -2052,27 +2125,39 @@ namespace Game.Maps
|
||||
{
|
||||
var transData = new UpdateData(player.GetMapId());
|
||||
foreach (Transport transport in _transports)
|
||||
{
|
||||
if (transport != player.GetTransport())
|
||||
{
|
||||
transport.BuildOutOfRangeUpdateBlock(transData);
|
||||
player.m_visibleTransports.Remove(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
transData.BuildPacket(out packet);
|
||||
player.SendPacket(packet);
|
||||
}
|
||||
|
||||
public void SendUpdateTransportVisibility(Player player, List<uint> previousPhases)
|
||||
public void SendUpdateTransportVisibility(Player player)
|
||||
{
|
||||
// Hack to send out transports
|
||||
UpdateData transData = new UpdateData(player.GetMapId());
|
||||
foreach (var trans in _transports)
|
||||
foreach (var transport in _transports)
|
||||
{
|
||||
if (trans == player.GetTransport())
|
||||
continue;
|
||||
|
||||
if (player.IsInPhase(trans) && !previousPhases.Intersect(trans.GetPhases()).Any())
|
||||
trans.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
else if (!player.IsInPhase(trans))
|
||||
trans.BuildOutOfRangeUpdateBlock(transData);
|
||||
var hasTransport = player.m_visibleTransports.Contains(transport.GetGUID());
|
||||
if (player.IsInPhase(transport))
|
||||
{
|
||||
if (!hasTransport)
|
||||
{
|
||||
transport.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transport.BuildOutOfRangeUpdateBlock(transData);
|
||||
player.m_visibleTransports.Remove(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
@@ -2525,7 +2610,7 @@ namespace Game.Maps
|
||||
continue;
|
||||
|
||||
foreach (var phaseId in phases[guid])
|
||||
corpse.SetInPhase(phaseId, false, true);
|
||||
PhasingHandler.AddPhase(corpse, phaseId, false);
|
||||
|
||||
AddCorpse(corpse);
|
||||
} while (result.NextRow());
|
||||
@@ -2604,7 +2689,7 @@ namespace Game.Maps
|
||||
|
||||
bones.SetUInt32Value(CorpseFields.Flags, corpse.GetUInt32Value(CorpseFields.Flags) | (uint)CorpseFlags.Bones);
|
||||
|
||||
bones.CopyPhaseFrom(corpse);
|
||||
PhasingHandler.InheritPhaseShift(bones, corpse);
|
||||
|
||||
AddCorpse(bones);
|
||||
|
||||
@@ -2847,6 +2932,10 @@ namespace Game.Maps
|
||||
return m_parentMap;
|
||||
}
|
||||
|
||||
public void AddChildTerrainMap(Map map) { m_childTerrainMaps.Add(map); }
|
||||
|
||||
public void UnlinkAllChildTerrainMaps() { m_childTerrainMaps.Clear(); }
|
||||
|
||||
public uint GetInstanceId()
|
||||
{
|
||||
return i_InstanceId;
|
||||
@@ -3225,7 +3314,8 @@ namespace Game.Maps
|
||||
return null;
|
||||
|
||||
// Set the summon to the summoner's phase
|
||||
summon.CopyPhaseFrom(summoner);
|
||||
if (summoner)
|
||||
PhasingHandler.InheritPhaseShift(summon, summoner);
|
||||
|
||||
summon.SetUInt32Value(UnitFields.CreatedBySpell, spellId);
|
||||
|
||||
@@ -4219,6 +4309,7 @@ namespace Game.Maps
|
||||
protected List<WorldObject> m_activeNonPlayers = new List<WorldObject>();
|
||||
protected List<Player> m_activePlayers = new List<Player>();
|
||||
Map m_parentMap;
|
||||
List<Map> m_childTerrainMaps = new List<Map>();
|
||||
SortedMultiMap<long, ScriptAction> m_scriptSchedule = new SortedMultiMap<long, ScriptAction>();
|
||||
|
||||
BitArray marked_cells = new BitArray(MapConst.TotalCellsPerMap * MapConst.TotalCellsPerMap);
|
||||
|
||||
+108
-74
@@ -37,10 +37,15 @@ namespace Game.Entities
|
||||
public void Initialize()
|
||||
{
|
||||
//todo needs alot of support for threadsafe.
|
||||
//int num_threads= WorldConfig.GetIntValue(WorldCfg.Numthreads);
|
||||
int num_threads = WorldConfig.GetIntValue(WorldCfg.Numthreads);
|
||||
// Start mtmaps if needed.
|
||||
//if (num_threads > 0)
|
||||
//m_updater = new MapUpdater(WorldConfig.GetIntValue(WorldCfg.Numthreads));
|
||||
if (num_threads > 0)
|
||||
m_updater = new MapUpdater(WorldConfig.GetIntValue(WorldCfg.Numthreads));
|
||||
}
|
||||
|
||||
public void InitializeParentMapData(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
_parentMapData = mapData;
|
||||
}
|
||||
|
||||
public void InitializeVisibilityDistanceInfo()
|
||||
@@ -52,31 +57,46 @@ namespace Game.Entities
|
||||
public Map CreateBaseMap(uint id)
|
||||
{
|
||||
Map map = FindBaseMap(id);
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
lock (this)
|
||||
var entry = CliDB.MapStorage.LookupByKey(id);
|
||||
Contract.Assert(entry != null);
|
||||
if (entry.ParentMapID != -1)
|
||||
{
|
||||
CreateBaseMap((uint)entry.ParentMapID);
|
||||
|
||||
var entry = CliDB.MapStorage.LookupByKey(id);
|
||||
Contract.Assert(entry != null);
|
||||
|
||||
if (entry.Instanceable())
|
||||
map = new MapInstanced(id, i_gridCleanUpDelay);
|
||||
else
|
||||
{
|
||||
map = new Map(id, i_gridCleanUpDelay, 0, Difficulty.None);
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
}
|
||||
|
||||
i_maps[id] = map;
|
||||
// must have been created by parent map
|
||||
map = FindBaseMap(id);
|
||||
return map;
|
||||
}
|
||||
|
||||
lock(_mapsLock)
|
||||
map = CreateBaseMap_i(entry);
|
||||
}
|
||||
Contract.Assert(map != null);
|
||||
return map;
|
||||
}
|
||||
|
||||
Map CreateBaseMap_i(MapRecord mapEntry)
|
||||
{
|
||||
Map map;
|
||||
if (mapEntry.Instanceable())
|
||||
map = new MapInstanced(mapEntry.Id, i_gridCleanUpDelay);
|
||||
else
|
||||
{
|
||||
map = new Map(mapEntry.Id, i_gridCleanUpDelay, 0, Difficulty.None);
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
}
|
||||
|
||||
i_maps[mapEntry.Id] = map;
|
||||
|
||||
foreach (uint childMapId in _parentMapData[mapEntry.Id])
|
||||
map.AddChildTerrainMap(CreateBaseMap_i(CliDB.MapStorage.LookupByKey(childMapId)));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map FindBaseNonInstanceMap(uint mapId)
|
||||
{
|
||||
Map map = FindBaseMap(mapId);
|
||||
@@ -206,20 +226,14 @@ namespace Game.Entities
|
||||
var time = (uint)i_timer.GetCurrent();
|
||||
foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//if (!m_updater)
|
||||
//m_updater.Enqueue(map, (uint)i_timer.GetCurrent());
|
||||
//else
|
||||
map.Update(time);
|
||||
if (m_updater != null)
|
||||
m_updater.Enqueue(map, (uint)i_timer.GetCurrent());
|
||||
else
|
||||
map.Update(time);
|
||||
}
|
||||
|
||||
//List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();
|
||||
//foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(() => map.Update(time)));
|
||||
}
|
||||
//System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
|
||||
//if (!m_updater)
|
||||
// m_updater.Wait();
|
||||
if (m_updater != null)
|
||||
m_updater.Wait();
|
||||
|
||||
foreach (var map in i_maps.ToList())
|
||||
map.Value.DelayedUpdate(time);
|
||||
@@ -251,6 +265,10 @@ namespace Game.Entities
|
||||
|
||||
public void UnloadAll()
|
||||
{
|
||||
// first unlink child maps
|
||||
foreach (var pair in i_maps)
|
||||
pair.Value.UnlinkAllChildTerrainMaps();
|
||||
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
pair.Value.UnloadAll();
|
||||
@@ -260,34 +278,40 @@ namespace Game.Entities
|
||||
|
||||
public uint GetNumInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps.ToList())
|
||||
lock (_mapsLock)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret++;
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public uint GetNumPlayersInInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret += (uint)imap.Value.GetPlayers().Count;
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret += (uint)imap.Value.GetPlayers().Count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void InitInstanceIds()
|
||||
@@ -361,54 +385,60 @@ namespace Game.Entities
|
||||
return i_maps.LookupByKey(mapId);
|
||||
}
|
||||
|
||||
uint GetAreaId(uint mapid, float x, float y, float z)
|
||||
uint GetAreaId(PhaseShift phaseShift, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetAreaId(x, y, z);
|
||||
return m.GetAreaId(phaseShift, x, y, z);
|
||||
}
|
||||
|
||||
public uint GetZoneId(uint mapid, float x, float y, float z)
|
||||
public uint GetZoneId(PhaseShift phaseShift, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetZoneId(x, y, z);
|
||||
return m.GetZoneId(phaseShift, x, y, z);
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid, uint mapid, float x, float y, float z)
|
||||
public void GetZoneAndAreaId(PhaseShift phaseShift, out uint zoneid, out uint areaid, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
m.GetZoneAndAreaId(out zoneid, out areaid, x, y, z);
|
||||
m.GetZoneAndAreaId(phaseShift, out zoneid, out areaid, x, y, z);
|
||||
}
|
||||
|
||||
public void DoForAllMaps(Action<Map> worker)
|
||||
{
|
||||
foreach (var map in i_maps.Values)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
foreach (var map in i_maps.Values)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances.Values)
|
||||
worker(instance);
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances.Values)
|
||||
worker(instance);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
public void DoForAllMapsWithMapId(uint mapId, Action<Map> worker)
|
||||
{
|
||||
var map = i_maps.LookupByKey(mapId);
|
||||
if (map != null)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
var map = i_maps.LookupByKey(mapId);
|
||||
if (map != null)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances)
|
||||
worker(instance.Value);
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances)
|
||||
worker(instance.Value);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,10 +449,14 @@ namespace Game.Entities
|
||||
|
||||
Dictionary<uint, Map> i_maps = new Dictionary<uint, Map>();
|
||||
IntervalTimer i_timer = new IntervalTimer();
|
||||
object _mapsLock= new object();
|
||||
uint i_gridCleanUpDelay;
|
||||
Dictionary<uint, bool> _instanceIds = new Dictionary<uint, bool>();
|
||||
uint _nextInstanceId;
|
||||
//MapUpdater m_updater;
|
||||
MapUpdater m_updater;
|
||||
uint _scheduledScripts;
|
||||
|
||||
// parent map links
|
||||
MultiMap<uint, uint> _parentMapData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ namespace Game.Maps
|
||||
_transportAnimations[transportEntry] = animNode;
|
||||
}
|
||||
|
||||
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, uint phaseid = 0, uint phasegroup = 0)
|
||||
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, PhaseUseFlagsValues phaseUseFlags = 0, uint phaseId = 0, uint phaseGroupId = 0)
|
||||
{
|
||||
// instance case, execute GetGameObjectEntry hook
|
||||
if (map != null)
|
||||
@@ -388,12 +388,7 @@ namespace Game.Maps
|
||||
if (!trans.Create(guidLow, entry, mapId, x, y, z, o, 255))
|
||||
return null;
|
||||
|
||||
if (phaseid != 0)
|
||||
trans.SetInPhase(phaseid, false, true);
|
||||
|
||||
if (phasegroup != 0)
|
||||
foreach (var ph in Global.DB2Mgr.GetPhasesForGroup(phasegroup))
|
||||
trans.SetInPhase(ph, false, true);
|
||||
PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId);
|
||||
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapId);
|
||||
if (mapEntry != null)
|
||||
@@ -424,7 +419,7 @@ namespace Game.Maps
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT guid, entry, phaseid, phasegroup FROM transports");
|
||||
SQLResult result = DB.World.Query("SELECT guid, entry, phaseUseFlags, phaseid, phasegroup FROM transports");
|
||||
|
||||
uint count = 0;
|
||||
if (!result.IsEmpty())
|
||||
@@ -433,13 +428,51 @@ namespace Game.Maps
|
||||
{
|
||||
ulong guid = result.Read<ulong>(0);
|
||||
uint entry = result.Read<uint>(1);
|
||||
uint phaseid = result.Read<uint>(2);
|
||||
uint phasegroup = result.Read<uint>(3);
|
||||
PhaseUseFlagsValues phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(2);
|
||||
uint phaseId = result.Read<uint>(3);
|
||||
uint phaseGroupId = result.Read<uint>(4);
|
||||
|
||||
if (Convert.ToBoolean(phaseUseFlags & ~PhaseUseFlagsValues.All))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with unknown `phaseUseFlags` set, removed unknown value.");
|
||||
phaseUseFlags &= PhaseUseFlagsValues.All;
|
||||
}
|
||||
|
||||
if (phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," +
|
||||
" removing PHASE_USE_FLAGS_INVERSE.");
|
||||
phaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
|
||||
}
|
||||
|
||||
if (phaseGroupId != 0 && phaseId != 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0");
|
||||
phaseGroupId = 0;
|
||||
}
|
||||
|
||||
if (phaseId != 0)
|
||||
{
|
||||
if (!CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with `phaseid` {phaseId} does not exist, set to 0");
|
||||
phaseId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (phaseGroupId != 0)
|
||||
{
|
||||
if (Global.DB2Mgr.GetPhasesForGroup(phaseGroupId).Empty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with `phaseGroup` {phaseGroupId} does not exist, set to 0");
|
||||
phaseGroupId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TransportTemplate tInfo = GetTransportTemplate(entry);
|
||||
if (tInfo != null)
|
||||
if (!tInfo.inInstance)
|
||||
if (CreateTransport(entry, guid, null, phaseid, phasegroup))
|
||||
if (CreateTransport(entry, guid, null, phaseUseFlags, phaseId, phaseGroupId))
|
||||
++count;
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
Reference in New Issue
Block a user