barrett777 / Heroes.ReplayParser

A C# library for parsing Heroes of the Storm replay files (.StormReplay)
MIT License
223 stars 95 forks source link

ReplayTrackerEvents.Parse - Error "Unexpected data in tracker event" #1

Closed Ubloobok closed 9 years ago

Ubloobok commented 9 years ago

Ben, good day!

I'm trying to parse locally my replies as in example code and getting error at the line "ReplayTrackerEvents.Parse" - "Unexpected data in tracker event". Replay file for example: https://www.dropbox.com/s/ilzza52r0iyn5uf/TestReplay.StormReplay?dl=0 Code:

var bytes = File.ReadAllBytes(filename);
var replay = new Replay();
MpqHeader.ParseHeader(replay, filename);
ReplayInitData.Parse(replay, bytes);
ReplayTrackerEvents.Parse(replay, bytes);

Can you help me please, what am I doing wrong?

P.S. And maybe I found in "Example Code" minor misprint: MpqHeader.ParseHeader(replay, bytes); , second parameter should be "filename"?

barrett777 commented 9 years ago

Hello!

The .StormReplay file is actually a file archive, in Blizzard's 'MPQ' format. You will need to extract the files in the .StormReplay archive first, and then pass the bytes of these inner files to the appropriate functions.

You can use this editor outside of code to see the files contained in a .StormReplay file, extract them, and then pass the appropriate file bytes to each function: http://www.zezula.net/en/mpq/download.html

There are a couple libraries you can use to extract these files in code. The most common one used is probably MpqLib.dll, which you can see uses and download in this Starcraft 2 replay project: https://github.com/ascendedguard/sc2replay-csharp/blob/master/Starcraft2.ReplayParser/Replay.cs

Here's more pseudo code using MpqLib.dll:

var archive = new CArchive(tmpPath); // The .StormReplay file var files = archive.FindFiles("replay.*"); // Find files within the .StormReplay archive const string CurFile = "replay.initData"; // The inner file 'replay.initData', which Heroes.ReplayParser can extract information from

var fileSize = (from f in files where f.FileName.Equals(CurFile) select f).Single().Size; // Size of inner 'replay.initData' file var buffer = new byte[fileSize]; archive.ExportFile(CurFile, buffer); // Extract inner 'replay.initData' file to buffer

ReplayInitData.Parse(replay, buffer); // Heroes.ReplayParser will parse this file

Ubloobok commented 9 years ago

Thanks! Sorry, I skipped phrase in documentation: "Requirements: An external tool to extract files from the .StormReplay container, such as MpqLib.dll". It solved my error.

There are a couple libraries you can use to extract these files in code. The most common one used is probably MpqLib.dll, which you can see uses and download in this Starcraft 2 replay project: https://github.com/ascendedguard/sc2replay-csharp/blob/master/Starcraft2.ReplayParser/Replay.cs

Hm, interesting, seems like that for "MpqLib.dll" required full access for directory where are placed replays. Without it we will get an error:

An unhandled exception of type 'System.IO.IOException' occurred in MpqLib.dll Additional information: Unable to open "TestReplay.StormReplay"!

For solve it, we can run application under administrator role or use TEMP-directory in Windows. Below are sample code, maybe will be helpfull for others, spied from "Starcraft2.ReplayParser":

var tmpPath = Path.GetTempFileName();
File.Copy(replayFileName, tmpPath, true);
var archive = new CArchive(replayFileName);