// Not super useful, it just gives you for each card how many are yet to be seen in the collection
        // (probably about the "new" flag)
        public static dynamic ReadCollectionCardRecords([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var service = image.GetNetCacheService("NetCacheCollection")?["<Stacks>k__BackingField"];
            var size    = service["_size"];
            var items   = service["_items"];
            var result  = new List <dynamic>();

            for (int i = 0; i < size; i++)
            {
                var stack   = items[i];
                var count   = stack["<Count>k__BackingField"];
                var numSeen = stack["<NumSeen>k__BackingField"];
                var cardId  = stack["<Def>k__BackingField"]["<Name>k__BackingField"];
                var premium = stack["<Def>k__BackingField"]["<Premium>k__BackingField"];
                result.Add(new
                {
                    CardId  = cardId,
                    Premium = premium,
                    Count   = count,
                    NumSeen = numSeen,
                });
            }

            result.Sort((dynamic a, dynamic b) => b.NumSeen - a.NumSeen);
            return(result);
        }
        public static IBoostersInfo ReadBoostersInfo([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var boosterServices = image.GetNetCacheService("NetCacheBoosters");
            if (boosterServices == null || boosterServices["<BoosterStacks>k__BackingField"] == null)
            {
                return null;
            }

            var boosters = new List<IBoosterStack>();
            var itemCount = boosterServices["<BoosterStacks>k__BackingField"]["_size"];
            var items = boosterServices["<BoosterStacks>k__BackingField"]["_items"];
            for (int i = 0; i < itemCount; i++)
            {
                var booster = items[i];
                boosters.Add(new BoosterStack()
                {
                    BoosterId = booster["<Id>k__BackingField"],
                    Count = booster["<Count>k__BackingField"],
                    EverGrantedCount = booster["<EverGrantedCount>k__BackingField"],
                });
            }

            boosters.Sort((a, b) => a.BoosterId - b.BoosterId);
            return new BoostersInfo()
            {
                Boosters = boosters,
            };
        }
Exemplo n.º 3
0
        private static IDungeonInfo BuildDungeonInfo(HearthstoneImage image, DungeonKey key, dynamic savesMap)
        {
            var index = DungeonInfoReader.GetKeyIndex(savesMap, (int)key);

            if (index == -1)
            {
                return(null);
            }

            var dungeonMap  = savesMap["valueSlots"][index];
            var dungeonInfo = new DungeonInfo
            {
                Key               = key,
                DeckCards         = DungeonInfoReader.ExtractValues(dungeonMap, (int)DungeonFieldKey.DeckList),
                LootOptionBundles = new List <List <int> >
                {
                    DungeonInfoReader.ExtractValues(dungeonMap, (int)DungeonFieldKey.LootOption1),
                    DungeonInfoReader.ExtractValues(dungeonMap, (int)DungeonFieldKey.LootOption2),
                    DungeonInfoReader.ExtractValues(dungeonMap, (int)DungeonFieldKey.LootOption3),
                },
                ChosenLoot       = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.ChosenLoot),
                TreasureOption   = DungeonInfoReader.ExtractValues(dungeonMap, (int)DungeonFieldKey.TreasureOption),
                ChosenTreasure   = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.ChosenTreasure),
                RunActive        = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.RunActive),
                SelectedDeck     = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.SelectedDeck),
                StartingTreasure = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.StartingTreasure),
            };

            dungeonInfo.DeckList = DungeonInfoReader.BuildRealDeckList(image, dungeonInfo);

            return(dungeonInfo);
        }
