From 1df9af08e61c39e0199bcf8dfbfcfee8087a51b8 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Wed, 20 Apr 2016 23:02:02 +0200 Subject: [PATCH] Bugfixes + other types for STM --- ArchiSteamFarm/ArchiWebHandler.cs | 36 +++++++++++---- ArchiSteamFarm/JSON/Steam.cs | 76 +++++++++++++++++++++---------- ArchiSteamFarm/Trading.cs | 11 +++-- 3 files changed, 87 insertions(+), 36 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 96c45a25e..7df3c141b 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -281,12 +281,32 @@ namespace ArchiSteamFarm { if (!typeMap.ContainsKey(key)) { string type = description["type"].Value; if (!string.IsNullOrEmpty(type)) { - if (type.EndsWith("Trading Card", StringComparison.Ordinal)) { - typeMap[key] = Steam.Item.EType.TradingCard; - } else if (type.EndsWith("Profile Background", StringComparison.Ordinal)) { - typeMap[key] = Steam.Item.EType.ProfileBackground; - } else { - typeMap[key] = Steam.Item.EType.Unknown; + switch (type) { + case "Booster Pack": + typeMap[key] = Steam.Item.EType.BoosterPack; + break; + case "Coupon": + typeMap[key] = Steam.Item.EType.Coupon; + break; + case "Gift": + typeMap[key] = Steam.Item.EType.Gift; + break; + case "Steam Gems": + typeMap[key] = Steam.Item.EType.SteamGems; + break; + default: + if (type.EndsWith("Emoticon", StringComparison.Ordinal)) { + typeMap[key] = Steam.Item.EType.Emoticon; + } else if (type.EndsWith("Foil Trading Card", StringComparison.Ordinal)) { + typeMap[key] = Steam.Item.EType.FoilTradingCard; + } else if (type.EndsWith("Profile Background", StringComparison.Ordinal)) { + typeMap[key] = Steam.Item.EType.ProfileBackground; + } else if (type.EndsWith("Trading Card", StringComparison.Ordinal)) { + typeMap[key] = Steam.Item.EType.TradingCard; + } else { + typeMap[key] = Steam.Item.EType.Unknown; + } + break; } } } @@ -308,7 +328,7 @@ namespace ArchiSteamFarm { AssetID = item["assetid"].AsUnsignedLong(), ClassID = item["classid"].AsUnsignedLong(), InstanceID = item["instanceid"].AsUnsignedLong(), - Amount = (byte) item["amount"].AsUnsignedLong() + Amount = (uint) item["amount"].AsUnsignedLong() }; Tuple key = new Tuple(steamItem.ClassID, steamItem.InstanceID); @@ -333,7 +353,7 @@ namespace ArchiSteamFarm { AssetID = item["assetid"].AsUnsignedLong(), ClassID = item["classid"].AsUnsignedLong(), InstanceID = item["instanceid"].AsUnsignedLong(), - Amount = (byte) item["amount"].AsUnsignedLong() + Amount = (uint) item["amount"].AsUnsignedLong() }; Tuple key = new Tuple(steamItem.ClassID, steamItem.InstanceID); diff --git a/ArchiSteamFarm/JSON/Steam.cs b/ArchiSteamFarm/JSON/Steam.cs index d3ef75df2..990b2501f 100644 --- a/ArchiSteamFarm/JSON/Steam.cs +++ b/ArchiSteamFarm/JSON/Steam.cs @@ -34,6 +34,14 @@ namespace ArchiSteamFarm { internal enum EType : byte { Unknown, + + BoosterPack, + Coupon, + Gift, + SteamGems, + + Emoticon, + FoilTradingCard, ProfileBackground, TradingCard } @@ -149,7 +157,7 @@ namespace ArchiSteamFarm { } } - internal byte Amount; + internal uint Amount; [JsonProperty(PropertyName = "amount", Required = Required.Always)] internal string AmountString { @@ -161,8 +169,8 @@ namespace ArchiSteamFarm { return; } - byte result; - if (!byte.TryParse(value, out result)) { + uint result; + if (!uint.TryParse(value, out result)) { return; } @@ -174,8 +182,7 @@ namespace ArchiSteamFarm { internal EType Type { get; set; } } - internal sealed class TradeOffer { - // REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService#CEcon_TradeOffer + internal sealed class TradeOffer { // REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService#CEcon_TradeOffer internal enum ETradeOfferState : byte { Unknown, Invalid, @@ -242,16 +249,16 @@ namespace ArchiSteamFarm { } } - internal bool IsSteamCardsOnlyTrade { + internal bool IsSteamOnlyTrade { get { foreach (Item item in ItemsToGive) { - if (item.AppID != Item.SteamAppID || item.ContextID != Item.SteamContextID || item.Type != Item.EType.TradingCard) { + if (item.AppID != Item.SteamAppID || item.ContextID != Item.SteamContextID) { return false; } } foreach (Item item in ItemsToReceive) { - if (item.AppID != Item.SteamAppID || item.ContextID != Item.SteamContextID || item.Type != Item.EType.TradingCard) { + if (item.AppID != Item.SteamAppID || item.ContextID != Item.SteamContextID) { return false; } } @@ -262,35 +269,56 @@ namespace ArchiSteamFarm { internal bool IsPotentiallyDupesTrade { get { - Dictionary ItemsToGivePerGameAmount = new Dictionary(); + Dictionary> ItemsToGivePerGame = new Dictionary>(); foreach (Item item in ItemsToGive) { - byte amount; - if (ItemsToGivePerGameAmount.TryGetValue(item.RealAppID, out amount)) { - ItemsToGivePerGameAmount[item.RealAppID] = (byte) (amount + item.Amount); + Dictionary ItemsPerType; + if (ItemsToGivePerGame.TryGetValue(item.RealAppID, out ItemsPerType)) { + ItemsPerType = new Dictionary(); + ItemsPerType[item.Type] = item.Amount; + ItemsToGivePerGame[item.RealAppID] = ItemsPerType; } else { - ItemsToGivePerGameAmount[item.RealAppID] = item.Amount; + uint amount; + if (ItemsPerType.TryGetValue(item.Type, out amount)) { + ItemsPerType[item.Type] = amount + item.Amount; + } else { + ItemsPerType[item.Type] = item.Amount; + } } } - Dictionary ItemsToReceivePerGameAmount = new Dictionary(); + Dictionary> ItemsToReceivePerGame = new Dictionary>(); foreach (Item item in ItemsToReceive) { - byte amount; - if (ItemsToReceivePerGameAmount.TryGetValue(item.RealAppID, out amount)) { - ItemsToReceivePerGameAmount[item.RealAppID] = (byte) (amount + item.Amount); + Dictionary ItemsPerType; + if (ItemsToReceivePerGame.TryGetValue(item.RealAppID, out ItemsPerType)) { + ItemsPerType = new Dictionary(); + ItemsPerType[item.Type] = item.Amount; + ItemsToReceivePerGame[item.RealAppID] = ItemsPerType; } else { - ItemsToReceivePerGameAmount[item.RealAppID] = item.Amount; + uint amount; + if (ItemsPerType.TryGetValue(item.Type, out amount)) { + ItemsPerType[item.Type] = amount + item.Amount; + } else { + ItemsPerType[item.Type] = item.Amount; + } } } - // Ensure that amounts are exactly the same - foreach (KeyValuePair item in ItemsToGivePerGameAmount) { - byte otherValue; - if (!ItemsToReceivePerGameAmount.TryGetValue(item.Key, out otherValue)) { + // Ensure that amount per type and per game matches + foreach (KeyValuePair> ItemsPerGame in ItemsToGivePerGame) { + Dictionary otherItemsPerType; + if (!ItemsToReceivePerGame.TryGetValue(ItemsPerGame.Key, out otherItemsPerType)) { return false; } - if (item.Value != otherValue) { - return false; + foreach (KeyValuePair ItemsPerType in ItemsPerGame.Value) { + uint otherAmount; + if (!otherItemsPerType.TryGetValue(ItemsPerType.Key, out otherAmount)) { + return false; + } + + if (ItemsPerType.Value != otherAmount) { + return false; + } } } diff --git a/ArchiSteamFarm/Trading.cs b/ArchiSteamFarm/Trading.cs index 451c72af4..e66cff66c 100644 --- a/ArchiSteamFarm/Trading.cs +++ b/ArchiSteamFarm/Trading.cs @@ -94,7 +94,10 @@ namespace ArchiSteamFarm { return; } - tradeOffers.RemoveWhere(trade => RecentlyParsedTrades.Contains(trade.TradeOfferID)); + lock (RecentlyParsedTrades) { + tradeOffers.RemoveWhere(trade => RecentlyParsedTrades.Contains(trade.TradeOfferID)); + } + if (tradeOffers.Count == 0) { return; } @@ -150,13 +153,13 @@ namespace ArchiSteamFarm { return false; } - // Rule 2 - We always trade steam cards and only for the same set - if (!tradeOffer.IsSteamCardsOnlyTrade || !tradeOffer.IsPotentiallyDupesTrade) { + // Rule 2 - We always trade steam itmes and only for the same set + if (!tradeOffer.IsSteamOnlyTrade || !tradeOffer.IsPotentiallyDupesTrade) { return false; } // This STM trade SHOULD be fine - // Potential TODO: Ensure that our inventory in fact has proper amount of both received and given cards + // Potential TODO: Ensure that our inventory in fact has proper amount of both received and given items // This way we could calculate amounts before and after trade, ensuring that we're in fact trading dupes and not 1 + 2 -> 0 + 3 return true; }