Esempio n. 1
0
        public VolskayaFoundry1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, _replayFile));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
        public async Task WriteDetailsAsync(StormReplay replay)
        {
            var mmr = settings.EnableMMR ? $"MMR: " + await heroesProfileService.CalculateMMRAsync(replay) : string.Empty;

            var map = gameDataService.Maps.Find(map => map.AltName.Equals(replay.Replay.MapAlternativeName) || replay.Replay.Map.Equals(map.Name));

            var mode = replay.Replay.GameMode switch
            {
                //GameMode.StormLeague => "Storm League",
                //GameMode.UnrankedDraft => "Unranked",
                //GameMode.QuickMatch => "Quick Match",
                //_ => replay.Replay.GameMode.ToString()
                _ => string.Empty
            };

            var bans = from ban in replay.Replay.DraftOrder.Where(pick => pick.PickType == DraftPickType.Banned).Select((pick, index) => new { Hero = pick.HeroSelected, Index = index + 1 })
                       from hero in gameDataService.Heroes
                       where ban.Hero.Equals(hero.Name, StringComparison.OrdinalIgnoreCase) || ban.Hero.Equals(hero.AltName, StringComparison.OrdinalIgnoreCase)
                       select $"{hero.Name}";

            if (bans.Any())
            {
                bans = bans.Prepend("Bans:");
            }

            string[] details = new[] { mode, mmr, replay.Replay.ReplayVersion }.Where(line => !string.IsNullOrEmpty(line)).ToArray();

            logger.LogInformation($"WriteDetailsAsync: {settings.CurrentReplayPath}");

            await File.WriteAllLinesAsync(settings.CurrentReplayPath, details.Concat(bans).Where(line => !string.IsNullOrWhiteSpace(line)), CancellationToken.None);
        }
    }
Esempio n. 3
0
 public GameEventArgs(StormReplay stormReplay, T data, TimeSpan timer, string message)
 {
     Timer       = timer;
     StormReplay = stormReplay;
     Message     = message;
     Data        = data;
 }
        public MissingWorkSetSlotId1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, _replayFile));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
        private static void NoGameEvents(StormReplayResult result)
        {
            StormReplay replay = result.Replay !;

            Assert.AreEqual(0, replay.GameEvents.Count);
            Assert.IsNull(replay.Owner?.PlayerHero?.HeroName);
        }
        public LostCavernNonSingleUnit1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, "LostCavernNonSingleUnit1_76517.StormR"));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
Esempio n. 7
0
        public async Task <StormReplay> LaunchAsync(StormReplay stormReplay)
        {
            int latestBuild  = Directory.EnumerateDirectories(Path.Combine(settings.Location.GameInstallPath, VersionsFolder)).Select(x => x).Select(x => int.Parse(Path.GetFileName(x).Replace("Base", string.Empty))).Max();
            var requiresAuth = stormReplay.Replay.ReplayBuild == latestBuild;

            if (IsLaunched && await IsReplay())
            {
                return(stormReplay); // already authenticated or in a replay
            }
            else if (IsLaunched && await IsHomeScreen())
            {
                await LaunchAndWait(stormReplay);
            }
            else if (requiresAuth)
            {
                await LaunchGameFromBattlenet();
                await LaunchAndWait(stormReplay);
            }
            else
            {
                await LaunchAndWait(stormReplay);
            }

            return(stormReplay);
        }
        public AIDragonShire1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, _replayFile));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
Esempio n. 9
0
        public EscapeFromBraxisHeroic1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, "EscapeFromBraxis(Heroic)1_70200.StormR"));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
