Skip to content

Commit

Permalink
Merge pull request #449 from ZaneDubya/shard-fix
Browse files Browse the repository at this point in the history
First pass. Final pass?
  • Loading branch information
ZaneDubya authored Nov 3, 2016
2 parents 1206c46 + 3621a38 commit ea2dd50
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 206 deletions.
23 changes: 23 additions & 0 deletions dev/Ultima/Data/MapDiffInfo.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
}
9 changes: 2 additions & 7 deletions dev/Ultima/Network/Server/GeneralInfoPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public ContextMenuData ContextMenu
/// <summary>
/// Subcommand 0x18: The count of map diffs that were received.
/// </summary>
public int MapDiffsCount
public MapDiffInfo MapDiffs
{
get;
private set;
Expand Down Expand Up @@ -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)
Expand Down
156 changes: 15 additions & 141 deletions dev/Ultima/Resources/TileMatrixData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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));
Expand All @@ -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);
}
}

Expand All @@ -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);
Expand All @@ -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];
Expand All @@ -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<UOPEntry>();

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<UOPEntry>
{
public static readonly IComparer<UOPEntry> Instance = new OffsetComparer();

public int Compare(UOPEntry x, UOPEntry y)
{
return x.Offset.CompareTo(y.Offset);
}
}

private class UOPEntry : IComparable<UOPEntry>
{
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)
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit ea2dd50

Please sign in to comment.