diff --git a/Heroes.ReplayParser/BitReader.cs b/Heroes.ReplayParser/BitReader.cs
index 2570dd1..d475ab6 100644
--- a/Heroes.ReplayParser/BitReader.cs
+++ b/Heroes.ReplayParser/BitReader.cs
@@ -51,7 +51,7 @@ public uint Read(int numBits)
{
if (numBits > 32)
{
- throw new ArgumentOutOfRangeException("numBits", "Number of bits must be less than 32.");
+ throw new ArgumentOutOfRangeException("numBits", "Number of bits must be less than 33.");
}
uint value = 0;
@@ -75,6 +75,46 @@ public uint Read(int numBits)
return value;
}
+ ///
+ /// Reads up to 64 bits from the stream, returning them as a long.
+ ///
+ ///
+ /// The number of bits to read.
+ ///
+ ///
+ /// The .
+ ///
+ ///
+ /// Thrown if numBits is greater than 64.
+ ///
+ public long ReadLong(int numBits)
+ {
+ if (numBits > 64)
+ {
+ throw new ArgumentOutOfRangeException("numBits", "Number of bits must be less than 65.");
+ }
+
+ long value = 0;
+
+ while (numBits > 0)
+ {
+ var bytePos = Cursor & 7;
+ int bitsLeftInByte = 8 - bytePos;
+ if (bytePos == 0)
+ {
+ currentByte = stream.ReadByte();
+ }
+
+ var bitsToRead = (bitsLeftInByte > numBits) ? numBits : bitsLeftInByte;
+
+ value = (value << bitsToRead) | ((uint)currentByte >> bytePos) & ((1u << bitsToRead) - 1u);
+ Cursor += bitsToRead;
+ numBits -= bitsToRead;
+ }
+
+ return value;
+
+ }
///
/// Skip specified number of bits in stream.
///
@@ -198,5 +238,19 @@ public byte[] ReadBlobPrecededWithLength(int numBitsForLength)
AlignToByte();
return ReadBytes((int)stringLength);
}
+
+ public string ReadStringFromBits(int numberOfBits, bool reverseEndianType = false)
+ {
+ byte[] bytes = BitConverter.GetBytes(Read(numberOfBits));
+ if (reverseEndianType)
+ {
+ Array.Reverse(bytes);
+ return Encoding.UTF8.GetString(bytes);
+ }
+ else
+ {
+ return Encoding.UTF8.GetString(bytes);
+ }
+ }
}
}
diff --git a/Heroes.ReplayParser/MPQFiles/ReplayServerBattlelobby.cs b/Heroes.ReplayParser/MPQFiles/ReplayServerBattlelobby.cs
index 5193c70..91fb6d0 100644
--- a/Heroes.ReplayParser/MPQFiles/ReplayServerBattlelobby.cs
+++ b/Heroes.ReplayParser/MPQFiles/ReplayServerBattlelobby.cs
@@ -153,39 +153,54 @@ private static void DetailedParse(BitReader bitReader, Replay replay, uint s2maC
for (uint i = 0; i < playerListLength; i++)
{
- bitReader.Read(3);
- bitReader.ReadBytes(24);
- bitReader.Read(24);
- bitReader.Read(16);
- bitReader.Read(10);
+ bitReader.Read(32);
+
+ bitReader.Read(5); // player index
+
+ // toon
+ bitReader.Read(8); // m_region
+ if (bitReader.ReadStringFromBits(32, true) != "Hero") // m_programId
+ throw new DetailedParsedException("Not Hero");
+ bitReader.Read(32); // m_realm
+ bitReader.ReadLong(64); // m_id
+
+ // internal toon
+ bitReader.Read(8); // m_region
+ if (bitReader.ReadStringFromBits(32, true) != "Hero") // m_programId
+ throw new DetailedParsedException("Not Hero");
+ bitReader.Read(32); // m_realm
int idLength = (int)bitReader.Read(7);
bitReader.AlignToByte();
if (bitReader.ReadString(2) != "T:")
- throw new Exception("Not T:");
+ throw new DetailedParsedException("Not T:");
replay.ClientListByUserID[i].BattleNetTId = bitReader.ReadString(idLength);
- bitReader.ReadBytes(4);
+ bitReader.Read(6);
if (replay.ReplayBuild <= 47479)
{
- bitReader.ReadBytes(5);
- bitReader.Read(5);
+ // internal toon repeat
+ bitReader.Read(8); // m_region
+ if (bitReader.ReadStringFromBits(32, true) != "Hero") // m_programId
+ throw new DetailedParsedException("Not Hero");
+ bitReader.Read(32); // m_realm
idLength = (int)bitReader.Read(7);
+ bitReader.AlignToByte();
if (bitReader.ReadString(2) != "T:")
- throw new Exception(" Not T: (duplicate)");
+ throw new DetailedParsedException("Not T: (duplicate)");
if (replay.ClientListByUserID[i].BattleNetTId != bitReader.ReadString(idLength))
- throw new Exception($"Duplicate TID does not match");
- }
- else
- {
- bitReader.ReadBytes(25);
+ throw new DetailedParsedException("Duplicate TID does not match");
}
+ bitReader.Read(2);
+ bitReader.ReadBytes(25);
+ bitReader.Read(24);
+
// bitReader.ReadBytes(8); ai games have 8 more bytes somewhere around here
bitReader.Read(7);
@@ -245,11 +260,6 @@ private static void DetailedParse(BitReader bitReader, Replay replay, uint s2maC
if (replay.ReplayBuild >= 69947)
{
bitReader.ReadBoolean(); // m_hasActiveBoost
- bitReader.Read(2);
- }
- else
- {
- bitReader.Read(3);
}
}