From 550effd7c165da15469130f58bbfd93b35a212a6 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Thu, 2 Jun 2016 23:48:09 +0200 Subject: [PATCH] EXPERIMENTAL: Base key on classID only I've just received trade offer from Endorlight game which used different combinations of classID/instanceID for the same items, such as <1450080555, 246376127> and <1450080555, 0> for Birdy trading card. This is the first time I've seen something like that, as up to this point all classID + instanceID matched nicely. It's not good because it results in possibly wrong results regarding numbers of the same cards. It's not any major problem scamming-wise, as ASF does other checks (including appID checks) so in worst case we could accept a trade that is not neutral+ for us, such as 1 -> 2 dupes one. This commit fixes wrong logic for that particular trade I've encountered, and many similar ones, but I have no idea if we can really base key on classID only. Number seems big enough to fit all steam items, but if there ever happens item that will have same classID as other one, we'll be in deep sh*t. I ran a test on my Steam account with 7.5k+ items and didn't find any item which could cause such conflict, so I can at least assume that the issue doesn't exist for majority of Steam users. Sadly there doesn't seem to be any good way to solve it either, as if such conflicts happens, then we will have 3 items such as <7, 1>, <7, 4> and <7, 0>. We can't know if 0 should be 1 or 4 (thanks GabeN). This seems to be best solution for that problem, and until we find clasID conflict, we can sleep in peace. --- ArchiSteamFarm/ArchiWebHandler.cs | 42 ++++++++----------------------- ArchiSteamFarm/Trading.cs | 14 +++++------ 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index cc570a121..ad27baff3 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -357,7 +357,7 @@ namespace ArchiSteamFarm { return null; } - Dictionary, Tuple> descriptions = new Dictionary, Tuple>(); + Dictionary> descriptions = new Dictionary>(); foreach (KeyValue description in response["descriptions"].Children) { ulong classID = description["classid"].AsUnsignedLong(); if (classID == 0) { @@ -365,10 +365,7 @@ namespace ArchiSteamFarm { continue; } - ulong instanceID = description["instanceid"].AsUnsignedLong(); - - Tuple key = new Tuple(classID, instanceID); - if (descriptions.ContainsKey(key)) { + if (descriptions.ContainsKey(classID)) { continue; } @@ -385,7 +382,7 @@ namespace ArchiSteamFarm { type = GetItemType(descriptionType); } - descriptions[key] = new Tuple(appID, type); + descriptions[classID] = new Tuple(appID, type); } HashSet result = new HashSet(); @@ -406,10 +403,8 @@ namespace ArchiSteamFarm { Amount = (uint) item["amount"].AsUnsignedLong() }; - Tuple key = new Tuple(steamItem.ClassID, steamItem.InstanceID); - Tuple description; - if (descriptions.TryGetValue(key, out description)) { + if (descriptions.TryGetValue(steamItem.ClassID, out description)) { steamItem.RealAppID = description.Item1; steamItem.Type = description.Item2; } @@ -427,10 +422,8 @@ namespace ArchiSteamFarm { Amount = (uint) item["amount"].AsUnsignedLong() }; - Tuple key = new Tuple(steamItem.ClassID, steamItem.InstanceID); - Tuple description; - if (descriptions.TryGetValue(key, out description)) { + if (descriptions.TryGetValue(steamItem.ClassID, out description)) { steamItem.RealAppID = description.Item1; steamItem.Type = description.Item2; } @@ -492,7 +485,7 @@ namespace ArchiSteamFarm { return null; // OK, empty inventory } - Dictionary, Tuple> descriptionMap = new Dictionary, Tuple>(); + Dictionary> descriptionMap = new Dictionary>(); foreach (JToken description in descriptions) { string classIDString = description["classid"].ToString(); if (string.IsNullOrEmpty(classIDString)) { @@ -506,20 +499,7 @@ namespace ArchiSteamFarm { continue; } - string instanceIDString = description["instanceid"].ToString(); - if (string.IsNullOrEmpty(instanceIDString)) { - Logging.LogNullError(nameof(instanceIDString), Bot.BotName); - continue; - } - - ulong instanceID; - if (!ulong.TryParse(instanceIDString, out instanceID)) { - Logging.LogNullError(nameof(instanceID), Bot.BotName); - continue; - } - - Tuple key = new Tuple(classID, instanceID); - if (descriptionMap.ContainsKey(key)) { + if (descriptionMap.ContainsKey(classID)) { continue; } @@ -536,7 +516,7 @@ namespace ArchiSteamFarm { type = GetItemType(descriptionType); } - descriptionMap[key] = new Tuple(appID, type); + descriptionMap[classID] = new Tuple(appID, type); } IEnumerable items = jObject.SelectTokens("$.rgInventory.*"); @@ -561,10 +541,8 @@ namespace ArchiSteamFarm { continue; } - Tuple key = new Tuple(steamItem.ClassID, steamItem.InstanceID); - Tuple description; - if (descriptionMap.TryGetValue(key, out description)) { + if (descriptionMap.TryGetValue(steamItem.ClassID, out description)) { steamItem.RealAppID = description.Item1; steamItem.Type = description.Item2; } @@ -574,7 +552,7 @@ namespace ArchiSteamFarm { bool more; if (!bool.TryParse(jObject["more"].ToString(), out more) || !more) { - break; // OK, last page + break; // OK, last page` } if (ushort.TryParse(jObject["more_start"].ToString(), out nextPage)) { diff --git a/ArchiSteamFarm/Trading.cs b/ArchiSteamFarm/Trading.cs index 1d702e741..2979f706b 100644 --- a/ArchiSteamFarm/Trading.cs +++ b/ArchiSteamFarm/Trading.cs @@ -164,21 +164,19 @@ namespace ArchiSteamFarm { } // Now let's create a map which maps items to their amount in our EQ - Dictionary, uint> amountMap = new Dictionary, uint>(); + Dictionary amountMap = new Dictionary(); foreach (Steam.Item item in inventory) { - Tuple key = new Tuple(item.ClassID, item.InstanceID); - uint amount; - if (amountMap.TryGetValue(key, out amount)) { - amountMap[key] = amount + item.Amount; + if (amountMap.TryGetValue(item.ClassID, out amount)) { + amountMap[item.ClassID] = amount + item.Amount; } else { - amountMap[key] = item.Amount; + amountMap[item.ClassID] = item.Amount; } } // Calculate our value of items to give List amountsToGive = new List(tradeOffer.ItemsToGive.Count); - foreach (Tuple key in tradeOffer.ItemsToGive.Select(item => new Tuple(item.ClassID, item.InstanceID))) { + foreach (ulong key in tradeOffer.ItemsToGive.Select(item => item.ClassID)) { uint amount; if (!amountMap.TryGetValue(key, out amount)) { amountsToGive.Add(0); @@ -193,7 +191,7 @@ namespace ArchiSteamFarm { // Calculate our value of items to receive List amountsToReceive = new List(tradeOffer.ItemsToReceive.Count); - foreach (Tuple key in tradeOffer.ItemsToReceive.Select(item => new Tuple(item.ClassID, item.InstanceID))) { + foreach (ulong key in tradeOffer.ItemsToReceive.Select(item => item.ClassID)) { uint amount; if (!amountMap.TryGetValue(key, out amount)) { amountsToReceive.Add(0);