Core/Entities: Phasing rewrite
This commit is contained in:
@@ -227,22 +227,22 @@ namespace Game.Collision
|
||||
|
||||
public class DynamicTreeIntersectionCallback : WorkerCallback
|
||||
{
|
||||
public DynamicTreeIntersectionCallback(List<uint> phases)
|
||||
public DynamicTreeIntersectionCallback(PhaseShift phaseShift)
|
||||
{
|
||||
_didHit = false;
|
||||
_phases = phases;
|
||||
_phaseShift = phaseShift;
|
||||
}
|
||||
|
||||
public override bool Invoke(Ray r, IModel obj, ref float distance)
|
||||
{
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phases);
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phaseShift);
|
||||
return _didHit;
|
||||
}
|
||||
|
||||
public bool didHit() { return _didHit; }
|
||||
|
||||
bool _didHit;
|
||||
List<uint> _phases;
|
||||
PhaseShift _phaseShift;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,17 +57,17 @@ namespace Game.Collision
|
||||
impl.update(diff);
|
||||
}
|
||||
|
||||
public bool getIntersectionTime(List<uint> phases, Ray ray, Vector3 endPos, float maxDist)
|
||||
public bool getIntersectionTime(Ray ray, Vector3 endPos, PhaseShift phaseShift, float maxDist)
|
||||
{
|
||||
float distance = maxDist;
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectRay(ray, callback, ref distance, endPos);
|
||||
if (callback.didHit())
|
||||
maxDist = distance;
|
||||
return callback.didHit();
|
||||
}
|
||||
|
||||
public bool getObjectHitPos(List<uint> phases, Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist)
|
||||
public bool getObjectHitPos(Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist, PhaseShift phaseShift)
|
||||
{
|
||||
bool result = false;
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
@@ -82,7 +82,7 @@ namespace Game.Collision
|
||||
Vector3 dir = (endPos - startPos) / maxDist; // direction with length of 1
|
||||
Ray ray = new Ray(startPos, dir);
|
||||
float dist = maxDist;
|
||||
if (getIntersectionTime(phases, ray, endPos, dist))
|
||||
if (getIntersectionTime(ray, endPos, phaseShift, dist))
|
||||
{
|
||||
resultHitPos = startPos + dir * dist;
|
||||
if (modifyDist < 0)
|
||||
@@ -105,7 +105,7 @@ namespace Game.Collision
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(Vector3 startPos, Vector3 endPos, List<uint> phases)
|
||||
public bool isInLineOfSight(Vector3 startPos, Vector3 endPos, PhaseShift phaseShift)
|
||||
{
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
|
||||
@@ -113,17 +113,17 @@ namespace Game.Collision
|
||||
return true;
|
||||
|
||||
Ray r = new Ray(startPos, (endPos - startPos) / maxDist);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectRay(r, callback, ref maxDist, endPos);
|
||||
|
||||
return !callback.didHit();
|
||||
}
|
||||
|
||||
public float getHeight(float x, float y, float z, float maxSearchDist, List<uint> phases)
|
||||
public float getHeight(float x, float y, float z, float maxSearchDist, PhaseShift phaseShift)
|
||||
{
|
||||
Vector3 v = new Vector3(x, y, z + 0.5f);
|
||||
Ray r = new Ray(v, new Vector3(0, 0, -1));
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectZAllignedRay(r, callback, ref maxSearchDist);
|
||||
|
||||
if (callback.didHit())
|
||||
|
||||
@@ -36,23 +36,39 @@ namespace Game.Collision
|
||||
|
||||
public static string VMapPath = Global.WorldMgr.GetDataPath() + "/vmaps/";
|
||||
|
||||
public void Initialize(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
iChildMapData = mapData;
|
||||
foreach (var pair in mapData)
|
||||
iParentMapData[pair.Value] = pair.Key;
|
||||
}
|
||||
|
||||
public VMAPLoadResult loadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var result = VMAPLoadResult.Ignored;
|
||||
if (_loadMap(mapId, x, y))
|
||||
result = VMAPLoadResult.OK;
|
||||
else
|
||||
result = VMAPLoadResult.Error;
|
||||
if (isMapLoadingEnabled())
|
||||
{
|
||||
if (loadSingleMap(mapId, x, y))
|
||||
{
|
||||
result = VMAPLoadResult.OK;
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadSingleMap(childMapId, x, y))
|
||||
result = VMAPLoadResult.Error;
|
||||
}
|
||||
else
|
||||
result = VMAPLoadResult.Error;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool _loadMap(uint mapId, uint tileX, uint tileY)
|
||||
bool loadSingleMap(uint mapId, uint tileX, uint tileY)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree == null)
|
||||
{
|
||||
string filename = string.Format("{0}{1:D4}.vmtree", VMapPath, mapId);
|
||||
string filename = VMapPath + getMapFileName(mapId);
|
||||
StaticMapTree newTree = new StaticMapTree(mapId);
|
||||
if (!newTree.InitMap(filename, this))
|
||||
return false;
|
||||
@@ -65,72 +81,90 @@ namespace Game.Collision
|
||||
return instanceTree.LoadMapTile(tileX, tileY, this);
|
||||
}
|
||||
|
||||
public WorldModel acquireModelInstance(string filename)
|
||||
public void unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadSingleMap(childMapId, x, y);
|
||||
|
||||
unloadSingleMap(mapId, x, y);
|
||||
}
|
||||
|
||||
void unloadSingleMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
WorldModel worldmodel = new WorldModel();
|
||||
if (!worldmodel.readFile(VMapPath + filename + ".vmo"))
|
||||
instanceTree.UnloadMapTile(x, y, this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: could not load '{0}.vmo'", filename);
|
||||
return null;
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
||||
iLoadedModelFiles.Add(filename, new ManagedModel());
|
||||
model = iLoadedModelFiles.LookupByKey(filename);
|
||||
model.setModel(worldmodel);
|
||||
}
|
||||
model.incRefCount();
|
||||
return model.getModel();
|
||||
}
|
||||
|
||||
public void releaseModelInstance(string filename)
|
||||
public void unloadMap(uint mapId)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadSingleMap(childMapId);
|
||||
|
||||
unloadSingleMap(mapId);
|
||||
}
|
||||
|
||||
void unloadSingleMap(uint mapId)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
||||
return;
|
||||
instanceTree.UnloadMap(this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
if (model.decRefCount() == 0)
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
if (!isLineOfSightCalcEnabled() || Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
||||
iLoadedModelFiles.Remove(filename);
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
if (pos1 != pos2)
|
||||
return instanceTree.isInLineOfSight(pos1, pos2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool existsMap(uint mapId, uint x, uint y)
|
||||
public bool getObjectHitPos(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
return StaticMapTree.CanLoadMap(VMapPath, mapId, x, y);
|
||||
}
|
||||
|
||||
public static string getMapFileName(uint mapId)
|
||||
{
|
||||
return string.Format("{0:D4}.vmtree", mapId);
|
||||
}
|
||||
|
||||
public bool GetLiquidLevel(uint mapId, float x, float y, float z, byte reqLiquidType, ref float level, ref float floor, ref uint type)
|
||||
{
|
||||
if (!Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLiquidStatus))
|
||||
if (isLineOfSightCalcEnabled() && !Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
LocationInfo info = new LocationInfo();
|
||||
Vector3 pos = convertPositionToInternalRep(x, y, z);
|
||||
if (instanceTree.GetLocationInfo(pos, info))
|
||||
{
|
||||
floor = info.ground_Z;
|
||||
Contract.Assert(floor < float.MaxValue);
|
||||
type = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc
|
||||
if (reqLiquidType != 0 && !Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(type) & reqLiquidType))
|
||||
return false;
|
||||
if (info.hitInstance.GetLiquidLevel(pos, info, ref level))
|
||||
return true;
|
||||
}
|
||||
Vector3 resultPos;
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
bool result = instanceTree.getObjectHitPos(pos1, pos2, out resultPos, modifyDist);
|
||||
resultPos = convertPositionToInternalRep(resultPos.X, resultPos.Y, resultPos.Z);
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
rz = resultPos.Z;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rx = x2;
|
||||
ry = y2;
|
||||
rz = z2;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -175,6 +209,78 @@ namespace Game.Collision
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetLiquidLevel(uint mapId, float x, float y, float z, byte reqLiquidType, ref float level, ref float floor, ref uint type)
|
||||
{
|
||||
if (!Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLiquidStatus))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
LocationInfo info = new LocationInfo();
|
||||
Vector3 pos = convertPositionToInternalRep(x, y, z);
|
||||
if (instanceTree.GetLocationInfo(pos, info))
|
||||
{
|
||||
floor = info.ground_Z;
|
||||
Contract.Assert(floor < float.MaxValue);
|
||||
type = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc
|
||||
if (reqLiquidType != 0 && !Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(type) & reqLiquidType))
|
||||
return false;
|
||||
if (info.hitInstance.GetLiquidLevel(pos, info, ref level))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public WorldModel acquireModelInstance(string filename)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
{
|
||||
WorldModel worldmodel = new WorldModel();
|
||||
if (!worldmodel.readFile(VMapPath + filename + ".vmo"))
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: could not load '{0}.vmo'", filename);
|
||||
return null;
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
||||
iLoadedModelFiles.Add(filename, new ManagedModel());
|
||||
model = iLoadedModelFiles.LookupByKey(filename);
|
||||
model.setModel(worldmodel);
|
||||
}
|
||||
model.incRefCount();
|
||||
return model.getModel();
|
||||
}
|
||||
|
||||
public void releaseModelInstance(string filename)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
||||
return;
|
||||
}
|
||||
if (model.decRefCount() == 0)
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
||||
iLoadedModelFiles.Remove(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public bool existsMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
return StaticMapTree.CanLoadMap(VMapPath, mapId, x, y, this);
|
||||
}
|
||||
|
||||
public int getParentMapId(uint mapId)
|
||||
{
|
||||
if (iParentMapData.ContainsKey(mapId))
|
||||
return (int)iParentMapData[mapId];
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Vector3 convertPositionToInternalRep(float x, float y, float z)
|
||||
{
|
||||
Vector3 pos = new Vector3();
|
||||
@@ -186,6 +292,11 @@ namespace Game.Collision
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static string getMapFileName(uint mapId)
|
||||
{
|
||||
return string.Format("{0:D4}.vmtree", mapId);
|
||||
}
|
||||
|
||||
public void setEnableLineOfSightCalc(bool pVal) { _enableLineOfSightCalc = pVal; }
|
||||
public void setEnableHeightCalc(bool pVal) { _enableHeightCalc = pVal; }
|
||||
|
||||
@@ -193,79 +304,10 @@ namespace Game.Collision
|
||||
public bool isHeightCalcEnabled() { return _enableHeightCalc; }
|
||||
public bool isMapLoadingEnabled() { return _enableLineOfSightCalc || _enableHeightCalc; }
|
||||
|
||||
public bool getObjectHitPos(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
if (isLineOfSightCalcEnabled() && !Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Vector3 resultPos;
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
bool result = instanceTree.getObjectHitPos(pos1, pos2, out resultPos, modifyDist);
|
||||
resultPos = convertPositionToInternalRep(resultPos.X, resultPos.Y, resultPos.Z);
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
rz = resultPos.Z;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rx = x2;
|
||||
ry = y2;
|
||||
rz = z2;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
if (!isLineOfSightCalcEnabled() || Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
if (pos1 != pos2)
|
||||
{
|
||||
return instanceTree.isInLineOfSight(pos1, pos2);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unloadMap(uint mapId)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
instanceTree.UnloadMap(this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
instanceTree.UnloadMapTile(x, y, this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, ManagedModel> iLoadedModelFiles = new Dictionary<string, ManagedModel>();
|
||||
Dictionary<uint, StaticMapTree> iInstanceMapTrees = new Dictionary<uint, StaticMapTree>();
|
||||
MultiMap<uint, uint> iChildMapData = new MultiMap<uint, uint>();
|
||||
Dictionary<uint, uint> iParentMapData = new Dictionary<uint, uint>();
|
||||
bool _enableLineOfSightCalc;
|
||||
bool _enableHeightCalc;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Game.Collision
|
||||
bool success = false;
|
||||
if (!File.Exists(fname))
|
||||
return false;
|
||||
|
||||
char tiled = '0';
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(fname, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
@@ -99,6 +100,21 @@ namespace Game.Collision
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.InitMap() : could not acquire WorldModel for '{0}'", spawn.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
success = reader.ReadStringFromChars(4) == "SIDX";
|
||||
if (success)
|
||||
{
|
||||
uint spawnIndicesSize = reader.ReadUInt32();
|
||||
for (uint i = 0; i < spawnIndicesSize && success; ++i)
|
||||
{
|
||||
uint spawnId = reader.ReadUInt32();
|
||||
uint spawnIndex = reader.ReadUInt32();
|
||||
iSpawnIndices[spawnId] = spawnIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -131,15 +147,14 @@ namespace Game.Collision
|
||||
}
|
||||
bool result = true;
|
||||
|
||||
string tilefile = VMapManager.VMapPath + getTileFileName(iMapID, tileX, tileY);
|
||||
|
||||
if (!File.Exists(tilefile))
|
||||
FileStream stream = OpenMapTileFile(VMapManager.VMapPath, iMapID, tileX, tileY, vm);
|
||||
if (stream == null)
|
||||
{
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
@@ -159,18 +174,27 @@ namespace Game.Collision
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.LoadMapTile() : could not acquire WorldModel [{0}, {1}]", tileX, tileY);
|
||||
|
||||
// update tree
|
||||
uint referencedVal = reader.ReadUInt32();
|
||||
if (!iLoadedSpawns.ContainsKey(referencedVal))
|
||||
if (iSpawnIndices.ContainsKey(spawn.ID))
|
||||
{
|
||||
iTreeValues[referencedVal] = new ModelInstance(spawn, model);
|
||||
iLoadedSpawns[referencedVal] = 1;
|
||||
uint referencedVal = iSpawnIndices[spawn.ID];
|
||||
if (!iLoadedSpawns.ContainsKey(referencedVal))
|
||||
{
|
||||
if (referencedVal >= iNTreeValues)
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "StaticMapTree.LoadMapTile() : invalid tree element ({0}/{1}) referenced in tile {2}", referencedVal, iNTreeValues, stream.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
iTreeValues[referencedVal] = new ModelInstance(spawn, model);
|
||||
iLoadedSpawns[referencedVal] = 1;
|
||||
}
|
||||
else
|
||||
++iLoadedSpawns[referencedVal];
|
||||
}
|
||||
else
|
||||
++iLoadedSpawns[referencedVal];
|
||||
result = false;
|
||||
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = true;
|
||||
@@ -189,36 +213,42 @@ namespace Game.Collision
|
||||
}
|
||||
if (tile) // file associated with tile
|
||||
{
|
||||
string tilefile = VMapManager.VMapPath + getTileFileName(iMapID, tileX, tileY);
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
FileStream stream = OpenMapTileFile(VMapManager.VMapPath, iMapID, tileX, tileY, vm);
|
||||
if (stream != null)
|
||||
{
|
||||
bool result = true;
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
result = false;
|
||||
|
||||
uint numSpawns = reader.ReadUInt32();
|
||||
for (uint i = 0; i < numSpawns && result; ++i)
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
// read model spawns
|
||||
ModelSpawn spawn;
|
||||
result = ModelSpawn.readFromFile(reader, out spawn);
|
||||
if (result)
|
||||
bool result = true;
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
result = false;
|
||||
|
||||
uint numSpawns = reader.ReadUInt32();
|
||||
for (uint i = 0; i < numSpawns && result; ++i)
|
||||
{
|
||||
// release model instance
|
||||
vm.releaseModelInstance(spawn.name);
|
||||
|
||||
// update tree
|
||||
uint referencedNode = reader.ReadUInt32();
|
||||
|
||||
|
||||
if (!iLoadedSpawns.ContainsKey(referencedNode))
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.UnloadMapTile() : trying to unload non-referenced model '{0}' (ID:{1})", spawn.name, spawn.ID);
|
||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||
// read model spawns
|
||||
ModelSpawn spawn;
|
||||
result = ModelSpawn.readFromFile(reader, out spawn);
|
||||
if (result)
|
||||
{
|
||||
iTreeValues[referencedNode].setUnloaded();
|
||||
iLoadedSpawns.Remove(referencedNode);
|
||||
}
|
||||
// release model instance
|
||||
vm.releaseModelInstance(spawn.name);
|
||||
|
||||
// update tree
|
||||
if (!iSpawnIndices.ContainsKey(spawn.ID))
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
uint referencedNode = iSpawnIndices[spawn.ID];
|
||||
if (!iLoadedSpawns.ContainsKey(referencedNode))
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.UnloadMapTile() : trying to unload non-referenced model '{0}' (ID:{1})", spawn.name, spawn.ID);
|
||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||
{
|
||||
iTreeValues[referencedNode].setUnloaded();
|
||||
iLoadedSpawns.Remove(referencedNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,10 +258,26 @@ namespace Game.Collision
|
||||
|
||||
static uint packTileID(uint tileX, uint tileY) { return tileX << 16 | tileY; }
|
||||
static void unpackTileID(uint ID, ref uint tileX, ref uint tileY) { tileX = ID >> 16; tileY = ID & 0xFF; }
|
||||
public static bool CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY)
|
||||
|
||||
static FileStream OpenMapTileFile(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
{
|
||||
string tilefile = vmapPath + getTileFileName(mapID, tileX, tileY);
|
||||
if (!File.Exists(tilefile))
|
||||
{
|
||||
int parentMapId = vm.getParentMapId(mapID);
|
||||
if (parentMapId != -1)
|
||||
tilefile = vmapPath + getTileFileName((uint)parentMapId, tileX, tileY);
|
||||
}
|
||||
|
||||
if (!File.Exists(tilefile))
|
||||
return null;
|
||||
|
||||
return new FileStream(tilefile, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public static bool CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
{
|
||||
string fullname = vmapPath + VMapManager.getMapFileName(mapID);
|
||||
bool success = true;
|
||||
if (!File.Exists(fullname))
|
||||
return false;
|
||||
|
||||
@@ -239,21 +285,24 @@ namespace Game.Collision
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
|
||||
char tiled = reader.ReadChar();
|
||||
if (tiled == 1)
|
||||
{
|
||||
string tilefile = vmapPath + getTileFileName(mapID, tileX, tileY);
|
||||
if (!File.Exists(tilefile))
|
||||
|
||||
FileStream stream = OpenMapTileFile(vmapPath, mapID, tileX, tileY, vm);
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (BinaryReader reader1 = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader1 = new BinaryReader(stream))
|
||||
{
|
||||
if (reader1.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
success = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static string getTileFileName(uint mapID, uint tileX, uint tileY)
|
||||
{
|
||||
@@ -380,6 +429,7 @@ namespace Game.Collision
|
||||
BIH iTree = new BIH();
|
||||
ModelInstance[] iTreeValues;
|
||||
uint iNTreeValues;
|
||||
Dictionary<uint, uint> iSpawnIndices = new Dictionary<uint, uint>();
|
||||
|
||||
Dictionary<uint, bool> iLoadedTiles = new Dictionary<uint, bool>();
|
||||
Dictionary<uint, uint> iLoadedSpawns = new Dictionary<uint, uint>();
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Game.Collision
|
||||
{
|
||||
public virtual bool IsSpawned() { return false; }
|
||||
public virtual uint GetDisplayId() { return 0; }
|
||||
public virtual bool IsInPhase(List<uint> phases) { return false; }
|
||||
public virtual bool IsInPhase(PhaseShift phaseShift) { return false; }
|
||||
public virtual Vector3 GetPosition() { return Vector3.Zero; }
|
||||
public virtual float GetOrientation() { return 0.0f; }
|
||||
public virtual float GetScale() { return 1.0f; }
|
||||
@@ -86,12 +86,12 @@ namespace Game.Collision
|
||||
return mdl;
|
||||
}
|
||||
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, List<uint> phases)
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift)
|
||||
{
|
||||
if (!isCollisionEnabled() || !owner.IsSpawned())
|
||||
return false;
|
||||
|
||||
if (!owner.IsInPhase(phases))
|
||||
if (!owner.IsInPhase(phaseShift))
|
||||
return false;
|
||||
|
||||
float time = ray.intersectionTime(iBound);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Game.Collision
|
||||
public virtual Vector3 getPosition() { return default(Vector3); }
|
||||
public virtual AxisAlignedBox getBounds() { return default(AxisAlignedBox); }
|
||||
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, List<uint> phases) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user