Esempio n. 10
0
        private static void GetInfo(StormReplayResult stormReplayResult)
        {
            StormReplay replay = stormReplayResult.Replay;

            List <StormPlayer> players = replay.StormPlayers.ToList();

            Console.WriteLine($"{"File Name: ",11}{Path.GetFileName(stormReplayResult.FileName)}");
            Console.WriteLine($"{"Game Mode: ",11}{replay.GameMode}");
            Console.WriteLine($"{"Map: ",11}{replay.MapInfo.MapName} [ID:{replay.MapInfo.MapId}]");
            Console.WriteLine($"{"Version: ",11}{replay.ReplayVersion}");
            Console.WriteLine($"{"Region: ",11}{replay.Region}");
            Console.WriteLine($"{"Game Time: ",11}{replay.ReplayLength}");

            if (_failed)
            {
                Environment.Exit(1);
            }

            IEnumerable <StormPlayer> blueTeam = players.Where(x => x.Team == StormTeam.Blue);
            IEnumerable <StormPlayer> redTeam  = players.Where(x => x.Team == StormTeam.Red);

            List <StormPlayer> playersWithObservers = replay.StormObservers.ToList();

            StormTeamDisplay(replay, blueTeam, StormTeam.Blue);
            StormTeamDisplay(replay, redTeam, StormTeam.Red);
            StormTeamDisplay(replay, playersWithObservers, StormTeam.Observer);
        }
Esempio n. 11
0
        public TowersofDoom1ReplayParserTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, "TowersofDoom1_39445.StormR"));

            _stormReplay = result.Replay;
            _result      = result.Status;
        }
