internal async Task StartFarming() { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } if (!Bot.CanReceiveSteamCards) { await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } await FarmingInitializationSemaphore.WaitAsync().ConfigureAwait(false); try { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } bool?isAnythingToFarm = await IsAnythingToFarm().ConfigureAwait(false); if (isAnythingToFarm == null) { return; } if (!isAnythingToFarm.Value) { Bot.ArchiLogger.LogGenericInfo(Strings.NothingToIdle); await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } if (GamesToFarm.Count == 0) { Bot.ArchiLogger.LogNullError(nameof(GamesToFarm)); return; } Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.GamesToIdle, GamesToFarm.Count, GamesToFarm.Sum(game => game.CardsRemaining), TimeRemaining.ToHumanReadable())); // This is the last moment for final check if we can farm if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } if (Bot.PlayingWasBlocked) { for (byte i = 0; (i < Bot.MinPlayingBlockedTTL) && Bot.IsPlayingPossible; i++) { await Task.Delay(1000).ConfigureAwait(false); } if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } } KeepFarming = NowFarming = true; Utilities.InBackground(Farm, true); } finally { FarmingInitializationSemaphore.Release(); } }
internal async Task StartFarming() { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } if (!Bot.CanReceiveSteamCards) { await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } await FarmingSemaphore.WaitAsync().ConfigureAwait(false); try { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } if (!await IsAnythingToFarm().ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericInfo(Strings.NothingToIdle); await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } if (GamesToFarm.Count == 0) { Bot.ArchiLogger.LogNullError(nameof(GamesToFarm)); return; } Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.GamesToIdle, GamesToFarm.Count, GamesToFarm.Sum(game => game.CardsRemaining), TimeRemaining.ToHumanReadable())); // This is the last moment for final check if we can farm if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } if (Bot.PlayingWasBlocked) { await Task.Delay(Bot.MinPlayingBlockedTTL * 1000).ConfigureAwait(false); if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } } KeepFarming = NowFarming = true; } finally { FarmingSemaphore.Release(); } do { // Now the algorithm used for farming depends on whether account is restricted or not if (Bot.BotConfig.CardDropsRestricted) // If we have restricted card drops, we use complex algorithm { Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Complex")); while (GamesToFarm.Count > 0) { HashSet <Game> gamesToFarmSolo = GamesToFarm.Count > 1 ? new HashSet <Game>(GamesToFarm.Where(game => game.HoursPlayed >= HoursToBump)) : new HashSet <Game>(GamesToFarm); if (gamesToFarmSolo.Count > 0) { while (gamesToFarmSolo.Count > 0) { Game game = gamesToFarmSolo.First(); if (await FarmSolo(game).ConfigureAwait(false)) { gamesToFarmSolo.Remove(game); } else { NowFarming = false; return; } } } else { if (FarmMultiple(GamesToFarm.OrderByDescending(game => game.HoursPlayed).Take(ArchiHandler.MaxGamesPlayedConcurrently))) { Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGames, string.Join(", ", GamesToFarm.Select(game => game.AppID)))); } else { NowFarming = false; return; } } } } else // If we have unrestricted card drops, we use simple algorithm { Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Simple")); while (GamesToFarm.Count > 0) { Game game = GamesToFarm.First(); if (await FarmSolo(game).ConfigureAwait(false)) { continue; } NowFarming = false; return; } } } while (await IsAnythingToFarm().ConfigureAwait(false)); CurrentGamesFarming.ClearAndTrim(); NowFarming = false; Bot.ArchiLogger.LogGenericInfo(Strings.IdlingFinished); await Bot.OnFarmingFinished(true).ConfigureAwait(false); }
private async Task Farm() { do { Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.GamesToIdle, GamesToFarm.Count, GamesToFarm.Sum(game => game.CardsRemaining), TimeRemaining.ToHumanReadable())); // Now the algorithm used for farming depends on whether account is restricted or not if (Bot.BotConfig.HoursUntilCardDrops > 0) { // If we have restricted card drops, we use complex algorithm Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Complex")); while (GamesToFarm.Count > 0) { // Initially we're going to farm games that passed our HoursUntilCardDrops // This block is almost identical to Simple algorithm, we just copy appropriate items from GamesToFarm into innerGamesToFarm HashSet <Game> innerGamesToFarm = GamesToFarm.Where(game => game.HoursPlayed >= Bot.BotConfig.HoursUntilCardDrops).ToHashSet(); while (innerGamesToFarm.Count > 0) { Game game = innerGamesToFarm.First(); if (!await IsPlayableGame(game).ConfigureAwait(false)) { GamesToFarm.Remove(game); innerGamesToFarm.Remove(game); continue; } if (await FarmSolo(game).ConfigureAwait(false)) { innerGamesToFarm.Remove(game); continue; } NowFarming = false; return; } // At this point we have no games past HoursUntilCardDrops anymore, so we're going to farm all other ones // In order to maximize efficiency, we'll take games that are closest to our HoursPlayed first // We must call ToList() here as we can't remove items while enumerating foreach (Game game in GamesToFarm.OrderByDescending(game => game.HoursPlayed).ToList()) { if (!await IsPlayableGame(game).ConfigureAwait(false)) { GamesToFarm.Remove(game); continue; } innerGamesToFarm.Add(game); // There is no need to check all games at once, allow maximum of MaxGamesPlayedConcurrently in this batch if (innerGamesToFarm.Count >= ArchiHandler.MaxGamesPlayedConcurrently) { break; } } // If we have no playable games to farm, we're done if (innerGamesToFarm.Count == 0) { break; } // Otherwise, we farm our innerGamesToFarm batch until any game hits HoursUntilCardDrops if (await FarmMultiple(innerGamesToFarm).ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGames, string.Join(", ", innerGamesToFarm.Select(game => game.AppID)))); } else { NowFarming = false; return; } } } else { // If we have unrestricted card drops, we use simple algorithm Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Simple")); while (GamesToFarm.Count > 0) { // In simple algorithm we're going to farm anything that is playable, regardless of hours Game game = GamesToFarm.First(); if (!await IsPlayableGame(game).ConfigureAwait(false)) { GamesToFarm.Remove(game); continue; } if (await FarmSolo(game).ConfigureAwait(false)) { continue; } NowFarming = false; return; } } } while ((await IsAnythingToFarm().ConfigureAwait(false)).GetValueOrDefault()); NowFarming = false; Bot.ArchiLogger.LogGenericInfo(Strings.IdlingFinished); await Bot.OnFarmingFinished(true).ConfigureAwait(false); }
internal async Task StartFarming() { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } if (!Bot.CanReceiveSteamCards) { await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } await FarmingSemaphore.WaitAsync().ConfigureAwait(false); try { if (NowFarming || Paused || !Bot.IsPlayingPossible) { return; } if (!await IsAnythingToFarm().ConfigureAwait(false)) { Bot.ArchiLogger.LogGenericInfo(Strings.NothingToIdle); await Bot.OnFarmingFinished(false).ConfigureAwait(false); return; } if (GamesToFarm.Count == 0) { Bot.ArchiLogger.LogNullError(nameof(GamesToFarm)); return; } Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.GamesToIdle, GamesToFarm.Count, GamesToFarm.Sum(game => game.CardsRemaining), TimeRemaining.ToHumanReadable())); // This is the last moment for final check if we can farm if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } if (Bot.PlayingWasBlocked) { await Task.Delay(Bot.MinPlayingBlockedTTL * 1000).ConfigureAwait(false); if (!Bot.IsPlayingPossible) { Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable); return; } } KeepFarming = NowFarming = true; Farm().Forget(); // Farm() will end when we're done farming, so don't wait for it } finally { FarmingSemaphore.Release(); } }