Exemplo n.º 4
0
        public static int ReadCollectionSize([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var collectibleCards = image["CollectionManager"]["s_instance"]["m_collectibleCards"];
            var items            = collectibleCards["_items"];
            int size             = collectibleCards["_size"];
            var totalCards       = 0;

            for (var index = 0; index < size; index++)
            {
                string cardId = items[index]["m_EntityDef"]["m_cardIdInternal"];
                if (string.IsNullOrEmpty(cardId))
                {
                    continue;
                }

                int count   = items[index]["<OwnedCount>k__BackingField"] ?? 0;
                int premium = items[index]["m_PremiumType"] ?? 0;
                totalCards += count;
                totalCards += premium;
            }
            return(totalCards);
        }
        public static IPackInfo ReadOpenPackInfo([NotNull] HearthstoneImage image)
        {
            var openPacksInfo = OpenPacksInfoReader.ReadOpenPacksInfo(image);

            if (openPacksInfo?.PackOpening?.Cards == null || openPacksInfo.PackOpening.Cards.Any(card => card == null || card.CardId == null))
            {
                return(null);
            }

            var cards = openPacksInfo.PackOpening.Cards;

            if (cards?.Count == 5)
            {
                return(new PackInfo
                {
                    BoosterId = openPacksInfo.LastOpenedBoosterId,
                    Cards = cards
                            .Select(card => new CardInfo
                    {
                        CardId = card.CardId,
                        Premium = card.Premium,
                        IsNew = card.IsNew,
                    } as ICardInfo)
                            .ToList(),
                });
            }

            return(null);
        }
Exemplo n.º 6
0
        public static IRewardTrackInfo ReadRewardTrack([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var service = image.GetService("Hearthstone.Progression.RewardTrackManager");

            if (service == null)
            {
                return(null);
            }

            var trackModel = service["<TrackDataModel>k__BackingField"];

            if (trackModel == null)
            {
                return(null);
            }

            return(new RewardTrackInfo
            {
                Level = trackModel["m_Level"],
                Xp = trackModel["m_Xp"],
                XpNeeded = trackModel["m_XpNeeded"],
                XpBonusPercent = trackModel["m_XpBonusPercent"],
            });
        }
Exemplo n.º 7
0
        private static DuelsMetaInfo ReadDuelsInfoFromDisplay([NotNull] HearthstoneImage image)
        {
            if (image["PvPDungeonRunDisplay"] == null ||
                image["PvPDungeonRunDisplay"]["m_instance"] == null ||
                image["PvPDungeonRunDisplay"]["m_instance"]["m_dataModel"] == null)
            {
                return(null);
            }

            var display          = image["PvPDungeonRunDisplay"]["m_instance"]["m_dataModel"];
            var wins             = display["m_Wins"];
            var losses           = display["m_Losses"];
            var rating           = display["m_Rating"];
            var paidRating       = display["m_PaidRating"];
            var lastRatingChange = display["m_LastRatingChange"];

            return(new DuelsMetaInfo
            {
                Wins = wins,
                Losses = losses,
                Rating = rating,
                PaidRating = paidRating,
                LastRatingChange = lastRatingChange,
            });
        }
Exemplo n.º 8
0
        public static bool IsDisplayingAchievementToast([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var manager = image.GetService("Hearthstone.Progression.AchievementManager");

            //var debugState = manager["m_playerState"];
            //debugState.TypeDefinition
            if (manager == null || manager["m_achievementToast"] == null)
            {
                return(false);
            }

            var toast = manager["m_achievementToast"];

            if (toast != null)
            {
                //processing = true;
                //TypeDefinitionContentViewModel model = new TypeDefinitionContentViewModel(manager.TypeDefinition);
                //List<string> dump = new List<string>();
                //var addresses = new List<uint>();
                //model.DumpMemory("", dump, addresses, manager);
                return(true);
            }

            return(true);
        }
Exemplo n.º 9
0
        private static BattleTag GetBattleTag(HearthstoneImage image, IAccount account)
        {
            var gameAccounts = image["BnetPresenceMgr"]["s_instance"]?["m_gameAccounts"];

            if (gameAccounts == null)
            {
                return(null);
            }

            var keys = gameAccounts["keySlots"];

            for (var i = 0; i < keys.Length; i++)
            {
                if ((keys[i]?["m_hi"] != account.Hi) || (keys[i]?["m_lo"] != account.Lo))
                {
                    continue;
                }

                var bTag = gameAccounts["valueSlots"][i]["m_battleTag"];
                return(new BattleTag
                {
                    Name = bTag["m_name"],
                    Number = bTag["m_number"],
                });
            }

            return(null);
        }
        public static IDeck ReadWhizbangDeck([NotNull] HearthstoneImage image, long whizbangDeckId)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            if (image["GameDbf"] == null ||
                image["GameDbf"]["DeckTemplate"] == null ||
                image["GameDbf"]["DeckTemplate"]["m_records"] == null)
            {
                return(null);
            }

            var templates = image["GameDbf"]["DeckTemplate"]["m_records"];
            var size      = templates["_size"];
            var items     = templates["_items"];

            for (var i = 0; i < size; i++)
            {
                var template = items[i];
                if (template["m_deckId"] == whizbangDeckId)
                {
                    var deckId   = template["m_deckId"];
                    var decklist = GetTemplateDeck(image, deckId);
                    return(new Deck()
                    {
                        DeckList = decklist,
                    });
                }
            }

            return(null);
        }
        public static IReadOnlyList <IDeck> ReadTemplateDecks(HearthstoneImage image)
        {
            var templates = image["GameDbf"]["DeckTemplate"]["m_records"]["_items"];
            var result    = new List <IDeck>();

            for (var i = 0; i < templates.Length; i++)
            {
                if (templates[i] != null)
                {
                    var     template = templates[i];
                    var     deckId   = template["m_deckId"];
                    DbfDeck dbfDeck  = ActiveDeckReader.GetDbfDeck(image, deckId);
                    if (dbfDeck == null)
                    {
                        continue;
                    }

                    IList <int> decklist = ActiveDeckReader.BuildDecklistFromTopCard(image, dbfDeck.TopCardId);
                    result.Add(new Deck()
                    {
                        DeckId    = deckId,
                        Id        = template["m_ID"],
                        DeckList  = decklist.Select(dbfId => "" + dbfId).ToList(),
                        Name      = dbfDeck.Name,
                        HeroClass = template["m_classId"],
                    });
                }
            }
            return(result);
        }
Exemplo n.º 12
0
        private static int GetRankValue(HearthstoneImage image, dynamic medalInfo)
        {
            var leagueId         = medalInfo["leagueId"];
            var starLevel        = medalInfo["starLevel"];
            var leagueRankRecord = MatchInfoReader.GetLeagueRankRecord(image, leagueId, starLevel);

            if (leagueRankRecord == null)
            {
                return(0);
            }

            var locValues = leagueRankRecord["m_medalText"]["m_locValues"]["_items"];

            foreach (var value in locValues)
            {
                if (value == null)
                {
                    continue;
                }

                if (int.TryParse(value, out int rank))
                {
                    return(rank);
                }
            }

            return(0);
        }
        private static int ExtractDeckDbfIdForBoH(HearthstoneImage image, dynamic dungeonMap)
        {
            // Find the story opponent
            int storyEnemyDbfId = DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.StoryEnemy);
            var storyCard       = DungeonInfoReader.GetCardDbf(image, storyEnemyDbfId);

            if (storyCard == null)
            {
                return(-1);
            }

            var storyCardId  = storyCard["m_noteMiniGuid"];
            var dbf          = image["GameDbf"];
            var starterDecks = dbf["Deck"]["m_records"]["_items"];

            for (var i = 0; i < starterDecks.Length; i++)
            {
                if (starterDecks[i] != null)
                {
                    var deckNoteName = starterDecks[i]["m_noteName"];
                    if (deckNoteName == storyCardId)
                    {
                        return(starterDecks[i]["m_ID"]);
                    }
                }
            }
            return(-1);
        }
 private static IDeck GetDuelsDeck(HearthstoneImage image)
 {
     return(new Deck
     {
         DeckList = DuelsInfoReader.ReadDuelsInfo(image)?.DeckList?.Select(dbfId => dbfId.ToString())?.ToList(),
     });
 }
Exemplo n.º 15
0
        public static IDuelsInfo ReadDuelsInfo([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var duelsMetaInfo = BuildDuelsMetaInfo(image);
            var dungeonInfo   = BuildDungeonInfo(image);

            return(new DuelsInfo
            {
                Wins = duelsMetaInfo?.Wins ?? -1,
                Losses = duelsMetaInfo?.Losses ?? -1,
                Rating = duelsMetaInfo?.Rating ?? -1,
                PaidRating = duelsMetaInfo?.PaidRating ?? -1,
                LastRatingChange = duelsMetaInfo?.LastRatingChange ?? -1,
                DeckList = dungeonInfo?.DeckList,
                StartingHeroPower = dungeonInfo?.StartingHeroPower ?? -1,
                LootOptionBundles = dungeonInfo?.LootOptionBundles,
                ChosenLoot = dungeonInfo?.ChosenLoot ?? -1,
                TreasureOption = dungeonInfo?.TreasureOption,
                ChosenTreasure = dungeonInfo?.ChosenTreasure ?? -1,
                PlayerClass = dungeonInfo?.PlayerClass ?? -1,
                RunActive = dungeonInfo.RunActive,
            });
        }
        public static IDungeonInfoCollection ReadCollection([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var savesMap = image["GameSaveDataManager"]?["s_instance"]?["m_gameSaveDataMapByKey"];

            if (savesMap == null)
            {
                return(null);
            }

            var dictionary = new Dictionary <DungeonKey, IDungeonInfo>();

            foreach (DungeonKey key in Enum.GetValues(typeof(DungeonKey)))
            {
                dictionary.Add(
                    key,
                    DungeonInfoReader.BuildDungeonInfo(image, key, savesMap));
            }

            return(new DungeonInfoCollection(dictionary));
        }
 private static bool IsValidRun(HearthstoneImage image)
 {
     return(image != null &&
            image["GameDbf"] != null &&
            image["GameDbf"]["Deck"] != null &&
            image["GameDbf"]["Deck"]["m_records"] != null &&
            image["GameDbf"]["Deck"]["m_records"]["_items"] != null);
 }
Exemplo n.º 18
0
        private static IReadOnlyList <int> BuildRealDeckList(HearthstoneImage image, IDungeonInfo runFromMemory)
        {
            var deckList = new List <int>();

            // The current run is in progress, which means the value held in the DeckCards
            // field is the aggregation of the cards picked in the previous steps
            // TODO: how to handle card changed / removed by Bob?
            if (runFromMemory.RunActive == 1)
            {
                deckList = runFromMemory.DeckCards.ToList();
                if (runFromMemory.ChosenLoot > 0)
                {
                    // index is 1-based
                    var chosenBundle = runFromMemory.LootOptionBundles[runFromMemory.ChosenLoot - 1];

                    // First card is the name of the bundle
                    for (var i = 1; i < chosenBundle.Count; i++)
                    {
                        deckList.Add(chosenBundle[i]);
                    }
                }

                if (runFromMemory.ChosenTreasure > 0)
                {
                    deckList.Add(runFromMemory.TreasureOption[runFromMemory.ChosenTreasure - 1]);
                }
            }
            else
            {
                if (runFromMemory.SelectedDeck > 0)
                {
                    deckList.Add(runFromMemory.StartingTreasure);

                    var dbf          = image["GameDbf"];
                    var starterDecks = dbf["Deck"]["m_records"]["_items"];
                    for (var i = 0; i < starterDecks.Length; i++)
                    {
                        var deckId = starterDecks[i]["m_ID"];
                        if (deckId == runFromMemory.SelectedDeck)
                        {
                            var topCardId = starterDecks[i]["m_topCardId"];
                            var cardDbf   = DungeonInfoReader.GetDeckCardDbf(image, topCardId);
                            while (cardDbf != null)
                            {
                                deckList.Add(cardDbf["m_cardId"]);
                                var next = cardDbf["m_nextCardId"];
                                cardDbf = next == 0 ? null : DungeonInfoReader.GetDeckCardDbf(image, next);
                            }
                        }
                    }
                }
            }

            // Some cards can be set to 0, when they are removed by Bob for instance
            return(deckList.Where(id => id > 0).ToArray());
        }
        public static IDeck ReadActiveDeck([NotNull] HearthstoneImage image, long?inputSelectedDeckId)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            if (image["DeckPickerTrayDisplay"] == null && inputSelectedDeckId == null)
            {
                return(null);
            }

            if (image["CollectionManager"] == null)
            {
                return(null);
            }

            var selectedDeckId = GetSelectedDeckId(image) ?? inputSelectedDeckId ?? 0;
            var deckFromMemory = ReadSelectedDeck(image, selectedDeckId);

            if (deckFromMemory != null)
            {
                return(deckFromMemory);
            }

            var matchInfo = MatchInfoReader.ReadMatchInfo(image);

            if (matchInfo == null)
            {
                return(null);
            }

            switch (matchInfo.GameType)
            {
            case GameType.GT_ARENA:
                return(GetArenaDeck(image));

            case GameType.GT_CASUAL:
                return(GetCasualDeck(image));

            case GameType.GT_RANKED:
                return(GetRankedDeck(image));

            case GameType.GT_VS_AI:
                return(GetSoloDeck(image, matchInfo.MissionId));

            case GameType.GT_VS_FRIEND:
                return(GetFriendlyDeck(image));

            case GameType.GT_PVPDR:
            case GameType.GT_PVPDR_PAID:
                return(GetDuelsDeck(image));

            default: return(null);
            }
        }
        public static IReadOnlyList <ICollectionCoin> ReadCollection([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var collectionCoins = new List <CollectionCoin>();

            var netCache = image.GetService("NetCache");

            if (netCache == null ||
                netCache["m_netCache"] == null ||
                netCache["m_netCache"]["valueSlots"] == null)
            {
                return(collectionCoins);
            }

            var coinDbf = image["GameDbf"]["Coin"]["m_records"];
            var _size   = coinDbf["_size"];
            var _items  = coinDbf["_items"];
            var coinDic = new Dictionary <int, int>();

            for (int i = 0; i < _size; i++)
            {
                var coin = _items[i];
                coinDic.Add(coin["m_ID"], coin["m_cardId"]);
            }

            var netCacheValues = netCache["m_netCache"]["valueSlots"];

            foreach (var value in netCacheValues)
            {
                if (value?.TypeDefinition?.Name == "NetCacheCoins")
                {
                    var cardBacks = value["<Coins>k__BackingField"];
                    var slots     = cardBacks["_slots"];
                    for (var i = 0; i < slots.Length; i++)
                    {
                        var coin   = slots[i];
                        var coinId = coin["value"];
                        if (coinId != 0)
                        {
                            collectionCoins.Add(new CollectionCoin()
                            {
                                CoinId = coinDic[coinId],
                            });
                        }
                    }
                }
            }


            return(collectionCoins);
        }
        private static int ExtractDeckDbfId(HearthstoneImage image, dynamic dungeonMap, DungeonKey key)
        {
            switch (key)
            {
            case DungeonKey.BookOfHeroes:
                return(DungeonInfoReader.ExtractDeckDbfIdForBoH(image, dungeonMap));

            default:
                return(DungeonInfoReader.ExtractValue(dungeonMap, (int)DungeonFieldKey.SelectedDeck));
            }
        }
Exemplo n.º 22
0
        public static IDuelsRewardsInfo ReadDuelsRewardsInfo([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            try
            {
                if (image["RewardBoxesDisplay"] == null || image["RewardBoxesDisplay"]["s_Instance"] == null)
                {
                    return(null);
                }
            } catch (Exception e)
            {
                return(null);
            }

            var service = image["RewardBoxesDisplay"]["s_Instance"];

            if (service["m_rewards"] == null || service["m_rewards"]["_size"] == 0)
            {
                return(null);
            }

            var  rewards      = service["m_rewards"]["_items"];
            var  rewardsCount = service["m_rewards"]["_size"];
            var  rewardsList  = new List <IDuelsRewardInfo>();
            long amount;

            for (int i = 0; i < rewardsCount; i++)
            {
                var rewardObject = rewards[i];
                try
                {
                    // Not sure which field is used based on what context, so we try both
                    amount = rewardObject["<Count>k__BackingField"];
                }
                catch (Exception e)
                {
                    amount = rewardObject["<Amount>k__BackingField"];
                }
                rewardsList.Add(new DuelsRewardInfo
                {
                    Type      = rewardObject["m_type"],
                    Amount    = amount,
                    BoosterId = rewardObject["m_type"] == 1 ? rewardObject["<Id>k__BackingField"] : -1,
                });
            }
            return(new DuelsRewardsInfo
            {
                Rewards = rewardsList,
            });
        }
        private static IReadOnlyList <int> BuildRealDeckList(HearthstoneImage image, IDungeonInfo runFromMemory)
        {
            // The current run is in progress, which means the value held in the DeckCards
            // field is the aggregation of the cards picked in the previous steps
            // TODO: how to handle card changed / removed by Bob?
            var deckList = runFromMemory.RunActive == 1
                ? BuildRealDeckListForActiveRun(runFromMemory)
                : BuildRealDeckListForNewRun(image, runFromMemory);

            // Some cards can be set to 0, when they are removed by Bob for instance
            return(deckList.Where(id => id > 0).ToArray());
        }
        private static List <int> BuildRealDeckListForNewRun(HearthstoneImage image, IDungeonInfo runFromMemory)
        {
            var deckList   = new List <int>();
            var isValidRun = runFromMemory.SelectedDeck > 0 && IsValidRun(image);

            if (isValidRun)
            {
                deckList.Add(runFromMemory.StartingTreasure);
                deckList.AddRange(ActiveDeckReader.GetTemplateDeck(image, runFromMemory.SelectedDeck));
            }
            return(deckList);
        }
Exemplo n.º 25
0
        public MindVision()
        {
            var process = Process.GetProcessesByName("Hearthstone").FirstOrDefault();

            if (process == null)
            {
                throw new InvalidOperationException(
                          "Failed to find Hearthstone executable. Please check that Hearthstone is running.");
            }

            this.image = new HearthstoneImage(AssemblyImageFactory.Create(process.Id));
        }
Exemplo n.º 26
0
        public static IReadOnlyList <IXpChange> ReadXpChanges([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var result  = new List <IXpChange>();
            var service = image.GetService("Hearthstone.Progression.RewardXpNotificationManager");

            if (service == null)
            {
                return(result);
            }

            dynamic xpChanges = null;

            try
            {
                xpChanges = service["m_xpChanges"];
                if (xpChanges == null)
                {
                    return(result);
                }
            }
            catch (Exception e)
            {
                return(result);
            }

            var size = xpChanges["_size"];

            if (size == 0)
            {
                return(result);
            }

            for (var i = 0; i < size; i++)
            {
                var xpChange = xpChanges["_items"][i];
                result.Add(new XpChange()
                {
                    CurrentLevel     = xpChange["_CurrLevel"],
                    CurrentXp        = xpChange["_CurrXp"],
                    PreviousLevel    = xpChange["_PrevLevel"],
                    PreviousXp       = xpChange["_PrevXp"],
                    RewardSourceId   = xpChange["_RewardSourceId"],
                    RewardSourceType = xpChange["_RewardSourceType"],
                });
            }

            return(result);
        }
        public static IList <int> BuildDecklistFromTopCard(HearthstoneImage image, dynamic topCardId)
        {
            var deckList = new List <int>();
            var cardDbf  = ActiveDeckReader.GetDeckCardDbf(image, topCardId);

            while (cardDbf != null)
            {
                deckList.Add(cardDbf["m_cardId"]);
                var next = cardDbf["m_nextCardId"];
                cardDbf = next == 0 ? null : ActiveDeckReader.GetDeckCardDbf(image, next);
            }
            return(deckList);
        }
        public static IAccountInfo ReadAccountInfo([NotNull] HearthstoneImage image)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var account = image["BnetPresenceMgr"]?["s_instance"]?["m_myGameAccountId"];

            return(account == null ? null : new AccountInfo {
                Hi = account["m_hi"], Lo = account["m_lo"]
            });
        }
        public static dynamic GetDeckCardDbf(HearthstoneImage image, int cardId)
        {
            var cards = image["GameDbf"]["DeckCard"]["m_records"]["_items"];

            for (var i = 0; i < cards.Length; i++)
            {
                if (cards[i]["m_ID"] == cardId)
                {
                    return(cards[i]);
                }
            }

            return(null);
        }
        private static IDeck GetSoloDeck(HearthstoneImage image, int missionId)
        {
            Console.WriteLine("Getting solo deck for missionId: " + missionId);
            var deckList = GetSoloDeckList(image, missionId);

            if (deckList == null)
            {
                return(null);
            }
            return(new Deck
            {
                DeckList = deckList.Select(dbfId => dbfId.ToString()).ToList(),
            });
        }