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.
This commit is contained in:
JustArchi
2016-06-02 23:48:09 +02:00
parent 548146cb65
commit 550effd7c1
2 changed files with 16 additions and 40 deletions

View File

@@ -357,7 +357,7 @@ namespace ArchiSteamFarm {
return null;
}
Dictionary<Tuple<ulong, ulong>, Tuple<uint, Steam.Item.EType>> descriptions = new Dictionary<Tuple<ulong, ulong>, Tuple<uint, Steam.Item.EType>>();
Dictionary<ulong, Tuple<uint, Steam.Item.EType>> descriptions = new Dictionary<ulong, Tuple<uint, Steam.Item.EType>>();
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<ulong, ulong> key = new Tuple<ulong, ulong>(classID, instanceID);
if (descriptions.ContainsKey(key)) {
if (descriptions.ContainsKey(classID)) {
continue;
}
@@ -385,7 +382,7 @@ namespace ArchiSteamFarm {
type = GetItemType(descriptionType);
}
descriptions[key] = new Tuple<uint, Steam.Item.EType>(appID, type);
descriptions[classID] = new Tuple<uint, Steam.Item.EType>(appID, type);
}
HashSet<Steam.TradeOffer> result = new HashSet<Steam.TradeOffer>();
@@ -406,10 +403,8 @@ namespace ArchiSteamFarm {
Amount = (uint) item["amount"].AsUnsignedLong()
};
Tuple<ulong, ulong> key = new Tuple<ulong, ulong>(steamItem.ClassID, steamItem.InstanceID);
Tuple<uint, Steam.Item.EType> 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<ulong, ulong> key = new Tuple<ulong, ulong>(steamItem.ClassID, steamItem.InstanceID);
Tuple<uint, Steam.Item.EType> 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<ulong, ulong>, Tuple<uint, Steam.Item.EType>> descriptionMap = new Dictionary<Tuple<ulong, ulong>, Tuple<uint, Steam.Item.EType>>();
Dictionary<ulong, Tuple<uint, Steam.Item.EType>> descriptionMap = new Dictionary<ulong, Tuple<uint, Steam.Item.EType>>();
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<ulong, ulong> key = new Tuple<ulong, ulong>(classID, instanceID);
if (descriptionMap.ContainsKey(key)) {
if (descriptionMap.ContainsKey(classID)) {
continue;
}
@@ -536,7 +516,7 @@ namespace ArchiSteamFarm {
type = GetItemType(descriptionType);
}
descriptionMap[key] = new Tuple<uint, Steam.Item.EType>(appID, type);
descriptionMap[classID] = new Tuple<uint, Steam.Item.EType>(appID, type);
}
IEnumerable<JToken> items = jObject.SelectTokens("$.rgInventory.*");
@@ -561,10 +541,8 @@ namespace ArchiSteamFarm {
continue;
}
Tuple<ulong, ulong> key = new Tuple<ulong, ulong>(steamItem.ClassID, steamItem.InstanceID);
Tuple<uint, Steam.Item.EType> 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)) {

View File

@@ -164,21 +164,19 @@ namespace ArchiSteamFarm {
}
// Now let's create a map which maps items to their amount in our EQ
Dictionary<Tuple<ulong, ulong>, uint> amountMap = new Dictionary<Tuple<ulong, ulong>, uint>();
Dictionary<ulong, uint> amountMap = new Dictionary<ulong, uint>();
foreach (Steam.Item item in inventory) {
Tuple<ulong, ulong> key = new Tuple<ulong, ulong>(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<uint> amountsToGive = new List<uint>(tradeOffer.ItemsToGive.Count);
foreach (Tuple<ulong, ulong> key in tradeOffer.ItemsToGive.Select(item => new Tuple<ulong, ulong>(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<uint> amountsToReceive = new List<uint>(tradeOffer.ItemsToReceive.Count);
foreach (Tuple<ulong, ulong> key in tradeOffer.ItemsToReceive.Select(item => new Tuple<ulong, ulong>(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);