Esempio n. 12
0
        public async Task WriteDetailsAsync(StormReplay replay)
        {
            try
            {
                var mmr = settings.HeroesProfileApi.EnableMMR ? $"Tier: " + await heroesProfileService.CalculateMMRAsync(replay) : string.Empty;

                var bans = from ban in replay.Replay.DraftOrder.Where(pick => pick.PickType == DraftPickType.Banned).Select((pick, index) => new { Hero = pick.HeroSelected, Index = index + 1 })
                           from hero in gameData.Heroes
                           where ban.Hero.Equals(hero.Name, StringComparison.OrdinalIgnoreCase) || ban.Hero.Equals(hero.AltName, StringComparison.OrdinalIgnoreCase)
                           select $"{hero.Name}";

                if (bans.Any())
                {
                    bans = bans.Prepend("Bans:");
                }

                string[] details = new[] { mmr }.Where(line => !string.IsNullOrWhiteSpace(line)).ToArray();

                logger.LogInformation($"writing replay details to: {settings.CurrentReplayInfoFilePath}");

                await File.WriteAllLinesAsync(settings.CurrentReplayInfoFilePath, details.Concat(bans).Where(line => !string.IsNullOrWhiteSpace(line)), CancellationToken.None);
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Could not update the file: {settings.CurrentReplayInfoFilePath}");
            }
        }
        public static void Parse(StormReplay replay, ReadOnlySpan <byte> source)
        {
            BitReader bitReader = new BitReader(source, EndianType.BigEndian);

            bitReader.ReadAlignedBytes(3);
            bitReader.ReadAlignedByte();
            bitReader.ReadAlignedBytes(4); // Data Max Size
            bitReader.ReadAlignedBytes(4); // Header Offset
            bitReader.ReadAlignedBytes(4); // User Data Header Size

            VersionedDecoder versionedDecoder = new VersionedDecoder(ref bitReader);

            // headerStructure.StructureByIndex[0].GetValueAsString(); // m_signature => "Heroes of the Storm replay 11

            // m_version struct
            replay.ReplayVersion.Major     = (int)(versionedDecoder.Structure?[1].Structure?[1].GetValueAsUInt32() !); // m_major
            replay.ReplayVersion.Minor     = (int)(versionedDecoder.Structure?[1].Structure?[2].GetValueAsUInt32() !); // m_minor
            replay.ReplayVersion.Revision  = (int)(versionedDecoder.Structure?[1].Structure?[3].GetValueAsUInt32() !); // m_revision
            replay.ReplayVersion.Build     = (int)(versionedDecoder.Structure?[1].Structure?[4].GetValueAsUInt32() !); // m_build
            replay.ReplayVersion.BaseBuild = (int)(versionedDecoder.Structure?[1].Structure?[5].GetValueAsUInt32() !); // m_baseBuild

            // the major version is a 0 before build 51978, it may be set as a 1

            /* if (stormReplay.ReplayBuild < 51978)
            *   stormReplay.ReplayVersion.Major = 1; */

            /* headerStructure.StructureByIndex[2].GetValueAsUInt32(); m_type */

            replay.ElapsedGamesLoops = (int)versionedDecoder.Structure ![3].GetValueAsUInt32(); // m_elapsedGameLoops
Esempio n. 14
0
        public async Task SetSessionAsync(StormReplay stormReplay)
        {
            await sessionCreater.CreateAsync(stormReplay);

            await replayFileWriter.WriteDetailsAsync(stormReplay);

            await gameController.LaunchAsync(stormReplay);
        }
Esempio n. 15
0
        private bool IsMatchingClientVersion(StormReplay stormReplay, Process p)
        {
            bool match = p.MainModule.FileVersionInfo.FileVersion == stormReplay.Replay.ReplayVersion;

            Logger.LogInformation($"Current: {p.MainModule.FileVersionInfo.FileVersion}");
            Logger.LogInformation($"Required: {stormReplay.Replay.ReplayVersion}");

            return(match);
        }
 private static void SetParsedData(StormReplay replay)
 {
     foreach (StormTrackerEvent stormTrackerEvent in replay.TrackerEventsInternal)
     {
         switch (stormTrackerEvent.TrackerEventType)
         {
         case StormTrackerEventType.PlayerSetupEvent:
             if (replay.NoWorkingSetSlotID)
             {
                 uint playerId         = stormTrackerEvent.VersionedDecoder !.Structure ![3].OptionalData !.GetValueAsUInt32();
Esempio n. 17
0
        public async Task <Uri> SaveClip(StormPlayer stormPlayer, StormReplay stormReplay)
        {
            // Limited api functionality
            // Cannot modify the title of the clip
            // Cannot modify the time of the clip from 30 to 60 seconds
            // When twitch allow it, modify the title to a format like: [Hero] [Map] - [Quintuple, Quad, Tripple] kill
            CreatedClipResponse response = await twitchAPI.Helix.Clips.CreateClipAsync(settings.TwitchBroadcasterId);

            GetClipResponse clip = await twitchAPI.Helix.Clips.GetClipAsync(response.CreatedClips[0].Id);

            return(new Uri(clip.Clips[0].Url));
        }
Esempio n. 18
0
 public virtual async Task <bool> WaitForMapLoadingAsync(StormReplay stormReplay, CancellationToken token = default)
 {
     return(await Policy
            .Handle <Exception>()                                                 // Issue getting Process information (terminated?)
            .OrResult <bool>(loaded => loaded == false)                           // it's not the game version that supports the replay
            .WaitAndRetryAsync(retryCount: 120, retry => TimeSpan.FromSeconds(1)) // this can time some time, especially if the game is downloading assets.
            .ExecuteAsync(async(t) =>
     {
         string[] names = stormReplay.Replay.Players.Select(p => p.Name).ToArray();
         return await GetWindowContainsAnyAsync(new[] { Constants.Ocr.LOADING_SCREEN_TEXT, stormReplay.Replay.Map }.Concat(names));
     }, token));
 }
Esempio n. 19
0
        private async Task LaunchGame(StormReplay stormReplay)
        {
            if (!await process.LaunchSelectedReplayAsync(stormReplay))
            {
                throw new Exception($"Game process version not found matching replay version: {stormReplay.Replay.ReplayVersion}");
            }

            if (!await process.WaitForMapLoadingAsync(stormReplay))
            {
                throw new Exception($"Map loading state was not detected after selecting: {stormReplay.Path}");
            }
        }
Esempio n. 20
0
 public async Task ReplayAsync(StormReplay stormReplay)
 {
     try
     {
         RegisterEvents();
         await RunAsync(stormReplay);
     }
     finally
     {
         zoomout = false;
         DeregisterEvents();
     }
 }
        public void NoTrackerEventsParsingTests()
        {
            StormReplayResult result = StormReplay.Parse(Path.Combine(_replaysFolder, _replayFile), new ParseOptions()
            {
                AllowPTR = false,
                ShouldParseGameEvents    = true,
                ShouldParseMessageEvents = true,
                ShouldParseTrackerEvents = false,
            });

            Assert.AreEqual(StormReplayParseStatus.Success, result.Status);

            NoTrackerEvents(result);
        }
Esempio n. 22
0
        public async Task <Uri> GetMatchLink(StormReplay stormReplay)
        {
            var apiKey          = settings.HeroesProfileApiKey;
            var hotsApiReplayId = replayHelper.TryGetReplayId(stormReplay);

            using (var client = new HttpClient()
            {
                BaseAddress = settings.HeroesProfileBaseUri
            })
            {
                string replayId = await client.GetStringAsync($"Heroesprofile/ReplayID?hotsapi_replayID={hotsApiReplayId}&api_token={apiKey}").ConfigureAwait(false);

                return(new Uri($"https://www.heroesprofile.com/Match/Single/?replayID={replayId}"));
            }
        }
Esempio n. 23
0
        public StormPlayer?GetStormPlayer(StormPlayer?currentPlayer, StormReplay stormReplay, TimeSpan timer)
        {
            IEnumerable <StormPlayer> stormPlayers = heroTool.GetPlayers(stormReplay.Replay, timer);

            if (stormPlayers.Any(p => p.SpectateEvent.IsAny(SpectateEvent.Proximity, SpectateEvent.Alive)))
            {
                if (currentPlayer == null)
                {
                    return(stormPlayers.Shuffle().FirstOrDefault());
                }
                return(stormPlayers.Where(stormPlayer => stormPlayer.Player != currentPlayer?.Player && stormPlayer.Player.Team != currentPlayer?.Player.Team).Shuffle().FirstOrDefault());
            }

            return(stormPlayers.Take(1).Select(stormPlayer => new StormPlayer(stormPlayer.Player, stormPlayer.Timer, stormPlayer.Duration - timer, stormPlayer.SpectateEvent)).FirstOrDefault());
        }
Esempio n. 24
0
        public virtual async Task <bool> LaunchSelectedReplayAsync(StormReplay stormReplay, CancellationToken token = default)
        {
            using (var defaultLaunch = Process.Start("explorer.exe", stormReplay.Path))
            {
                defaultLaunch.WaitForExit();

                // new patch or old patch can be upto 50Mb, give this some time
                return(await Task.FromResult(Policy
                                             .Handle <Exception>()
                                             .OrResult <bool>(result => result == false)
                                             .WaitAndRetry(retryCount : 300, retry => TimeSpan.FromSeconds(1))
                                             .Execute(t => Process
                                                      .GetProcessesByName(ProcessName)
                                                      .Any(p => IsMatchingClientVersion(stormReplay, p)), token)));
            }
        }
Esempio n. 25
0
        public async Task CreateAsync(StormReplay stormReplay)
        {
            DateTime start = DateTime.Now;

            logger.LogInformation($"Creating session for: {stormReplay.Path}");

            var players = replayAnalyzer.GetPlayers(stormReplay.Replay);
            var panels  = replayAnalyzer.GetPanels(stormReplay.Replay);
            var end     = replayAnalyzer.GetEnd(stormReplay.Replay);
            var isCarriedObjectiveMap = replayAnalyzer.IsCarriedObjectiveMap(stormReplay.Replay);

            sessionSetter.Set(new SessionData(players, panels, end, isCarriedObjectiveMap), stormReplay);

            logger.LogDebug($"Time to create session data: {DateTime.Now - start}");

            logger.LogInformation($"Session set for: {stormReplay.Path}");
        }
Esempio n. 26
0
        private static void Parse(string replayPath, bool onlyResult)
        {
            StormReplayResult stormReplayResult = StormReplay.Parse(replayPath, new ParseOptions()
            {
                AllowPTR = true,
                ShouldParseTrackerEvents = true,
                ShouldParseGameEvents    = true,
                ShouldParseMessageEvents = true,
            });

            ResultLine(stormReplayResult);

            if (!onlyResult)
            {
                GetInfo(stormReplayResult);
                Console.WriteLine();
            }
        }
        public static void Parse(StormReplay replay, ReadOnlySpan <byte> source)
        {
            BitReader bitReader = new BitReader(source, EndianType.BigEndian);

            uint gameLoop = 0;

            while (bitReader.Index < source.Length)
            {
                gameLoop += new VersionedDecoder(ref bitReader).ChoiceData !.GetValueAsUInt32();

                TimeSpan timeSpan             = TimeSpan.FromSeconds(gameLoop / 16.0);
                StormTrackerEventType type    = (StormTrackerEventType) new VersionedDecoder(ref bitReader).GetValueAsUInt32();
                VersionedDecoder      decoder = new VersionedDecoder(ref bitReader);

                replay.TrackerEventsInternal.Add(new StormTrackerEvent(type, timeSpan, decoder));
            }

            SetParsedData(replay);
        }
Esempio n. 28
0
        public static void Main(string[] args)
        {
            if (args != null && args.Length == 1 && File.Exists(args[0]))
            {
                StormReplayResult stormReplayResult = StormReplay.Parse(args[0], new ParseOptions()
                {
                    AllowPTR = true,
                    ShouldParseGameEvents    = true,
                    ShouldParseMessageEvents = true,
                    ShouldParseTrackerEvents = true,
                });

                Console.WriteLine(stormReplayResult.Status);
            }
            else
            {
                Console.WriteLine("No file.");
            }
        }
        private static void NoTrackerEvents(StormReplayResult result)
        {
            StormReplay replay = result.Replay !;

            Assert.IsNull(result.Replay.MapInfo.MapId);

            Assert.AreEqual(0, replay.TrackerEvents.Count);
            Assert.IsNull(replay.GetTeamLevels(StormTeam.Blue));
            Assert.IsNull(replay.GetTeamLevels(StormTeam.Red));
            Assert.IsNull(replay.GetTeamXPBreakdown(StormTeam.Blue));
            Assert.IsNull(replay.GetTeamXPBreakdown(StormTeam.Red));
            Assert.AreEqual(0, replay.DraftPicks.Count);

            List <StormPlayer> players = replay.StormPlayers.ToList();

            Assert.IsNull(players[0].Talents[0].TalentNameId);
            Assert.IsNull(players[0].ScoreResult);
            Assert.IsNull(players[0].MatchAwards);
            Assert.IsNull(players[0].MatchAwardsCount);
        }
Esempio n. 30
0
        private async Task LaunchAndWait(StormReplay stormReplay)
        {
            // This will make the HeroSwitcher communicate with existing game to launch selected replay
            using (var defaultLaunch = Process.Start(ExplorerProcess, stormReplay.Path))
            {
                Policy
                .Handle <Exception>()
                .OrResult <bool>(result => result == false)
                .WaitAndRetry(retryCount: 150, retry => TimeSpan.FromSeconds(5))
                .Execute(() => IsMatchingClientVersion(stormReplay.Replay));
            }

            var searchTerms = stormReplay.Replay.Players.Select(x => x.Name).Concat(stormReplay.Replay.Players.Select(x => x.Character)).Concat(settings.OCR.LoadingScreenText).Concat(new[] { stormReplay.Replay.Map });

            await Policy
            .Handle <Exception>()
            .OrResult <bool>(result => result == false)
            .WaitAndRetryAsync(retryCount: 10, retry => TimeSpan.FromSeconds(5))
            .ExecuteAsync(async(t) => await ContainsAnyAsync(searchTerms), this.tokenProvider.Token);
        }