public static Tuple <ReplayParseResult, Replay> ParseReplay(string fileName, bool deleteFile, ParseOptions parseOptions) { var replay = new Replay(); try { // File in the version numbers for later use. MpqHeader.ParseHeader(replay, fileName); if (!parseOptions.IgnoreErrors && replay.ReplayBuild < 32455) { return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null)); } using (var archive = new MpqArchive(fileName)) ParseReplayArchive(replay, archive, parseOptions); if (deleteFile) { File.Delete(fileName); } return(ParseReplayResults(replay, parseOptions.IgnoreErrors, parseOptions.AllowPTR)); } catch { return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.ParserException, new Replay { ReplayBuild = replay.ReplayBuild })); } }
private static void ParseReplayArchive(Replay replay, MpqArchive archive, ParseOptions parseOptions) { archive.AddListfileFilenames(); // Replay Details ReplayDetails.Parse(replay, GetMpqFile(archive, ReplayDetails.FileName), parseOptions.IgnoreErrors); if (!parseOptions.IgnoreErrors) { if (replay.Players.Length != 10 || replay.Players.Count(i => i.IsWinner) != 5) { // Filter out 'Try Me' games, any games without 10 players, and incomplete games return; } else if (replay.Timestamp == DateTime.MinValue) { // Uncommon issue when parsing replay.details return; } else if (replay.Timestamp < new DateTime(2014, 10, 6, 0, 0, 0, DateTimeKind.Utc)) { // Technical Alpha replays return; } } // Replay Init Data ReplayInitData.Parse(replay, GetMpqFile(archive, ReplayInitData.FileName)); ReplayAttributeEvents.Parse(replay, GetMpqFile(archive, ReplayAttributeEvents.FileName)); if (parseOptions.ShouldParseEvents) { replay.TrackerEvents = ReplayTrackerEvents.Parse(GetMpqFile(archive, ReplayTrackerEvents.FileName)); try { replay.GameEvents = ReplayGameEvents.Parse(GetMpqFile(archive, ReplayGameEvents.FileName), replay.ClientListByUserID, replay.ReplayBuild, replay.ReplayVersionMajor, parseOptions.ShouldParseMouseEvents); replay.IsGameEventsParsedSuccessfully = true; } catch { replay.GameEvents = new List <GameEvent>(); } { // Gather talent selections var talentGameEventsDictionary = replay.GameEvents .Where(i => i.eventType == GameEventType.CHeroTalentSelectedEvent) .GroupBy(i => i.player) .ToDictionary( i => i.Key, i => i.Select(j => new Talent { TalentID = (int)j.data.unsignedInt.Value, TimeSpanSelected = j.TimeSpan }).OrderBy(j => j.TimeSpanSelected).ToArray()); foreach (var player in talentGameEventsDictionary.Keys) { player.Talents = talentGameEventsDictionary[player]; } } // Replay Server Battlelobby if (archive.Any(i => i.Filename == ReplayServerBattlelobby.FileName)) { if (parseOptions.ShouldParseDetailedBattleLobby) { ReplayServerBattlelobby.Parse(replay, GetMpqFile(archive, ReplayServerBattlelobby.FileName)); } else { ReplayServerBattlelobby.GetBattleTags(replay, GetMpqFile(archive, ReplayServerBattlelobby.FileName)); } } // Parse Unit Data using Tracker events if (parseOptions.ShouldParseUnits) { Unit.ParseUnitData(replay); } // Parse Statistics if (parseOptions.ShouldParseStatistics) { if (replay.ReplayBuild >= 40431) { try { Statistics.Parse(replay); replay.IsStatisticsParsedSuccessfully = true; } catch { replay.IsGameEventsParsedSuccessfully = false; } } } // Replay Message Events if (parseOptions.ShouldParseMessageEvents) { ReplayMessageEvents.Parse(replay, GetMpqFile(archive, ReplayMessageEvents.FileName)); } // Replay Resumable Events // So far it doesn't look like this file has anything we would be interested in // ReplayResumableEvents.Parse(replay, GetMpqFile(archive, "replay.resumable.events")); } }