mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 23:24:36 +00:00
Add farming time approximation
Because @MaduRUDE asked nicely
This commit is contained in:
parent
9b56734bad
commit
33edc81116
13 changed files with 5571 additions and 16 deletions
|
@ -35,6 +35,8 @@ using SteamKit2.Internal;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class ArchiHandler : ClientMsgHandler {
|
internal sealed class ArchiHandler : ClientMsgHandler {
|
||||||
|
internal const byte MaxGamesPlayedConcurrently = 32; // This is limit introduced by Steam Network
|
||||||
|
|
||||||
private readonly ArchiLogger ArchiLogger;
|
private readonly ArchiLogger ArchiLogger;
|
||||||
|
|
||||||
internal ArchiHandler(ArchiLogger archiLogger) {
|
internal ArchiHandler(ArchiLogger archiLogger) {
|
||||||
|
|
|
@ -79,6 +79,10 @@
|
||||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Humanizer, Version=2.1.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Humanizer.Core.2.1.0\lib\netstandard1.0\Humanizer.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.9.0.2-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.9.0.2-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
|
|
|
@ -2039,7 +2039,7 @@ namespace ArchiSteamFarm {
|
||||||
|
|
||||||
gamesToPlay.Add(gameID);
|
gamesToPlay.Add(gameID);
|
||||||
|
|
||||||
if (gamesToPlay.Count >= CardsFarmer.MaxGamesPlayedConcurrently) {
|
if (gamesToPlay.Count >= ArchiHandler.MaxGamesPlayedConcurrently) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2368,7 +2368,7 @@ namespace ArchiSteamFarm {
|
||||||
response.Append("appIDs " + string.Join(", ", CardsFarmer.CurrentGamesFarming.Select(game => game.AppID)));
|
response.Append("appIDs " + string.Join(", ", CardsFarmer.CurrentGamesFarming.Select(game => game.AppID)));
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Append(" and has a total of " + CardsFarmer.GamesToFarm.Count + " games (" + CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining) + " cards) left to farm.");
|
response.Append(" and has a total of " + CardsFarmer.GamesToFarm.Count + " games (" + CardsFarmer.GamesToFarm.Sum(game => game.CardsRemaining) + " cards, about " + CardsFarmer.TimeRemaining.ToHumanReadable() + ") left to farm.");
|
||||||
return response.ToString();
|
return response.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,13 +152,13 @@ namespace ArchiSteamFarm {
|
||||||
|
|
||||||
// User might not know what he's doing
|
// User might not know what he's doing
|
||||||
// Ensure that he can't screw core ASF variables
|
// Ensure that he can't screw core ASF variables
|
||||||
if (botConfig.GamesPlayedWhileIdle.Count <= CardsFarmer.MaxGamesPlayedConcurrently) {
|
if (botConfig.GamesPlayedWhileIdle.Count <= ArchiHandler.MaxGamesPlayedConcurrently) {
|
||||||
return botConfig;
|
return botConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program.ArchiLogger.LogGenericWarning("Playing more than " + CardsFarmer.MaxGamesPlayedConcurrently + " games concurrently is not possible, only first " + CardsFarmer.MaxGamesPlayedConcurrently + " entries from GamesPlayedWhileIdle will be used");
|
Program.ArchiLogger.LogGenericWarning("Playing more than " + ArchiHandler.MaxGamesPlayedConcurrently + " games concurrently is not possible, only first " + ArchiHandler.MaxGamesPlayedConcurrently + " entries from GamesPlayedWhileIdle will be used");
|
||||||
|
|
||||||
HashSet<uint> validGames = new HashSet<uint>(botConfig.GamesPlayedWhileIdle.Take(CardsFarmer.MaxGamesPlayedConcurrently));
|
HashSet<uint> validGames = new HashSet<uint>(botConfig.GamesPlayedWhileIdle.Take(ArchiHandler.MaxGamesPlayedConcurrently));
|
||||||
botConfig.GamesPlayedWhileIdle.IntersectWith(validGames);
|
botConfig.GamesPlayedWhileIdle.IntersectWith(validGames);
|
||||||
botConfig.GamesPlayedWhileIdle.TrimExcess();
|
botConfig.GamesPlayedWhileIdle.TrimExcess();
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class CardsFarmer : IDisposable {
|
internal sealed class CardsFarmer : IDisposable {
|
||||||
internal const byte MaxGamesPlayedConcurrently = 32; // This is limit introduced by Steam Network
|
private const byte HoursToBump = 2; // How many hours are required for restricted accounts
|
||||||
|
|
||||||
private static readonly HashSet<uint> UntrustedAppIDs = new HashSet<uint> { 440, 570, 730 };
|
private static readonly HashSet<uint> UntrustedAppIDs = new HashSet<uint> { 440, 570, 730 };
|
||||||
|
|
||||||
|
@ -56,6 +56,13 @@ namespace ArchiSteamFarm {
|
||||||
private bool NowFarming;
|
private bool NowFarming;
|
||||||
private bool StickyPause;
|
private bool StickyPause;
|
||||||
|
|
||||||
|
[JsonProperty]
|
||||||
|
internal TimeSpan TimeRemaining => new TimeSpan(
|
||||||
|
Bot.BotConfig.CardDropsRestricted ? (int) Math.Ceiling(GamesToFarm.Count / (float) ArchiHandler.MaxGamesPlayedConcurrently * HoursToBump) : 0,
|
||||||
|
30 * GamesToFarm.Sum(game => game.CardsRemaining),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
internal CardsFarmer(Bot bot) {
|
internal CardsFarmer(Bot bot) {
|
||||||
if (bot == null) {
|
if (bot == null) {
|
||||||
throw new ArgumentNullException(nameof(bot));
|
throw new ArgumentNullException(nameof(bot));
|
||||||
|
@ -95,8 +102,8 @@ namespace ArchiSteamFarm {
|
||||||
|
|
||||||
// If we have Complex algorithm and some games to boost, it's also worth to make a re-check, but only in this case
|
// If we have Complex algorithm and some games to boost, it's also worth to make a re-check, but only in this case
|
||||||
// That's because we would check for new games after our current round anyway, and having extra games in the queue right away doesn't change anything
|
// That's because we would check for new games after our current round anyway, and having extra games in the queue right away doesn't change anything
|
||||||
// Therefore, there is no need for extra restart of CardsFarmer if we have no games under 2 hours in current round
|
// Therefore, there is no need for extra restart of CardsFarmer if we have no games under HoursToBump hours in current round
|
||||||
if (Bot.BotConfig.CardDropsRestricted && (GamesToFarm.Count > 0) && (GamesToFarm.Min(game => game.HoursPlayed) < 2)) {
|
if (Bot.BotConfig.CardDropsRestricted && (GamesToFarm.Count > 0) && (GamesToFarm.Min(game => game.HoursPlayed) < HoursToBump)) {
|
||||||
await StopFarming().ConfigureAwait(false);
|
await StopFarming().ConfigureAwait(false);
|
||||||
StartFarming().Forget();
|
StartFarming().Forget();
|
||||||
}
|
}
|
||||||
|
@ -165,7 +172,7 @@ namespace ArchiSteamFarm {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot.ArchiLogger.LogGenericInfo("We have a total of " + GamesToFarm.Count + " games (" + GamesToFarm.Sum(game => game.CardsRemaining) + " cards) to farm on this account...");
|
Bot.ArchiLogger.LogGenericInfo("We have a total of " + GamesToFarm.Count + " games (" + GamesToFarm.Sum(game => game.CardsRemaining) + " cards, about " + TimeRemaining.ToHumanReadable() + ") to farm on this account...");
|
||||||
|
|
||||||
// This is the last moment for final check if we can farm
|
// This is the last moment for final check if we can farm
|
||||||
if (!Bot.IsPlayingPossible) {
|
if (!Bot.IsPlayingPossible) {
|
||||||
|
@ -183,7 +190,7 @@ namespace ArchiSteamFarm {
|
||||||
if (Bot.BotConfig.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
if (Bot.BotConfig.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
||||||
Bot.ArchiLogger.LogGenericInfo("Chosen farming algorithm: Complex");
|
Bot.ArchiLogger.LogGenericInfo("Chosen farming algorithm: Complex");
|
||||||
while (GamesToFarm.Count > 0) {
|
while (GamesToFarm.Count > 0) {
|
||||||
HashSet<Game> gamesToFarmSolo = GamesToFarm.Count > 1 ? new HashSet<Game>(GamesToFarm.Where(game => game.HoursPlayed >= 2)) : new HashSet<Game>(GamesToFarm);
|
HashSet<Game> gamesToFarmSolo = GamesToFarm.Count > 1 ? new HashSet<Game>(GamesToFarm.Where(game => game.HoursPlayed >= HoursToBump)) : new HashSet<Game>(GamesToFarm);
|
||||||
if (gamesToFarmSolo.Count > 0) {
|
if (gamesToFarmSolo.Count > 0) {
|
||||||
while (gamesToFarmSolo.Count > 0) {
|
while (gamesToFarmSolo.Count > 0) {
|
||||||
Game game = gamesToFarmSolo.First();
|
Game game = gamesToFarmSolo.First();
|
||||||
|
@ -195,7 +202,7 @@ namespace ArchiSteamFarm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (FarmMultiple(GamesToFarm.OrderByDescending(game => game.HoursPlayed).Take(MaxGamesPlayedConcurrently))) {
|
if (FarmMultiple(GamesToFarm.OrderByDescending(game => game.HoursPlayed).Take(ArchiHandler.MaxGamesPlayedConcurrently))) {
|
||||||
Bot.ArchiLogger.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Select(game => game.AppID)));
|
Bot.ArchiLogger.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Select(game => game.AppID)));
|
||||||
} else {
|
} else {
|
||||||
NowFarming = false;
|
NowFarming = false;
|
||||||
|
@ -533,8 +540,8 @@ namespace ArchiSteamFarm {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxHour >= 2) {
|
if (maxHour >= HoursToBump) {
|
||||||
Bot.ArchiLogger.LogGenericError("Received request for past-2h games!");
|
Bot.ArchiLogger.LogGenericError("Received request for already boosted games!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +609,7 @@ namespace ArchiSteamFarm {
|
||||||
GamesToFarm.Remove(game);
|
GamesToFarm.Remove(game);
|
||||||
|
|
||||||
TimeSpan timeSpan = TimeSpan.FromHours(game.HoursPlayed);
|
TimeSpan timeSpan = TimeSpan.FromHours(game.HoursPlayed);
|
||||||
Bot.ArchiLogger.LogGenericInfo("Done farming: " + game.AppID + " (" + game.GameName + ") after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!");
|
Bot.ArchiLogger.LogGenericInfo("Done farming: " + game.AppID + " (" + game.GameName + ") after " + timeSpan.ToHumanReadable() + " of playtime!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Humanizer;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal static class Utilities {
|
internal static class Utilities {
|
||||||
|
@ -71,5 +72,7 @@ namespace ArchiSteamFarm {
|
||||||
return Random.Next(maxWithout);
|
return Random.Next(maxWithout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string ToHumanReadable(this TimeSpan timeSpan) => timeSpan.Humanize(3, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
|
<package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
|
||||||
<package id="Fody" version="1.30.0-beta01" targetFramework="net461" developmentDependency="true" />
|
<package id="Fody" version="1.30.0-beta01" targetFramework="net461" developmentDependency="true" />
|
||||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net461" />
|
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net461" />
|
||||||
|
<package id="Humanizer.Core" version="2.1.0" targetFramework="net461" />
|
||||||
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net461" />
|
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net461" />
|
||||||
<package id="NLog" version="5.0.0-beta03" targetFramework="net461" />
|
<package id="NLog" version="5.0.0-beta03" targetFramework="net461" />
|
||||||
<package id="protobuf-net" version="2.0.0.668" targetFramework="net45" />
|
<package id="protobuf-net" version="2.0.0.668" targetFramework="net45" />
|
||||||
|
|
|
@ -4,4 +4,13 @@
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||||
</startup>
|
</startup>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
|
@ -48,6 +48,10 @@
|
||||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Humanizer, Version=2.1.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Humanizer.Core.2.1.0\lib\netstandard1.0\Humanizer.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.9.0.2-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.9.0.2-beta1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
|
<package id="Costura.Fody" version="2.0.0-beta0018" targetFramework="net461" developmentDependency="true" />
|
||||||
<package id="Fody" version="1.30.0-beta01" targetFramework="net461" developmentDependency="true" />
|
<package id="Fody" version="1.30.0-beta01" targetFramework="net461" developmentDependency="true" />
|
||||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net461" />
|
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net461" />
|
||||||
|
<package id="Humanizer.Core" version="2.1.0" targetFramework="net461" />
|
||||||
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net461" />
|
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net461" />
|
||||||
<package id="NLog" version="5.0.0-beta03" targetFramework="net461" />
|
<package id="NLog" version="5.0.0-beta03" targetFramework="net461" />
|
||||||
<package id="NLog.Windows.Forms" version="4.2.3" targetFramework="net461" />
|
<package id="NLog.Windows.Forms" version="4.2.3" targetFramework="net461" />
|
||||||
|
|
BIN
packages/Humanizer.Core.2.1.0/Humanizer.Core.2.1.0.nupkg
vendored
Normal file
BIN
packages/Humanizer.Core.2.1.0/Humanizer.Core.2.1.0.nupkg
vendored
Normal file
Binary file not shown.
BIN
packages/Humanizer.Core.2.1.0/lib/netstandard1.0/Humanizer.dll
vendored
Normal file
BIN
packages/Humanizer.Core.2.1.0/lib/netstandard1.0/Humanizer.dll
vendored
Normal file
Binary file not shown.
5526
packages/Humanizer.Core.2.1.0/lib/netstandard1.0/Humanizer.xml
vendored
Normal file
5526
packages/Humanizer.Core.2.1.0/lib/netstandard1.0/Humanizer.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue