Skip to content

Commit

Permalink
Merge pull request #100 from koliva8245/battlelobby-toon
Browse files Browse the repository at this point in the history
Decoded toon handles in battlelobby
  • Loading branch information
barrett777 authored Jan 27, 2020
2 parents 7a4b18f + b7cc9e8 commit f41d693
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 22 deletions.
56 changes: 55 additions & 1 deletion Heroes.ReplayParser/BitReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -75,6 +75,46 @@ public uint Read(int numBits)
return value;
}

/// <summary>
/// Reads up to 64 bits from the stream, returning them as a long.
/// </summary>
/// <param name="numBits">
/// The number of bits to read.
/// </param>
/// <returns>
/// The <see cref="uint"/>.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if numBits is greater than 64.
/// </exception>
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;

}
/// <summary>
/// Skip specified number of bits in stream.
/// </summary>
Expand Down Expand Up @@ -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);
}
}
}
}
52 changes: 31 additions & 21 deletions Heroes.ReplayParser/MPQFiles/ReplayServerBattlelobby.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -423,7 +433,7 @@ private static void GetBattleTags(Replay replay, BitReader reader)
for (var playerNum = 0; playerNum < replay.Players.Length; playerNum++)
{
var player = replay.Players[playerNum];
if (player == null)
if (player == null || string.IsNullOrEmpty(player.Name))
continue;

// Find each player's name, and then their associated BattleTag
Expand Down

0 comments on commit f41d693

Please sign in to comment.