Core/Maps: Updated vmaps and some cleaups
This commit is contained in:
@@ -61,16 +61,16 @@ namespace Framework.Constants
|
|||||||
public const float MaxHeight = 100000.0f;
|
public const float MaxHeight = 100000.0f;
|
||||||
public const float MaxFallDistance = 250000.0f;
|
public const float MaxFallDistance = 250000.0f;
|
||||||
|
|
||||||
public const string MapMagic = "MAPS";
|
public const uint MapMagic = 0x5350414D; //"MAPS";
|
||||||
public const string MapVersionMagic = "v1.9";
|
public const uint MapVersionMagic = 0x392E3176; //"v1.9";
|
||||||
public const string MapAreaMagic = "AREA";
|
public const uint MapAreaMagic = 0x41455241; //"AREA";
|
||||||
public const string MapHeightMagic = "MHGT";
|
public const uint MapHeightMagic = 0x5447484D; //"MHGT";
|
||||||
public const string MapLiquidMagic = "MLIQ";
|
public const uint MapLiquidMagic = 0x51494C4D; //"MLIQ";
|
||||||
|
|
||||||
public const string mmapMagic = "MMAP";
|
public const uint mmapMagic = 0x4D4D4150; // 'MMAP'
|
||||||
public const int mmapVersion = 9;
|
public const int mmapVersion = 9;
|
||||||
|
|
||||||
public const string VMapMagic = "VMAP_4.7";
|
public const string VMapMagic = "VMAP_4.8";
|
||||||
public const float VMAPInvalidHeightValue = -200000.0f;
|
public const float VMAPInvalidHeightValue = -200000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,27 +294,6 @@ namespace System
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region BinaryReader
|
#region BinaryReader
|
||||||
public static T ReadStruct<T>(this BinaryReader reader) where T : struct
|
|
||||||
{
|
|
||||||
byte[] data = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
|
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
||||||
T returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
|
||||||
|
|
||||||
handle.Free();
|
|
||||||
return returnObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T ReadStruct<T>(this BinaryReader reader, uint offset) where T : struct
|
|
||||||
{
|
|
||||||
reader.BaseStream.Position = offset;
|
|
||||||
byte[] data = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
|
|
||||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
||||||
T returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
|
|
||||||
|
|
||||||
handle.Free();
|
|
||||||
return returnObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ReadCString(this BinaryReader reader)
|
public static string ReadCString(this BinaryReader reader)
|
||||||
{
|
{
|
||||||
byte num;
|
byte num;
|
||||||
@@ -337,9 +316,9 @@ namespace System
|
|||||||
return new string(reader.ReadChars(count));
|
return new string(reader.ReadChars(count));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T[] ReadArray<T>(this BinaryReader reader, int size) where T : struct
|
public static T[] ReadArray<T>(this BinaryReader reader, uint size) where T : struct
|
||||||
{
|
{
|
||||||
int numBytes = FastStruct<T>.Size * size;
|
int numBytes = FastStruct<T>.Size * (int)size;
|
||||||
|
|
||||||
byte[] result = reader.ReadBytes(numBytes);
|
byte[] result = reader.ReadBytes(numBytes);
|
||||||
|
|
||||||
|
|||||||
@@ -276,14 +276,10 @@ namespace Game.Collision
|
|||||||
bounds = new AxisAlignedBox(lo, hi);
|
bounds = new AxisAlignedBox(lo, hi);
|
||||||
|
|
||||||
uint treeSize = reader.ReadUInt32();
|
uint treeSize = reader.ReadUInt32();
|
||||||
tree = new uint[treeSize];
|
tree = reader.ReadArray<uint>(treeSize);
|
||||||
for (var i = 0; i < treeSize; i++)
|
|
||||||
tree[i] = reader.ReadUInt32();
|
|
||||||
|
|
||||||
var count = reader.ReadUInt32();
|
var count = reader.ReadUInt32();
|
||||||
objects = new uint[count];
|
objects = reader.ReadArray<uint>(count);
|
||||||
for (var i = 0; i < count; i++)
|
|
||||||
objects[i] = reader.ReadUInt32();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace Game.Collision
|
|||||||
{
|
{
|
||||||
string filename = VMapPath + getMapFileName(mapId);
|
string filename = VMapPath + getMapFileName(mapId);
|
||||||
StaticMapTree newTree = new StaticMapTree(mapId);
|
StaticMapTree newTree = new StaticMapTree(mapId);
|
||||||
if (!newTree.InitMap(filename, this))
|
if (!newTree.InitMap(filename))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
iInstanceMapTrees.Add(mapId, newTree);
|
iInstanceMapTrees.Add(mapId, newTree);
|
||||||
@@ -235,36 +235,42 @@ namespace Game.Collision
|
|||||||
|
|
||||||
public WorldModel acquireModelInstance(string filename)
|
public WorldModel acquireModelInstance(string filename)
|
||||||
{
|
{
|
||||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
lock (LoadedModelFilesLock)
|
||||||
if (model == null)
|
|
||||||
{
|
{
|
||||||
WorldModel worldmodel = new WorldModel();
|
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||||
if (!worldmodel.readFile(VMapPath + filename + ".vmo"))
|
if (model == null)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Server, "VMapManager: could not load '{0}.vmo'", filename);
|
WorldModel worldmodel = new WorldModel();
|
||||||
return null;
|
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);
|
||||||
}
|
}
|
||||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
model.incRefCount();
|
||||||
iLoadedModelFiles.Add(filename, new ManagedModel());
|
return model.getModel();
|
||||||
model = iLoadedModelFiles.LookupByKey(filename);
|
|
||||||
model.setModel(worldmodel);
|
|
||||||
}
|
}
|
||||||
model.incRefCount();
|
|
||||||
return model.getModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseModelInstance(string filename)
|
public void releaseModelInstance(string filename)
|
||||||
{
|
{
|
||||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
lock (LoadedModelFilesLock)
|
||||||
if (model == null)
|
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||||
return;
|
if (model == null)
|
||||||
}
|
{
|
||||||
if (model.decRefCount() == 0)
|
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
||||||
{
|
return;
|
||||||
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
}
|
||||||
iLoadedModelFiles.Remove(filename);
|
if (model.decRefCount() == 0)
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
||||||
|
iLoadedModelFiles.Remove(filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,6 +316,8 @@ namespace Game.Collision
|
|||||||
Dictionary<uint, uint> iParentMapData = new Dictionary<uint, uint>();
|
Dictionary<uint, uint> iParentMapData = new Dictionary<uint, uint>();
|
||||||
bool _enableLineOfSightCalc;
|
bool _enableLineOfSightCalc;
|
||||||
bool _enableHeightCalc;
|
bool _enableHeightCalc;
|
||||||
|
|
||||||
|
object LoadedModelFilesLock = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ManagedModel
|
public class ManagedModel
|
||||||
|
|||||||
@@ -58,47 +58,23 @@ namespace Game.Collision
|
|||||||
iMapID = mapId;
|
iMapID = mapId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool InitMap(string fname, VMapManager vm)
|
public bool InitMap(string fname)
|
||||||
{
|
{
|
||||||
Log.outDebug(LogFilter.Maps, "StaticMapTree.InitMap() : initializing StaticMapTree '{0}'", fname);
|
Log.outDebug(LogFilter.Maps, "StaticMapTree.InitMap() : initializing StaticMapTree '{0}'", fname);
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (!File.Exists(fname))
|
if (!File.Exists(fname))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char tiled = '0';
|
|
||||||
using (BinaryReader reader = new BinaryReader(new FileStream(fname, FileMode.Open, FileAccess.Read)))
|
using (BinaryReader reader = new BinaryReader(new FileStream(fname, FileMode.Open, FileAccess.Read)))
|
||||||
{
|
{
|
||||||
var magic = reader.ReadStringFromChars(8);
|
var magic = reader.ReadStringFromChars(8);
|
||||||
tiled = reader.ReadChar();
|
|
||||||
var node = reader.ReadStringFromChars(4);
|
var node = reader.ReadStringFromChars(4);
|
||||||
|
|
||||||
if (magic == MapConst.VMapMagic && node == "NODE" && iTree.readFromFile(reader))
|
if (magic == MapConst.VMapMagic && node == "NODE" && iTree.readFromFile(reader))
|
||||||
{
|
{
|
||||||
iNTreeValues = iTree.primCount();
|
iNTreeValues = iTree.primCount();
|
||||||
iTreeValues = new ModelInstance[iNTreeValues];
|
iTreeValues = new ModelInstance[iNTreeValues];
|
||||||
success = reader.ReadStringFromChars(4) == "GOBJ";
|
success = true;
|
||||||
}
|
|
||||||
|
|
||||||
iIsTiled = (tiled == 1);
|
|
||||||
|
|
||||||
// global model spawns
|
|
||||||
// only non-tiled maps have them, and if so exactly one (so far at least...)
|
|
||||||
ModelSpawn spawn;
|
|
||||||
if (!iIsTiled && ModelSpawn.readFromFile(reader, out spawn))
|
|
||||||
{
|
|
||||||
WorldModel model = vm.acquireModelInstance(spawn.name);
|
|
||||||
Log.outDebug(LogFilter.Maps, "StaticMapTree.InitMap() : loading {0}", spawn.name);
|
|
||||||
if (model != null)
|
|
||||||
{
|
|
||||||
// assume that global model always is the first and only tree value (could be improved...)
|
|
||||||
iTreeValues[0] = new ModelInstance(spawn, model);
|
|
||||||
iLoadedSpawns[0] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
Log.outError(LogFilter.Server, "StaticMapTree.InitMap() : could not acquire WorldModel for '{0}'", spawn.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
@@ -107,7 +83,7 @@ namespace Game.Collision
|
|||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
uint spawnIndicesSize = reader.ReadUInt32();
|
uint spawnIndicesSize = reader.ReadUInt32();
|
||||||
for (uint i = 0; i < spawnIndicesSize && success; ++i)
|
for (uint i = 0; i < spawnIndicesSize; ++i)
|
||||||
{
|
{
|
||||||
uint spawnId = reader.ReadUInt32();
|
uint spawnId = reader.ReadUInt32();
|
||||||
uint spawnIndex = reader.ReadUInt32();
|
uint spawnIndex = reader.ReadUInt32();
|
||||||
@@ -133,13 +109,6 @@ namespace Game.Collision
|
|||||||
|
|
||||||
public bool LoadMapTile(uint tileX, uint tileY, VMapManager vm)
|
public bool LoadMapTile(uint tileX, uint tileY, VMapManager vm)
|
||||||
{
|
{
|
||||||
if (!iIsTiled)
|
|
||||||
{
|
|
||||||
// currently, core creates grids for all maps, whether it has terrain tiles or not
|
|
||||||
// so we need "fake" tile loads to know when we can unload map geometry
|
|
||||||
iLoadedTiles[packTileID(tileX, tileY)] = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (iTreeValues == null)
|
if (iTreeValues == null)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Server, "StaticMapTree.LoadMapTile() : tree has not been initialized [{0}, {1}]", tileX, tileY);
|
Log.outError(LogFilter.Server, "StaticMapTree.LoadMapTile() : tree has not been initialized [{0}, {1}]", tileX, tileY);
|
||||||
@@ -285,25 +254,21 @@ namespace Game.Collision
|
|||||||
{
|
{
|
||||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char tiled = reader.ReadChar();
|
FileStream stream = OpenMapTileFile(vmapPath, mapID, tileX, tileY, vm);
|
||||||
if (tiled == 1)
|
if (stream == null)
|
||||||
{
|
return false;
|
||||||
|
|
||||||
FileStream stream = OpenMapTileFile(vmapPath, mapID, tileX, tileY, vm);
|
using (BinaryReader reader = new BinaryReader(stream))
|
||||||
if (stream == null)
|
{
|
||||||
return false;
|
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||||
|
return false;
|
||||||
using (BinaryReader reader1 = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
if (reader1.ReadStringFromChars(8) != MapConst.VMapMagic)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string getTileFileName(uint mapID, uint tileX, uint tileY)
|
public static string getTileFileName(uint mapID, uint tileX, uint tileY)
|
||||||
{
|
{
|
||||||
return string.Format("{0:D4}_{1:D2}_{2:D2}.vmtile", mapID, tileY, tileX);
|
return string.Format("{0:D4}_{1:D2}_{2:D2}.vmtile", mapID, tileY, tileX);
|
||||||
@@ -425,7 +390,6 @@ namespace Game.Collision
|
|||||||
public int numLoadedTiles() { return iLoadedTiles.Count; }
|
public int numLoadedTiles() { return iLoadedTiles.Count; }
|
||||||
|
|
||||||
uint iMapID;
|
uint iMapID;
|
||||||
bool iIsTiled;
|
|
||||||
BIH iTree = new BIH();
|
BIH iTree = new BIH();
|
||||||
ModelInstance[] iTreeValues;
|
ModelInstance[] iTreeValues;
|
||||||
uint iNTreeValues;
|
uint iNTreeValues;
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ namespace Game.Collision
|
|||||||
public enum ModelFlags
|
public enum ModelFlags
|
||||||
{
|
{
|
||||||
M2 = 1,
|
M2 = 1,
|
||||||
WorldSpawn = 1 << 1,
|
HasBound = 1 << 1,
|
||||||
HasBound = 1 << 2
|
ParentSpawn = 1 << 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ModelSpawn
|
public class ModelSpawn
|
||||||
|
|||||||
@@ -139,14 +139,10 @@ namespace Game.Collision
|
|||||||
if (liquid.iTilesX != 0 && liquid.iTilesY != 0)
|
if (liquid.iTilesX != 0 && liquid.iTilesY != 0)
|
||||||
{
|
{
|
||||||
uint size = (liquid.iTilesX + 1) * (liquid.iTilesY + 1);
|
uint size = (liquid.iTilesX + 1) * (liquid.iTilesY + 1);
|
||||||
liquid.iHeight = new float[size];
|
liquid.iHeight = reader.ReadArray<float>(size);
|
||||||
for (var i = 0; i < size; i++)
|
|
||||||
liquid.iHeight[i] = reader.ReadSingle();
|
|
||||||
|
|
||||||
size = liquid.iTilesX * liquid.iTilesY;
|
size = liquid.iTilesX * liquid.iTilesY;
|
||||||
liquid.iFlags = new byte[size];
|
liquid.iFlags = reader.ReadArray<byte>(size);
|
||||||
for (var i = 0; i < size; i++)
|
|
||||||
liquid.iFlags[i] = reader.ReadByte();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -210,7 +206,9 @@ namespace Game.Collision
|
|||||||
vertices.Clear();
|
vertices.Clear();
|
||||||
iLiquid = null;
|
iLiquid = null;
|
||||||
|
|
||||||
iBound = reader.ReadStruct<AxisAlignedBox>();
|
var lo = reader.Read<Vector3>();
|
||||||
|
var hi = reader.Read<Vector3>();
|
||||||
|
iBound = new AxisAlignedBox(lo, hi);
|
||||||
iMogpFlags = reader.ReadUInt32();
|
iMogpFlags = reader.ReadUInt32();
|
||||||
iGroupWMOID = reader.ReadUInt32();
|
iGroupWMOID = reader.ReadUInt32();
|
||||||
|
|
||||||
@@ -234,7 +232,7 @@ namespace Game.Collision
|
|||||||
count = reader.ReadUInt32();
|
count = reader.ReadUInt32();
|
||||||
|
|
||||||
for (var i = 0; i < count; ++i)
|
for (var i = 0; i < count; ++i)
|
||||||
triangles.Add(reader.ReadStruct<MeshTriangle>());
|
triangles.Add(reader.Read<MeshTriangle>());
|
||||||
|
|
||||||
// read mesh BIH
|
// read mesh BIH
|
||||||
if (reader.ReadStringFromChars(4) != "MBIH")
|
if (reader.ReadStringFromChars(4) != "MBIH")
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Game.DataStorage
|
|||||||
if (fieldInfo.IsArray)
|
if (fieldInfo.IsArray)
|
||||||
{
|
{
|
||||||
Array array = (Array)fieldInfo.Getter(obj);
|
Array array = (Array)fieldInfo.Getter(obj);
|
||||||
SetArrayValue(obj, array.Length, fieldInfo, dataReader);
|
SetArrayValue(obj, (uint)array.Length, fieldInfo, dataReader);
|
||||||
|
|
||||||
arrayLength -= array.Length;
|
arrayLength -= array.Length;
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ namespace Game.DataStorage
|
|||||||
if (fieldInfo.IsArray)
|
if (fieldInfo.IsArray)
|
||||||
{
|
{
|
||||||
Array array = (Array)fieldInfo.Getter(obj);
|
Array array = (Array)fieldInfo.Getter(obj);
|
||||||
SetArrayValue(obj, array.Length, fieldInfo, dataReader);
|
SetArrayValue(obj, (uint)array.Length, fieldInfo, dataReader);
|
||||||
|
|
||||||
dataFieldIndex += array.Length - 1;
|
dataFieldIndex += array.Length - 1;
|
||||||
}
|
}
|
||||||
@@ -258,11 +258,7 @@ namespace Game.DataStorage
|
|||||||
|
|
||||||
// IndexTable
|
// IndexTable
|
||||||
if (Header.HasIndexTable())
|
if (Header.HasIndexTable())
|
||||||
{
|
m_indexes = reader.ReadArray<int>(Header.RecordCount);
|
||||||
m_indexes = new int[Header.RecordCount];
|
|
||||||
for (int i = 0; i < Header.RecordCount; i++)
|
|
||||||
m_indexes[i] = reader.ReadInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copytable
|
// Copytable
|
||||||
if (Header.CopyTableSize > 0)
|
if (Header.CopyTableSize > 0)
|
||||||
@@ -508,7 +504,7 @@ namespace Game.DataStorage
|
|||||||
return bits.ToArray();
|
return bits.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetArrayValue(object obj, int arraySize, DB6FieldInfo fieldInfo, BinaryReader reader)
|
static void SetArrayValue(object obj, uint arraySize, DB6FieldInfo fieldInfo, BinaryReader reader)
|
||||||
{
|
{
|
||||||
switch (Type.GetTypeCode(fieldInfo.FieldType))
|
switch (Type.GetTypeCode(fieldInfo.FieldType))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ namespace Game.DataStorage
|
|||||||
for (uint k = 0; k < cam.target_positions.timestamps.number; ++k)
|
for (uint k = 0; k < cam.target_positions.timestamps.number; ++k)
|
||||||
{
|
{
|
||||||
// Extract Target positions
|
// Extract Target positions
|
||||||
M2Array targTsArray = new M2Array(reader, cam.target_positions.timestamps.offset_elements);
|
reader.BaseStream.Position = cam.target_positions.timestamps.offset_elements;
|
||||||
|
M2Array targTsArray = reader.Read<M2Array>();
|
||||||
|
|
||||||
reader.BaseStream.Position = targTsArray.offset_elements;
|
reader.BaseStream.Position = targTsArray.offset_elements;
|
||||||
uint[] targTimestamps = new uint[targTsArray.number];
|
uint[] targTimestamps = reader.ReadArray<uint>(targTsArray.number);
|
||||||
for (var i = 0; i < targTsArray.number; ++i)
|
|
||||||
targTimestamps[i] = reader.ReadUInt32();
|
|
||||||
|
|
||||||
M2Array targArray = new M2Array(reader, cam.target_positions.values.offset_elements);
|
reader.BaseStream.Position = cam.target_positions.values.offset_elements;
|
||||||
|
M2Array targArray = reader.Read<M2Array>();
|
||||||
|
|
||||||
reader.BaseStream.Position = targArray.offset_elements;
|
reader.BaseStream.Position = targArray.offset_elements;
|
||||||
M2SplineKey[] targPositions = new M2SplineKey[targArray.number];
|
M2SplineKey[] targPositions = new M2SplineKey[targArray.number];
|
||||||
@@ -90,14 +90,14 @@ namespace Game.DataStorage
|
|||||||
for (uint k = 0; k < cam.positions.timestamps.number; ++k)
|
for (uint k = 0; k < cam.positions.timestamps.number; ++k)
|
||||||
{
|
{
|
||||||
// Extract Camera positions for this set
|
// Extract Camera positions for this set
|
||||||
M2Array posTsArray = reader.ReadStruct<M2Array>(cam.positions.timestamps.offset_elements);
|
reader.BaseStream.Position = cam.positions.timestamps.offset_elements;
|
||||||
|
M2Array posTsArray = reader.Read<M2Array>();
|
||||||
|
|
||||||
reader.BaseStream.Position = posTsArray.offset_elements;
|
reader.BaseStream.Position = posTsArray.offset_elements;
|
||||||
uint[] posTimestamps = new uint[posTsArray.number];
|
uint[] posTimestamps = reader.ReadArray<uint>(posTsArray.number);
|
||||||
for (var i = 0; i < posTsArray.number; ++i)
|
|
||||||
posTimestamps[i] = reader.ReadUInt32();
|
|
||||||
|
|
||||||
M2Array posArray = new M2Array(reader, cam.positions.values.offset_elements);
|
reader.BaseStream.Position = cam.positions.values.offset_elements;
|
||||||
|
M2Array posArray = reader.Read<M2Array>();
|
||||||
|
|
||||||
reader.BaseStream.Position = posArray.offset_elements;
|
reader.BaseStream.Position = posArray.offset_elements;
|
||||||
M2SplineKey[] positions = new M2SplineKey[posTsArray.number];
|
M2SplineKey[] positions = new M2SplineKey[posTsArray.number];
|
||||||
@@ -181,7 +181,7 @@ namespace Game.DataStorage
|
|||||||
using (BinaryReader m2file = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
using (BinaryReader m2file = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||||
{
|
{
|
||||||
// Check file has correct magic (MD21)
|
// Check file has correct magic (MD21)
|
||||||
if (m2file.ReadStringFromChars(4) != "MD21")
|
if (m2file.ReadUInt32() != 0x3132444D) //"MD21"
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.ServerLoading, "Camera file {0} is damaged. File identifier not found.", filename);
|
Log.outError(LogFilter.ServerLoading, "Camera file {0} is damaged. File identifier not found.", filename);
|
||||||
continue;
|
continue;
|
||||||
@@ -190,10 +190,11 @@ namespace Game.DataStorage
|
|||||||
var unknownSize = m2file.ReadUInt32(); //unknown size
|
var unknownSize = m2file.ReadUInt32(); //unknown size
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
M2Header header = m2file.ReadStruct<M2Header>();
|
M2Header header = m2file.Read<M2Header>();
|
||||||
|
|
||||||
// Get camera(s) - Main header, then dump them.
|
// Get camera(s) - Main header, then dump them.
|
||||||
M2Camera cam = m2file.ReadStruct<M2Camera>(8 + header.ofsCameras);
|
m2file.BaseStream.Position = 8 + header.ofsCameras;
|
||||||
|
M2Camera cam = m2file.Read<M2Camera>();
|
||||||
|
|
||||||
m2file.BaseStream.Position = 8;
|
m2file.BaseStream.Position = 8;
|
||||||
readCamera(cam, new BinaryReader(new MemoryStream(m2file.ReadBytes((int)m2file.BaseStream.Length - 8))), cameraEntry);
|
readCamera(cam, new BinaryReader(new MemoryStream(m2file.ReadBytes((int)m2file.BaseStream.Length - 8))), cameraEntry);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
using Framework.GameMath;
|
using Framework.GameMath;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Game.DataStorage
|
namespace Game.DataStorage
|
||||||
{
|
{
|
||||||
@@ -37,8 +36,7 @@ namespace Game.DataStorage
|
|||||||
|
|
||||||
public struct M2Header
|
public struct M2Header
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
public uint Magic; // "MD20"
|
||||||
public char[] Magic; // "MD20"
|
|
||||||
public uint Version; // The version of the format.
|
public uint Version; // The version of the format.
|
||||||
public uint lName; // Length of the model's name including the trailing \0
|
public uint lName; // Length of the model's name including the trailing \0
|
||||||
public uint ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
|
public uint ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
|
||||||
@@ -110,15 +108,6 @@ namespace Game.DataStorage
|
|||||||
|
|
||||||
public struct M2Array
|
public struct M2Array
|
||||||
{
|
{
|
||||||
public M2Array(BinaryReader reader, uint offset)
|
|
||||||
{
|
|
||||||
if (offset != 0)
|
|
||||||
reader.BaseStream.Position = offset;
|
|
||||||
|
|
||||||
number = reader.ReadUInt32();
|
|
||||||
offset_elements = reader.ReadUInt32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint number;
|
public uint number;
|
||||||
public uint offset_elements;
|
public uint offset_elements;
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-62
@@ -46,22 +46,33 @@ namespace Game.Maps
|
|||||||
_fileExists = true;
|
_fileExists = true;
|
||||||
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||||
{
|
{
|
||||||
mapFileHeader header = reader.ReadStruct<mapFileHeader>();
|
mapFileHeader header = reader.Read<mapFileHeader>();
|
||||||
if (new string(header.mapMagic) != MapConst.MapMagic || new string(header.versionMagic) != MapConst.MapVersionMagic)
|
if (header.mapMagic != MapConst.MapMagic || header.versionMagic != MapConst.MapVersionMagic)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "Map file '{0}' is from an incompatible map version. Please recreate using the mapextractor.", filename);
|
Log.outError(LogFilter.Maps, $"Map file '{filename}' is from an incompatible map version. Please recreate using the mapextractor.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (header.areaMapOffset != 0)
|
|
||||||
LoadAreaData(reader, header.areaMapOffset);
|
|
||||||
|
|
||||||
if (header.heightMapOffset != 0)
|
if (header.areaMapOffset != 0 && !LoadAreaData(reader, header.areaMapOffset))
|
||||||
LoadHeightData(reader, header.heightMapOffset);
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "Error loading map area data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (header.liquidMapOffset != 0)
|
if (header.heightMapOffset != 0 && !LoadHeightData(reader, header.heightMapOffset))
|
||||||
LoadLiquidData(reader, header.liquidMapOffset);
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "Error loading map height data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.liquidMapOffset != 0 && !LoadLiquidData(reader, header.liquidMapOffset))
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "Error loading map liquids data");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unloadData()
|
public void unloadData()
|
||||||
@@ -76,25 +87,28 @@ namespace Game.Maps
|
|||||||
_fileExists = false;
|
_fileExists = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadAreaData(BinaryReader reader, uint offset)
|
bool LoadAreaData(BinaryReader reader, uint offset)
|
||||||
{
|
{
|
||||||
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||||
map_AreaHeader areaHeader = reader.ReadStruct<map_AreaHeader>();
|
map_AreaHeader areaHeader = reader.Read<map_AreaHeader>();
|
||||||
|
if (areaHeader.fourcc != MapConst.MapAreaMagic)
|
||||||
|
return false;
|
||||||
|
|
||||||
_gridArea = areaHeader.gridArea;
|
_gridArea = areaHeader.gridArea;
|
||||||
|
|
||||||
if (!areaHeader.flags.HasAnyFlag(AreaHeaderFlags.NoArea))
|
if (!areaHeader.flags.HasAnyFlag(AreaHeaderFlags.NoArea))
|
||||||
{
|
_areaMap = reader.ReadArray<ushort>(16 * 16);
|
||||||
_areaMap = new ushort[16 * 16];
|
|
||||||
for (var i = 0; i < _areaMap.Length; ++i)
|
return true;
|
||||||
_areaMap[i] = reader.ReadUInt16();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadHeightData(BinaryReader reader, uint offset)
|
bool LoadHeightData(BinaryReader reader, uint offset)
|
||||||
{
|
{
|
||||||
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||||
map_HeightHeader mapHeader = reader.ReadStruct<map_HeightHeader>();
|
map_HeightHeader mapHeader = reader.Read<map_HeightHeader>();
|
||||||
|
|
||||||
|
if (mapHeader.fourcc != MapConst.MapHeightMagic)
|
||||||
|
return false;
|
||||||
|
|
||||||
_gridHeight = mapHeader.gridHeight;
|
_gridHeight = mapHeader.gridHeight;
|
||||||
_flags = (uint)mapHeader.flags;
|
_flags = (uint)mapHeader.flags;
|
||||||
@@ -103,13 +117,8 @@ namespace Game.Maps
|
|||||||
{
|
{
|
||||||
if (mapHeader.flags.HasAnyFlag(HeightHeaderFlags.HeightAsInt16))
|
if (mapHeader.flags.HasAnyFlag(HeightHeaderFlags.HeightAsInt16))
|
||||||
{
|
{
|
||||||
m_uint16_V9 = new ushort[129 * 129];
|
m_uint16_V9 = reader.ReadArray<ushort>(129 * 129);
|
||||||
for (var i = 0; i < m_uint16_V9.Length; ++i)
|
m_uint16_V8 = reader.ReadArray<ushort>(128 * 128);
|
||||||
m_uint16_V9[i] = reader.ReadUInt16();
|
|
||||||
|
|
||||||
m_uint16_V8 = new ushort[128 * 128];
|
|
||||||
for (var i = 0; i < m_uint16_V8.Length; ++i)
|
|
||||||
m_uint16_V8[i] = reader.ReadUInt16();
|
|
||||||
|
|
||||||
_gridIntHeightMultiplier = (mapHeader.gridMaxHeight - mapHeader.gridHeight) / 65535;
|
_gridIntHeightMultiplier = (mapHeader.gridMaxHeight - mapHeader.gridHeight) / 65535;
|
||||||
_gridGetHeight = getHeightFromUint16;
|
_gridGetHeight = getHeightFromUint16;
|
||||||
@@ -123,13 +132,8 @@ namespace Game.Maps
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_V9 = new float[129 * 129];
|
m_V9 = reader.ReadArray<float>(129 * 129);
|
||||||
for (var i = 0; i < m_V9.Length; ++i)
|
m_V8 = reader.ReadArray<float>(128 * 128);
|
||||||
m_V9[i] = reader.ReadSingle();
|
|
||||||
|
|
||||||
m_V8 = new float[128 * 128];
|
|
||||||
for (var i = 0; i < m_V8.Length; ++i)
|
|
||||||
m_V8[i] = reader.ReadSingle();
|
|
||||||
|
|
||||||
_gridGetHeight = getHeightFromFloat;
|
_gridGetHeight = getHeightFromFloat;
|
||||||
}
|
}
|
||||||
@@ -139,13 +143,8 @@ namespace Game.Maps
|
|||||||
|
|
||||||
if (mapHeader.flags.HasAnyFlag(HeightHeaderFlags.HeightHasFlightBounds))
|
if (mapHeader.flags.HasAnyFlag(HeightHeaderFlags.HeightHasFlightBounds))
|
||||||
{
|
{
|
||||||
short[] maxHeights = new short[3 * 3];
|
short[] maxHeights = reader.ReadArray<short>(3 * 3);
|
||||||
short[] minHeights = new short[3 * 3];
|
short[] minHeights = reader.ReadArray<short>(3 * 3);
|
||||||
for (var i = 0; i < maxHeights.Length; ++i)
|
|
||||||
maxHeights[i] = reader.ReadInt16();
|
|
||||||
|
|
||||||
for (var i = 0; i < minHeights.Length; ++i)
|
|
||||||
minHeights[i] = reader.ReadInt16();
|
|
||||||
|
|
||||||
uint[][] indices =
|
uint[][] indices =
|
||||||
{
|
{
|
||||||
@@ -180,15 +179,20 @@ namespace Game.Maps
|
|||||||
new Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]])
|
new Vector3(boundGridCoords[indices[quarterIndex][2]][0], boundGridCoords[indices[quarterIndex][2]][1], minHeights[indices[quarterIndex][2]])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadLiquidData(BinaryReader reader, uint offset)
|
bool LoadLiquidData(BinaryReader reader, uint offset)
|
||||||
{
|
{
|
||||||
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
reader.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||||
map_LiquidHeader liquidHeader = reader.ReadStruct<map_LiquidHeader>();
|
map_LiquidHeader liquidHeader = reader.Read<map_LiquidHeader>();
|
||||||
|
|
||||||
|
if (liquidHeader.fourcc != MapConst.MapLiquidMagic)
|
||||||
|
return false;
|
||||||
|
|
||||||
_liquidGlobalEntry = liquidHeader.liquidType;
|
_liquidGlobalEntry = liquidHeader.liquidType;
|
||||||
_liquidGlobalFlags = (byte)liquidHeader.liquidFlags;
|
_liquidGlobalFlags = liquidHeader.liquidFlags;
|
||||||
_liquidOffX = liquidHeader.offsetX;
|
_liquidOffX = liquidHeader.offsetX;
|
||||||
_liquidOffY = liquidHeader.offsetY;
|
_liquidOffY = liquidHeader.offsetY;
|
||||||
_liquidWidth = liquidHeader.width;
|
_liquidWidth = liquidHeader.width;
|
||||||
@@ -197,19 +201,14 @@ namespace Game.Maps
|
|||||||
|
|
||||||
if (!liquidHeader.flags.HasAnyFlag(LiquidHeaderFlags.LiquidNoType))
|
if (!liquidHeader.flags.HasAnyFlag(LiquidHeaderFlags.LiquidNoType))
|
||||||
{
|
{
|
||||||
_liquidEntry = new ushort[16 * 16];
|
_liquidEntry = reader.ReadArray<ushort>(16 * 16);
|
||||||
for (var i = 0; i < _liquidEntry.Length; ++i)
|
|
||||||
_liquidEntry[i] = reader.ReadUInt16();
|
|
||||||
|
|
||||||
_liquidFlags = reader.ReadBytes(16 * 16);
|
_liquidFlags = reader.ReadBytes(16 * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!liquidHeader.flags.HasAnyFlag(LiquidHeaderFlags.LiquidNoHeight))
|
if (!liquidHeader.flags.HasAnyFlag(LiquidHeaderFlags.LiquidNoHeight))
|
||||||
{
|
_liquidMap = reader.ReadArray<float>((uint)(_liquidWidth * _liquidHeight));
|
||||||
_liquidMap = new float[_liquidWidth * _liquidHeight];
|
|
||||||
for (var i = 0; i < _liquidMap.Length; ++i)
|
return true;
|
||||||
_liquidMap[i] = reader.ReadSingle();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort getArea(float x, float y)
|
public ushort getArea(float x, float y)
|
||||||
@@ -636,14 +635,10 @@ namespace Game.Maps
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct mapFileHeader
|
public struct mapFileHeader
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
public uint mapMagic;
|
||||||
public char[] mapMagic;
|
public uint versionMagic;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
|
||||||
public char[] versionMagic;
|
|
||||||
public uint buildMagic;
|
public uint buildMagic;
|
||||||
public uint areaMapOffset;
|
public uint areaMapOffset;
|
||||||
public uint areaMapSize;
|
public uint areaMapSize;
|
||||||
@@ -655,7 +650,6 @@ namespace Game.Maps
|
|||||||
public uint holesSize;
|
public uint holesSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct map_AreaHeader
|
public struct map_AreaHeader
|
||||||
{
|
{
|
||||||
public uint fourcc;
|
public uint fourcc;
|
||||||
@@ -663,7 +657,6 @@ namespace Game.Maps
|
|||||||
public ushort gridArea;
|
public ushort gridArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct map_HeightHeader
|
public struct map_HeightHeader
|
||||||
{
|
{
|
||||||
public uint fourcc;
|
public uint fourcc;
|
||||||
@@ -672,7 +665,6 @@ namespace Game.Maps
|
|||||||
public float gridMaxHeight;
|
public float gridMaxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct map_LiquidHeader
|
public struct map_LiquidHeader
|
||||||
{
|
{
|
||||||
public uint fourcc;
|
public uint fourcc;
|
||||||
@@ -686,7 +678,6 @@ namespace Game.Maps
|
|||||||
public float liquidLevel;
|
public float liquidLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public class LiquidData
|
public class LiquidData
|
||||||
{
|
{
|
||||||
public uint type_flags;
|
public uint type_flags;
|
||||||
|
|||||||
@@ -178,64 +178,73 @@ namespace Game.Maps
|
|||||||
|
|
||||||
InstanceMap CreateInstance(uint InstanceId, InstanceSave save, Difficulty difficulty, int teamId)
|
InstanceMap CreateInstance(uint InstanceId, InstanceSave save, Difficulty difficulty, int teamId)
|
||||||
{
|
{
|
||||||
// make sure we have a valid map id
|
lock (_mapLock)
|
||||||
MapRecord entry = CliDB.MapStorage.LookupByKey(GetId());
|
|
||||||
if (entry == null)
|
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "CreateInstance: no record for map {0}", GetId());
|
// make sure we have a valid map id
|
||||||
Contract.Assert(false);
|
MapRecord entry = CliDB.MapStorage.LookupByKey(GetId());
|
||||||
|
if (entry == null)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "CreateInstance: no record for map {0}", GetId());
|
||||||
|
Contract.Assert(false);
|
||||||
|
}
|
||||||
|
InstanceTemplate iTemplate = Global.ObjectMgr.GetInstanceTemplate(GetId());
|
||||||
|
if (iTemplate == null)
|
||||||
|
{
|
||||||
|
Log.outError(LogFilter.Maps, "CreateInstance: no instance template for map {0}", GetId());
|
||||||
|
Contract.Assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// some instances only have one difficulty
|
||||||
|
Global.DB2Mgr.GetDownscaledMapDifficultyData(GetId(), ref difficulty);
|
||||||
|
|
||||||
|
Log.outDebug(LogFilter.Maps, "MapInstanced.CreateInstance: {0} map instance {1} for {2} created with difficulty {3}", save != null ? "" : "new ", InstanceId, GetId(), difficulty);
|
||||||
|
|
||||||
|
InstanceMap map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
|
||||||
|
Contract.Assert(map.IsDungeon());
|
||||||
|
|
||||||
|
map.LoadRespawnTimes();
|
||||||
|
map.LoadCorpseData();
|
||||||
|
|
||||||
|
bool load_data = save != null;
|
||||||
|
map.CreateInstanceData(load_data);
|
||||||
|
InstanceScenario instanceScenario = Global.ScenarioMgr.CreateInstanceScenario(map, teamId);
|
||||||
|
if (instanceScenario != null)
|
||||||
|
map.SetInstanceScenario(instanceScenario);
|
||||||
|
|
||||||
|
if (WorldConfig.GetBoolValue(WorldCfg.InstancemapLoadGrids))
|
||||||
|
map.LoadAllCells();
|
||||||
|
|
||||||
|
m_InstancedMaps[InstanceId] = map;
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
InstanceTemplate iTemplate = Global.ObjectMgr.GetInstanceTemplate(GetId());
|
|
||||||
if (iTemplate == null)
|
|
||||||
{
|
|
||||||
Log.outError(LogFilter.Maps, "CreateInstance: no instance template for map {0}", GetId());
|
|
||||||
Contract.Assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// some instances only have one difficulty
|
|
||||||
Global.DB2Mgr.GetDownscaledMapDifficultyData(GetId(), ref difficulty);
|
|
||||||
|
|
||||||
Log.outDebug(LogFilter.Maps, "MapInstanced.CreateInstance: {0} map instance {1} for {2} created with difficulty {3}", save != null ? "" : "new ", InstanceId, GetId(), difficulty);
|
|
||||||
|
|
||||||
InstanceMap map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
|
|
||||||
Contract.Assert(map.IsDungeon());
|
|
||||||
|
|
||||||
map.LoadRespawnTimes();
|
|
||||||
map.LoadCorpseData();
|
|
||||||
|
|
||||||
bool load_data = save != null;
|
|
||||||
map.CreateInstanceData(load_data);
|
|
||||||
InstanceScenario instanceScenario = Global.ScenarioMgr.CreateInstanceScenario(map, teamId);
|
|
||||||
if (instanceScenario != null)
|
|
||||||
map.SetInstanceScenario(instanceScenario);
|
|
||||||
|
|
||||||
if (WorldConfig.GetBoolValue(WorldCfg.InstancemapLoadGrids))
|
|
||||||
map.LoadAllCells();
|
|
||||||
|
|
||||||
m_InstancedMaps[InstanceId] = map;
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BattlegroundMap CreateBattleground(uint InstanceId, Battleground bg)
|
BattlegroundMap CreateBattleground(uint InstanceId, Battleground bg)
|
||||||
{
|
{
|
||||||
Log.outDebug(LogFilter.Maps, "MapInstanced.CreateBattleground: map bg {0} for {1} created.", InstanceId, GetId());
|
lock (_mapLock)
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.Maps, "MapInstanced.CreateBattleground: map bg {0} for {1} created.", InstanceId, GetId());
|
||||||
|
|
||||||
BattlegroundMap map = new BattlegroundMap(GetId(), (uint)GetGridExpiry(), InstanceId, this, Difficulty.None);
|
BattlegroundMap map = new BattlegroundMap(GetId(), (uint)GetGridExpiry(), InstanceId, this, Difficulty.None);
|
||||||
Contract.Assert(map.IsBattlegroundOrArena());
|
Contract.Assert(map.IsBattlegroundOrArena());
|
||||||
map.SetBG(bg);
|
map.SetBG(bg);
|
||||||
bg.SetBgMap(map);
|
bg.SetBgMap(map);
|
||||||
|
|
||||||
m_InstancedMaps[InstanceId] = map;
|
m_InstancedMaps[InstanceId] = map;
|
||||||
return map;
|
return map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GarrisonMap CreateGarrison(uint instanceId, Player owner)
|
GarrisonMap CreateGarrison(uint instanceId, Player owner)
|
||||||
{
|
{
|
||||||
GarrisonMap map = new GarrisonMap(GetId(), GetGridExpiry(), instanceId, this, owner.GetGUID());
|
lock (_mapLock)
|
||||||
Contract.Assert(map.IsGarrison());
|
{
|
||||||
|
GarrisonMap map = new GarrisonMap(GetId(), GetGridExpiry(), instanceId, this, owner.GetGUID());
|
||||||
|
Contract.Assert(map.IsGarrison());
|
||||||
|
|
||||||
m_InstancedMaps[instanceId] = map;
|
m_InstancedMaps[instanceId] = map;
|
||||||
return map;
|
return map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DestroyInstance(KeyValuePair<uint, Map> pair)
|
bool DestroyInstance(KeyValuePair<uint, Map> pair)
|
||||||
|
|||||||
@@ -139,9 +139,8 @@ namespace Game
|
|||||||
|
|
||||||
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>();
|
MmapTileHeader fileHeader = reader.Read<MmapTileHeader>();
|
||||||
Array.Reverse(fileHeader.mmapMagic);
|
if (fileHeader.mmapMagic != MapConst.mmapMagic)
|
||||||
if (new string(fileHeader.mmapMagic) != MapConst.mmapMagic)
|
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "MMAP:loadMap: Bad header in mmap {0:D4}{1:D2}{2:D2}.mmtile", mapId, x, y);
|
Log.outError(LogFilter.Maps, "MMAP:loadMap: Bad header in mmap {0:D4}{1:D2}{2:D2}.mmtile", mapId, x, y);
|
||||||
return false;
|
return false;
|
||||||
@@ -356,16 +355,12 @@ namespace Game
|
|||||||
public Dictionary<uint, ulong> loadedTileRefs = new Dictionary<uint, ulong>(); // maps [map grid coords] to [dtTile]
|
public Dictionary<uint, ulong> loadedTileRefs = new Dictionary<uint, ulong>(); // maps [map grid coords] to [dtTile]
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct MmapTileHeader
|
public struct MmapTileHeader
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
public uint mmapMagic;
|
||||||
public char[] mmapMagic;
|
|
||||||
public uint dtVersion;
|
public uint dtVersion;
|
||||||
public uint mmapVersion;
|
public uint mmapVersion;
|
||||||
public uint size;
|
public uint size;
|
||||||
public byte usesLiquids;
|
public byte usesLiquids;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
|
||||||
public byte[] padding;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-5
@@ -96,11 +96,11 @@ namespace Game.Maps
|
|||||||
|
|
||||||
using (var reader = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))
|
using (var reader = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))
|
||||||
{
|
{
|
||||||
var header = reader.ReadStruct<mapFileHeader>();
|
var header = reader.Read<mapFileHeader>();
|
||||||
if (new string(header.mapMagic) != MapConst.MapMagic || new string(header.versionMagic) != MapConst.MapVersionMagic)
|
if (header.mapMagic != MapConst.MapMagic || header.versionMagic != MapConst.MapVersionMagic)
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Maps, "Map file '{0}' is from an incompatible map version ({1}), {2} is expected. Please recreate using the mapextractor.",
|
Log.outError(LogFilter.Maps, "Map file '{0}' is from an incompatible map version ({1}), {2} is expected. Please recreate using the mapextractor.",
|
||||||
fileName, new string(header.versionMagic), MapConst.MapVersionMagic);
|
fileName, header.versionMagic, MapConst.MapVersionMagic);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -136,6 +136,9 @@ namespace Game.Maps
|
|||||||
|
|
||||||
void LoadVMap(uint gx, uint gy)
|
void LoadVMap(uint gx, uint gy)
|
||||||
{
|
{
|
||||||
|
if (!Global.VMapMgr.isMapLoadingEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
// x and y are swapped !!
|
// x and y are swapped !!
|
||||||
VMAPLoadResult vmapLoadResult = Global.VMapMgr.loadMap(GetId(), gx, gy);
|
VMAPLoadResult vmapLoadResult = Global.VMapMgr.loadMap(GetId(), gx, gy);
|
||||||
switch (vmapLoadResult)
|
switch (vmapLoadResult)
|
||||||
@@ -363,7 +366,7 @@ namespace Game.Maps
|
|||||||
|
|
||||||
void EnsureGridCreated(GridCoord p)
|
void EnsureGridCreated(GridCoord p)
|
||||||
{
|
{
|
||||||
lock (this)
|
lock (_gridLock)
|
||||||
{
|
{
|
||||||
EnsureGridCreated_i(p);
|
EnsureGridCreated_i(p);
|
||||||
}
|
}
|
||||||
@@ -4338,6 +4341,9 @@ namespace Game.Maps
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
internal object _mapLock = new object();
|
||||||
|
object _gridLock = new object();
|
||||||
|
|
||||||
bool _creatureToMoveLock;
|
bool _creatureToMoveLock;
|
||||||
List<Creature> creaturesToMove = new List<Creature>();
|
List<Creature> creaturesToMove = new List<Creature>();
|
||||||
|
|
||||||
@@ -4455,6 +4461,7 @@ namespace Game.Maps
|
|||||||
/// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
|
/// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
|
||||||
// GMs still can teleport player in instance.
|
// GMs still can teleport player in instance.
|
||||||
// Is it needed?
|
// Is it needed?
|
||||||
|
lock(_mapLock)
|
||||||
{
|
{
|
||||||
// Dungeon only code
|
// Dungeon only code
|
||||||
if (IsDungeon())
|
if (IsDungeon())
|
||||||
@@ -4878,7 +4885,9 @@ namespace Game.Maps
|
|||||||
|
|
||||||
public override bool AddPlayerToMap(Player player, bool initPlayer = true)
|
public override bool AddPlayerToMap(Player player, bool initPlayer = true)
|
||||||
{
|
{
|
||||||
player.m_InstanceValid = true;
|
lock (_mapLock)
|
||||||
|
player.m_InstanceValid = true;
|
||||||
|
|
||||||
return base.AddPlayerToMap(player, initPlayer);
|
return base.AddPlayerToMap(player, initPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user