From 3621a38bc942dd7d71779609881dd22dc67574b6 Mon Sep 17 00:00:00 2001 From: Zane Wagner Date: Thu, 3 Nov 2016 17:46:34 -0500 Subject: [PATCH] First pass. Final pass? Fix for #447 --- dev/Ultima/Data/MapDiffInfo.cs | 23 +++ .../Network/Server/GeneralInfoPacket.cs | 9 +- dev/Ultima/Resources/TileMatrixData.cs | 156 ++---------------- dev/Ultima/Resources/TileMatrixDataPatch.cs | 137 +++++++++------ dev/Ultima/Resources/UOPIndex.cs | 131 +++++++++++++++ dev/Ultima/World/Maps/Map.cs | 21 ++- dev/Ultima/World/Maps/MapChunk.cs | 28 +++- dev/Ultima/World/WorldClient.cs | 3 +- dev/Ultima/World/WorldModel.cs | 6 - dev/UltimaXNA.csproj | 2 + 10 files changed, 310 insertions(+), 206 deletions(-) create mode 100644 dev/Ultima/Data/MapDiffInfo.cs create mode 100644 dev/Ultima/Resources/UOPIndex.cs diff --git a/dev/Ultima/Data/MapDiffInfo.cs b/dev/Ultima/Data/MapDiffInfo.cs new file mode 100644 index 00000000..a041c1d5 --- /dev/null +++ b/dev/Ultima/Data/MapDiffInfo.cs @@ -0,0 +1,23 @@ +using UltimaXNA.Core.Network; + +namespace UltimaXNA.Ultima.Data +{ + public class MapDiffInfo + { + public readonly int MapCount; + public readonly int[] MapPatches; + public readonly int[] StaticPatches; + + public MapDiffInfo(PacketReader reader) + { + MapCount = reader.ReadInt32(); + MapPatches = new int[MapCount]; + StaticPatches = new int[MapCount]; + for (int i = 0; i < MapCount; i++) + { + StaticPatches[i] = reader.ReadInt32(); + MapPatches[i] = reader.ReadInt32(); + } + } + } +} diff --git a/dev/Ultima/Network/Server/GeneralInfoPacket.cs b/dev/Ultima/Network/Server/GeneralInfoPacket.cs index b97ab00c..9762a4cc 100644 --- a/dev/Ultima/Network/Server/GeneralInfoPacket.cs +++ b/dev/Ultima/Network/Server/GeneralInfoPacket.cs @@ -55,7 +55,7 @@ public ContextMenuData ContextMenu /// /// Subcommand 0x18: The count of map diffs that were received. /// - public int MapDiffsCount + public MapDiffInfo MapDiffs { get; private set; @@ -185,12 +185,7 @@ void receiveHouseRevisionState(PacketReader reader) void receiveMapDiffManifest(PacketReader reader) { - MapDiffsCount = reader.ReadInt32(); - for (int i = 0; i < MapDiffsCount; i++) - { - int mapPatches = reader.ReadInt32(); - int staticPatches = reader.ReadInt32(); - } + MapDiffs = new MapDiffInfo(reader); } void receiveContextMenu(PacketReader reader) diff --git a/dev/Ultima/Resources/TileMatrixData.cs b/dev/Ultima/Resources/TileMatrixData.cs index 0e0dc0db..9c45ccbb 100644 --- a/dev/Ultima/Resources/TileMatrixData.cs +++ b/dev/Ultima/Resources/TileMatrixData.cs @@ -13,38 +13,36 @@ ***************************************************************************/ #region usings using System; -using System.Collections.Generic; using System.IO; using UltimaXNA.Core.Windows; using UltimaXNA.Core.Diagnostics; using UltimaXNA.Core.Diagnostics.Tracing; using UltimaXNA.Ultima.IO; +using UltimaXNA.Ultima.Data; #endregion namespace UltimaXNA.Ultima.Resources { public class TileMatrixData { - private static uint[] m_MapChunkHeightList = new uint[] { 512, 512, 200, 256, 181 }; + // === Static Data ============================================================================================ + private readonly uint[] MapChunkHeightList = { 512, 512, 200, 256, 181 }; private const int m_SizeLandChunk = 196; private const int m_SizeLandChunkData = 192; - + private const uint m_bufferedLandChunksMaxCount = 256; + // === Instance data ========================================================================================== + private uint m_MapIndex; private byte[] m_EmptyStaticsChunk; private byte[] m_InvalidLandChunk; - - private const uint m_bufferedLandChunksMaxCount = 256; private byte[][] m_bufferedLandChunks; private uint[] m_bufferedLandChunks_Keys; - private byte[] m_StaticTileLoadingBuffer; private TileMatrixDataPatch m_Patch; - private readonly FileStream m_MapDataStream; private readonly FileStream m_StaticDataStream; private readonly BinaryReader m_StaticIndexReader; - private readonly UOPIndex m_MapIndex; - + private readonly UOPIndex m_UOPIndex; public uint ChunkHeight { @@ -60,6 +58,7 @@ public uint ChunkWidth public TileMatrixData(uint index) { + m_MapIndex = index; FileStream staticIndexStream; string mapPath = FileManager.GetFilePath(String.Format("map{0}.mul", index)); @@ -75,7 +74,7 @@ public TileMatrixData(uint index) if (File.Exists(mapPath)) { m_MapDataStream = new FileStream(mapPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - m_MapIndex = new UOPIndex(m_MapDataStream); + m_UOPIndex = new UOPIndex(m_MapDataStream); } } @@ -101,7 +100,7 @@ public TileMatrixData(uint index) if (File.Exists(mapPath2)) { m_MapDataStream = new FileStream(mapPath2, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - m_MapIndex = new UOPIndex(m_MapDataStream); + m_UOPIndex = new UOPIndex(m_MapDataStream); } } staticIndexStream = FileManager.GetFile("staidx{0}.mul", trammel); @@ -115,7 +114,7 @@ public TileMatrixData(uint index) m_StaticIndexReader = new BinaryReader(staticIndexStream); - ChunkHeight = m_MapChunkHeightList[index]; + ChunkHeight = MapChunkHeightList[index]; ChunkWidth = (uint)m_MapDataStream.Length / (ChunkHeight * m_SizeLandChunk); m_EmptyStaticsChunk = new byte[0]; @@ -130,131 +129,6 @@ public TileMatrixData(uint index) m_Patch = new TileMatrixDataPatch(this, index); } - public class UOPIndex - { - private readonly UOPEntry[] _entries; - private readonly int _length; - private readonly BinaryReader _reader; - private readonly int _version; - - public UOPIndex(FileStream stream) - { - _reader = new BinaryReader(stream); - _length = (int)stream.Length; - - if (_reader.ReadInt32() != 0x50594D) - { - throw new ArgumentException("Invalid UOP file."); - } - - _version = _reader.ReadInt32(); - _reader.ReadInt32(); - var nextTable = _reader.ReadInt32(); - - var entries = new List(); - - do - { - stream.Seek(nextTable, SeekOrigin.Begin); - var count = _reader.ReadInt32(); - nextTable = _reader.ReadInt32(); - _reader.ReadInt32(); - - for (var i = 0; i < count; ++i) - { - var offset = _reader.ReadInt32(); - - if (offset == 0) - { - stream.Seek(30, SeekOrigin.Current); - continue; - } - - _reader.ReadInt64(); - var length = _reader.ReadInt32(); - - entries.Add(new UOPEntry(offset, length)); - - stream.Seek(18, SeekOrigin.Current); - } - } while (nextTable != 0 && nextTable < _length); - - entries.Sort(OffsetComparer.Instance); - - for (var i = 0; i < entries.Count; ++i) - { - stream.Seek(entries[i].Offset + 2, SeekOrigin.Begin); - - int dataOffset = _reader.ReadInt16(); - entries[i].Offset += 4 + dataOffset; - - stream.Seek(dataOffset, SeekOrigin.Current); - entries[i].Order = _reader.ReadInt32(); - } - - entries.Sort(); - _entries = entries.ToArray(); - } - - private class OffsetComparer : IComparer - { - public static readonly IComparer Instance = new OffsetComparer(); - - public int Compare(UOPEntry x, UOPEntry y) - { - return x.Offset.CompareTo(y.Offset); - } - } - - private class UOPEntry : IComparable - { - public readonly int Length; - public int Offset; - public int Order; - - public UOPEntry(int offset, int length) - { - Offset = offset; - Length = length; - Order = 0; - } - - public int CompareTo(UOPEntry other) - { - return Order.CompareTo(other.Order); - } - } - - public int Version - { - get { return _version; } - } - - public int Lookup(int offset) - { - var total = 0; - - for (var i = 0; i < _entries.Length; ++i) - { - var newTotal = total + _entries[i].Length; - - if (offset < newTotal) - { - return _entries[i].Offset + (offset - total); - } - - total = newTotal; - } - - return _length; - } - - public void Close() - { - _reader.Close(); - } - } - public byte[] GetLandChunk(uint chunkX, uint chunkY) { if (m_MapDataStream == null) @@ -301,7 +175,7 @@ private unsafe byte[] readStaticChunk(uint chunkX, uint chunkY, out int length) chunkY %= ChunkHeight; // load the map chunk from a file. Check the patch file first (mapdif#.mul), then the base file (map#.mul). - if (m_Patch.TryGetStaticChunk(chunkX, chunkY, ref m_StaticTileLoadingBuffer, out length)) + if (m_Patch.TryGetStaticChunk(m_MapIndex, chunkX, chunkY, ref m_StaticTileLoadingBuffer, out length)) { return m_StaticTileLoadingBuffer; } @@ -356,16 +230,16 @@ private unsafe byte[] readLandChunk(uint chunkX, uint chunkY) m_bufferedLandChunks_Keys[index] = key; // load the map chunk from a file. Check the patch file first (mapdif#.mul), then the base file (map#.mul). - if (m_Patch.TryGetLandPatch(chunkX, chunkY, ref m_bufferedLandChunks[index])) + if (m_Patch.TryGetLandPatch(m_MapIndex, chunkX, chunkY, ref m_bufferedLandChunks[index])) { return m_bufferedLandChunks[index]; } else { var ptr = (int) ((chunkX * ChunkHeight) + chunkY) * m_SizeLandChunk + 4; - if (m_MapIndex != null) + if (m_UOPIndex != null) { - ptr = m_MapIndex.Lookup(ptr); + ptr = m_UOPIndex.Lookup(ptr); } m_MapDataStream.Seek(ptr, SeekOrigin.Begin); diff --git a/dev/Ultima/Resources/TileMatrixDataPatch.cs b/dev/Ultima/Resources/TileMatrixDataPatch.cs index d4f0bb9f..a745a69e 100644 --- a/dev/Ultima/Resources/TileMatrixDataPatch.cs +++ b/dev/Ultima/Resources/TileMatrixDataPatch.cs @@ -22,26 +22,50 @@ namespace UltimaXNA.Ultima.Resources { public class TileMatrixDataPatch { - private static bool m_Enabled = true; - public static bool Enabled + // === Static Data ============================================================================================ + private static MapDiffInfo EnabledDiffs; + public static void EnableMapDiffs(MapDiffInfo diffs) { - get { return m_Enabled; } - set { m_Enabled = value; } + EnabledDiffs = diffs; } + // === Instance data ========================================================================================== private FileStream m_LandPatchStream; private FileStream m_StaticPatchStream; - private Dictionary m_LandPatchPtrs; - private Dictionary> m_StaticPatchPtrs; + private Dictionary m_LandPatchPtrs; + private Dictionary m_StaticPatchPtrs; - public TileMatrixDataPatch(TileMatrixData matrix, uint index) + private class LandPatchData + { + public readonly uint Index; + public readonly uint Pointer; + public LandPatchData Next; + + public LandPatchData(uint index, uint ptr) + { + Index = index; + Pointer = ptr; + } + } + + private class StaticPatchData { - if (!m_Enabled) + public readonly uint Index; + public readonly uint Pointer; + public readonly int Length; // lengths can be negative; if they are, then they should be ignored. + public StaticPatchData Next; + + public StaticPatchData(uint index, uint ptr, int length) { - return; + Index = index; + Pointer = ptr; + Length = length; } + } + public TileMatrixDataPatch(TileMatrixData matrix, uint index) + { LoadLandPatches(matrix, String.Format("mapdif{0}.mul", index), String.Format("mapdifl{0}.mul", index)); LoadStaticPatches(matrix, String.Format("stadif{0}.mul", index), String.Format("stadifl{0}.mul", index), String.Format("stadifi{0}.mul", index)); } @@ -51,18 +75,27 @@ private uint MakeChunkKey(uint blockX, uint blockY) return ((blockY & 0x0000ffff) << 16) | (blockX & 0x0000ffff); } - public unsafe bool TryGetLandPatch(uint blockX, uint blockY, ref byte[] landData) + public unsafe bool TryGetLandPatch(uint map, uint blockX, uint blockY, ref byte[] landData) { if (ClientVersion.InstallationIsUopFormat) + { return false; - + } uint key = MakeChunkKey(blockX, blockY); - uint ptr; - - if (m_LandPatchPtrs.TryGetValue(key, out ptr)) + LandPatchData data; + if (m_LandPatchPtrs.TryGetValue(key, out data)) { - m_LandPatchStream.Seek(ptr, SeekOrigin.Begin); - + if (data.Index >= EnabledDiffs.MapPatches[map]) + { + return false; + } + while (data.Next != null) + { + if (data.Next.Index >= EnabledDiffs.MapPatches[map]) + break; + data = data.Next; + } + m_LandPatchStream.Seek(data.Pointer, SeekOrigin.Begin); landData = new byte[192]; fixed (byte* pTiles = landData) { @@ -76,15 +109,16 @@ public unsafe bool TryGetLandPatch(uint blockX, uint blockY, ref byte[] landData private unsafe int LoadLandPatches(TileMatrixData tileMatrix, string landPath, string indexPath) { - m_LandPatchPtrs = new Dictionary(); + m_LandPatchPtrs = new Dictionary(); if (ClientVersion.InstallationIsUopFormat) return 0; m_LandPatchStream = FileManager.GetFile(landPath); if (m_LandPatchStream == null) + { return 0; - + } using (FileStream fsIndex = FileManager.GetFile(indexPath)) { @@ -94,9 +128,8 @@ private unsafe int LoadLandPatches(TileMatrixData tileMatrix, string landPath, s uint ptr = 0; - for (int i = 0; i < count; ++i) + for (uint i = 0; i < count; ++i) { - uint blockID = indexReader.ReadUInt32(); uint x = blockID / tileMatrix.ChunkHeight; uint y = blockID % tileMatrix.ChunkHeight; @@ -104,7 +137,17 @@ private unsafe int LoadLandPatches(TileMatrixData tileMatrix, string landPath, s ptr += 4; - m_LandPatchPtrs.Add(key, ptr); + if (m_LandPatchPtrs.ContainsKey(key)) + { + LandPatchData current = m_LandPatchPtrs[key]; + while (current.Next != null) + current = current.Next; + current.Next = new LandPatchData(i, ptr); + } + else + { + m_LandPatchPtrs.Add(key, new LandPatchData(i, ptr)); + } ptr += 192; } @@ -115,39 +158,43 @@ private unsafe int LoadLandPatches(TileMatrixData tileMatrix, string landPath, s } } - public unsafe bool TryGetStaticChunk(uint blockX, uint blockY, ref byte[] staticData, out int length) + public unsafe bool TryGetStaticChunk(uint map, uint blockX, uint blockY, ref byte[] staticData, out int length) { try { - + length = 0; if (ClientVersion.InstallationIsUopFormat) { - length = 0; return false; } - uint key = MakeChunkKey(blockX, blockY); - Tuple ptr; // offset, length - if (m_StaticPatchPtrs.TryGetValue(key, out ptr)) + StaticPatchData data; + if (m_StaticPatchPtrs.TryGetValue(key, out data)) { - int offset = ptr.Item1; - length = ptr.Item2; - - if (offset < 0 || length <= 0) + if (data.Index >= EnabledDiffs.StaticPatches[map]) { return false; } - - m_StaticPatchStream.Seek(offset, SeekOrigin.Begin); - + while (data.Next != null) + { + if (data.Next.Index >= EnabledDiffs.StaticPatches[map]) + break; + data = data.Next; + } + if (data.Pointer == 0 || data.Length <= 0) + { + return false; + } + length = data.Length; + m_StaticPatchStream.Seek(data.Pointer, SeekOrigin.Begin); if (length > staticData.Length) + { staticData = new byte[length]; - + } fixed (byte* pStaticTiles = staticData) { NativeMethods.ReadBuffer(m_StaticPatchStream.SafeFileHandle, pStaticTiles, length); } - return true; } length = 0; @@ -161,7 +208,7 @@ public unsafe bool TryGetStaticChunk(uint blockX, uint blockY, ref byte[] static private unsafe int LoadStaticPatches(TileMatrixData tileMatrix, string dataPath, string indexPath, string lookupPath) { - m_StaticPatchPtrs = new Dictionary>(); + m_StaticPatchPtrs = new Dictionary(); m_StaticPatchStream = FileManager.GetFile(dataPath); if (m_StaticPatchStream == null) @@ -176,28 +223,26 @@ private unsafe int LoadStaticPatches(TileMatrixData tileMatrix, string dataPath, int count = (int)(indexReader.BaseStream.Length / 4); - for (int i = 0; i < count; ++i) + for (uint i = 0; i < count; ++i) { uint blockID = indexReader.ReadUInt32(); uint blockX = blockID / tileMatrix.ChunkHeight; uint blockY = blockID % tileMatrix.ChunkHeight; uint key = MakeChunkKey(blockX, blockY); - - int offset = lookupReader.ReadInt32(); + uint offset = lookupReader.ReadUInt32(); int length = lookupReader.ReadInt32(); lookupReader.ReadInt32(); - if (m_StaticPatchPtrs.ContainsKey(key)) { - // Tuple old = m_StaticPatchPtrs[key]; - m_StaticPatchPtrs[key] = new Tuple(offset, length); + StaticPatchData current = m_StaticPatchPtrs[key]; + while (current.Next != null) + current = current.Next; + current.Next = new StaticPatchData(i, offset, length); } else { - m_StaticPatchPtrs.Add(key, new Tuple(offset, length)); + m_StaticPatchPtrs.Add(key, new StaticPatchData(i, offset, length)); } - - } indexReader.Close(); diff --git a/dev/Ultima/Resources/UOPIndex.cs b/dev/Ultima/Resources/UOPIndex.cs new file mode 100644 index 00000000..84f4f97f --- /dev/null +++ b/dev/Ultima/Resources/UOPIndex.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace UltimaXNA.Ultima.Resources +{ +public class UOPIndex + { + private readonly UOPEntry[] _entries; + private readonly int _length; + private readonly BinaryReader _reader; + private readonly int _version; + + public UOPIndex(FileStream stream) + { + _reader = new BinaryReader(stream); + _length = (int)stream.Length; + + if (_reader.ReadInt32() != 0x50594D) + { + throw new ArgumentException("Invalid UOP file."); + } + + _version = _reader.ReadInt32(); + _reader.ReadInt32(); + var nextTable = _reader.ReadInt32(); + + var entries = new List(); + + do + { + stream.Seek(nextTable, SeekOrigin.Begin); + var count = _reader.ReadInt32(); + nextTable = _reader.ReadInt32(); + _reader.ReadInt32(); + + for (var i = 0; i < count; ++i) + { + var offset = _reader.ReadInt32(); + + if (offset == 0) + { + stream.Seek(30, SeekOrigin.Current); + continue; + } + + _reader.ReadInt64(); + var length = _reader.ReadInt32(); + + entries.Add(new UOPEntry(offset, length)); + + stream.Seek(18, SeekOrigin.Current); + } + } while (nextTable != 0 && nextTable < _length); + + entries.Sort(OffsetComparer.Instance); + + for (var i = 0; i < entries.Count; ++i) + { + stream.Seek(entries[i].Offset + 2, SeekOrigin.Begin); + + int dataOffset = _reader.ReadInt16(); + entries[i].Offset += 4 + dataOffset; + + stream.Seek(dataOffset, SeekOrigin.Current); + entries[i].Order = _reader.ReadInt32(); + } + + entries.Sort(); + _entries = entries.ToArray(); + } + + private class OffsetComparer : IComparer + { + public static readonly IComparer Instance = new OffsetComparer(); + + public int Compare(UOPEntry x, UOPEntry y) + { + return x.Offset.CompareTo(y.Offset); + } + } + + private class UOPEntry : IComparable + { + public readonly int Length; + public int Offset; + public int Order; + + public UOPEntry(int offset, int length) + { + Offset = offset; + Length = length; + Order = 0; + } + + public int CompareTo(UOPEntry other) + { + return Order.CompareTo(other.Order); + } + } + + public int Version + { + get { return _version; } + } + + public int Lookup(int offset) + { + var total = 0; + + for (var i = 0; i < _entries.Length; ++i) + { + var newTotal = total + _entries[i].Length; + + if (offset < newTotal) + { + return _entries[i].Offset + (offset - total); + } + + total = newTotal; + } + + return _length; + } + + public void Close() + { + _reader.Close(); + } + } +} diff --git a/dev/Ultima/World/Maps/Map.cs b/dev/Ultima/World/Maps/Map.cs index f20dabd8..7fd73595 100644 --- a/dev/Ultima/World/Maps/Map.cs +++ b/dev/Ultima/World/Maps/Map.cs @@ -55,7 +55,10 @@ public void Dispose() for (int i = 0; i < m_Chunks.Length; i++) { if (m_Chunks[i] != null) - m_Chunks[i].Unload(); + { + m_Chunks[i].Dispose(); + m_Chunks[i] = null; + } } } @@ -117,9 +120,9 @@ private void InternalCheckCellsInMemory() if (m_Chunks[cellIndex] == null || m_Chunks[cellIndex].ChunkX != cellX || m_Chunks[cellIndex].ChunkY != cellY) { if (m_Chunks[cellIndex] != null) - m_Chunks[cellIndex].Unload(); + m_Chunks[cellIndex].Dispose(); m_Chunks[cellIndex] = new MapChunk(cellX, cellY); - m_Chunks[cellIndex].Load(MapData, this); + m_Chunks[cellIndex].LoadStatics(MapData, this); // if we have a translator and it's not spring, change some statics! if (Season != Seasons.Spring && SeasonalTranslator != null) SeasonalTranslator(m_Chunks[cellIndex], Season); @@ -206,5 +209,17 @@ public Seasons Season } public static Action SeasonalTranslator; + + public void ReloadStatics() + { + foreach (MapChunk chunk in m_Chunks) + { + if (chunk != null) + { + chunk.UnloadStatics(); + chunk.LoadStatics(MapData, this); + } + } + } } } \ No newline at end of file diff --git a/dev/Ultima/World/Maps/MapChunk.cs b/dev/Ultima/World/Maps/MapChunk.cs index 328c87eb..246a7dbf 100644 --- a/dev/Ultima/World/Maps/MapChunk.cs +++ b/dev/Ultima/World/Maps/MapChunk.cs @@ -8,6 +8,7 @@ * ***************************************************************************/ #region usings +using System; using UltimaXNA.Ultima.Resources; using UltimaXNA.Ultima.World.Entities; using UltimaXNA.Ultima.World.Entities.Items; @@ -35,7 +36,7 @@ public MapChunk(uint x, uint y) /// /// Unloads all tiles and entities from memory. /// - public void Unload() + public void Dispose() { for (int i = 0; i < 64; i++) { @@ -64,7 +65,7 @@ public void Unload() Tiles = null; } - public void Load(TileMatrixData tileData, Map map) + public void LoadStatics(TileMatrixData tileData, Map map) { // get data from the tile Matrix byte[] groundData = tileData.GetLandChunk(ChunkX, ChunkY); @@ -97,5 +98,28 @@ public void Load(TileMatrixData tileData, Map map) item.Position.Set((int)ChunkX * 8 + iX, (int)ChunkY * 8 + iY, iTileZ); } } + + public void UnloadStatics() + { + for (int i = 0; i < 64; i++) + { + if (Tiles[i] != null) + { + for (int j = 0; j < Tiles[i].Entities.Count; j++) + { + if (Tiles[i].Entities[j] is Ground || Tiles[i].Entities[j] is StaticItem) + { + int entityCount = Tiles[i].Entities.Count; + Tiles[i].Entities[j].Dispose(); + if (entityCount == Tiles[i].Entities.Count) + { + Tiles[i].Entities.RemoveAt(j); + } + j--; // entity will dispose, removing it from collection. + } + } + } + } + } } } diff --git a/dev/Ultima/World/WorldClient.cs b/dev/Ultima/World/WorldClient.cs index f0e0f131..09c2766c 100644 --- a/dev/Ultima/World/WorldClient.cs +++ b/dev/Ultima/World/WorldClient.cs @@ -1131,7 +1131,8 @@ private void ReceiveGeneralInfo(IRecvPacket packet) } case 0x18: // Enable map-diff (files) / number of maps // as of 6.0.0.0, this only tells us the number of maps. - m_World.MapCount = p.MapDiffsCount; + TileMatrixDataPatch.EnableMapDiffs(p.MapDiffs); + m_World.Map.ReloadStatics(); break; case 0x19: // Extended stats if (p.ExtendedStatsSerial != WorldModel.PlayerSerial) diff --git a/dev/Ultima/World/WorldModel.cs b/dev/Ultima/World/WorldModel.cs index 6ca0a240..8dbec22d 100644 --- a/dev/Ultima/World/WorldModel.cs +++ b/dev/Ultima/World/WorldModel.cs @@ -100,12 +100,6 @@ public WorldCursor Cursor m_Cursor = value; } } - - public int MapCount - { - get; - set; - } public Map Map { diff --git a/dev/UltimaXNA.csproj b/dev/UltimaXNA.csproj index b80a068f..19a17d29 100644 --- a/dev/UltimaXNA.csproj +++ b/dev/UltimaXNA.csproj @@ -130,6 +130,7 @@ + @@ -308,6 +309,7 @@ +