Jump to content
McKay Development

Dr. McKay

Administrator
  • Posts

    3575
  • Joined

  • Last visited

Everything posted by Dr. McKay

  1. Maybe items with craft_class "tool" are always craftable. I don't remember seeing any uncraftable name tags or decal tools, for example. Also, it's probably worth mentioning that I have a recollection of seeing the NotEcon flag on contracts. Contracts are sent to the game client as CSOEconItems (because adding another SO type for contracts would be way too logical, and we can't have that), but they have the NotEcon flag which hides them from the backpack and other econ views. I could be mistaken on this, but I don't think so. I don't recall ever seeing NotEcon anywhere else. Based on this minimal research, here is my best (likely incorrect) guess at pseudocode to match Valve's actual code: function IsItemCraftable(EconItem item) { if (item.flags & NotEcon) { return false; } if (item.schemaDefinition.craft_class == "tool") { return true; } if (item.hasAttribute("never craftable")) { return false; } if ( (item.origin == Purchased || item.origin == StorePromotion) && !item.schemaDefinition.capabilities.can_craft_if_purchased ) { return false; } if (item.flags & CannotCraft) { return false; } return true; } function IsItemTradable(EconItem item) { if (item.flags & NotEcon) { return false; } if (item.flags & CannotTrade) { return false; } if (item.hasAttribute("tradable after date") && item.getAttribute("tradable after date") > time()) return false; } if (item.hasAttribute("always tradable")) { return true; } if (item.hasAttribute("cannot trade")) { return false; } if (item.origin == Achievement) { return false; } return true; } (hasAttribute and getAttribute also check the schema definition if the appropriate attribute is not present on the CSOEconItem instance)
  2. You got me curious, so I dumped my backpack and checked out some craftable and uncraftable items. Tour of Duty Ticket Craftable: Origin 8 (Found in Crate) Uncraftable: Origin 2 (Purchased), flags +16 (unknown flag) Killstreak Kits Inherit "never craftable" attribute from their schema definitions Uncraftable weapon Origin 2 (Purchased), same flags as craftable ToD ticket (4) World Traveler's Hat Inherits "cannot trade" attribute from its schema definition Flags 16 Origin 5 (Store Promotion) Sir Hootsalot Flags 0 Origin 12 (Halloween Drop) Has "never craftable" attribute on the item Mann Co. Cap Flags 0 Origin 5 (Store Promotion) Inherits "cannot trade" attribute from its schema definition Gun Mettle Campaign Coin This one is weird. I haven't found a way to determine that it's uncraftable using only the schema from the WebAPI and the GC data Flags 0 Origin 0 (Timed Drop) The only attributes listed in GetSchemaItems are kill eater attributes items_game.txt also includes static_attrs for this defindex, which contains "never craftable" and "cannot trade", among other things I also went back to check if the Mann Co. Cap also includes "never craftable" in items_game.txt, but it only has "cannot trade". My suspicion is that origin 5 (Store Promotion) also makes items uncraftable. I only have 3 items with this origin (World Traveler's Hat, Mann Co. Cap, Mann Co. Online Cap) and all are uncraftable. Pyrovision Goggles I don't have a tradable pair to compare with, but the only identifying characteristic in the GC backpack data is origin 1 (Achievement). Flags are 0 and there are no attributes, and it shares the same defindex as a tradable pair of goggles. So as far as I'm concerned, that's proof that origin can determine tradability or craftability. SpaceChem Pin My instance has the "cannot trade" attribute, but the schema definition has the "always tradable" attribute, and my item is tradable. It seems that "always tradable" overrides the "cannot trade" attribute. I suspect that "always tradable" would also override the Achievement origin, but I can't confirm. The Ghastlierest Gibus has the always tradable attribute, and that's an achievement item. I wouldn't be surprised if the always tradable attribute was added specifically for the Ghastly Gibus Grab achievement. Notably, some item have a capability can_craft_if_purchased, which backs up my suspicion that items with origin 2 (Purchased) are uncraftable unless their schema definition defines otherwise. Yeah, I believe this is what's happening. There are flags that determine if items are untradable or uncraftable, but the WebAPI also resolves the various other conditions that make an item untradable and stuffs them into those props as well. For the most part, the only attributes that are sent in your actual backpack data from the GC are those that are specific to an item instance. That would be stuff like maker's mark (crafter name), gifter name, craft index, kill eater (strange kills), tradable after date, stuff like that.
  3. All item attributes are visible in the data received from the GC. They're in the attributes array.
  4. My assumption would be that the Preview flag is set on items that are temporary store previews (the "try it out" button in the Mann Co. store) and that NotEcon would be set on items that shouldn't be tradable or craftable. It seems that your experience doesn't match my assumption, which means that either your data is wrong, my assumption is wrong, or the actual values of the named flags in node-tf2 are wrong. Any of those could be possible; I don't think I got those flag names from any authoritative source.
  5. I've never personally confirmed it, though I all but guarantee that after the game client receives info from the GC about an item that's crafted or gifted by a user that's not in the local cache, it separately requests the user's persona name using the SteamWorks RequestUserInformation function. This request goes directly to Steam and bypasses the GC. This function uses the same CM message as steam-user's getPersonas method. I promise you that all of the information necessary to tell if an item is tradable or craftable is present in the backpack property. The problem is just that Valve is good at spaghetti code and so there are a handful of different things you need to check to tell if an item is untradable or uncraftable. For tradability, there's origin (for achievement items and untradable free contract rewards), a few different item attributes (cannot trade, purchased, tradable after date, non economy, but also there's the always tradable attribute which surely overrides something but lord knows what), and a flag in the flags bitfield, and probably something else I missed too. Non-craftability is a bit easier, and you probably just need to check the purchased, never craftable, and non economy attributes in addition to the flag in the flags bitfield. But there's also the Preview and NotEcon flags to contend with. Logic dictates that both of those flags should also indicate that an item is untradable and uncraftable, but maybe that's not the case. It's just a complete mess.
  6. Show your code.
  7. That sort of error is caused by Steam unreliability. Just retry and hopefully it should work.
  8. That means Steam didn't send back a valid response.
  9. This is how you would encapsulate it: const offerObject = await new Promise((resolve, reject) => tradeHandler.manager.getOffer(depositResponse.offerId, (err, offer) => { if (err) { return reject(err); } resolve(offer); });
  10. Accepting a specific offer by ID without retrieving its data first isn't a supported use-case for TradeOfferManager, since it's designed to make the process as simple as possible and performs various checks and such. You'd need to either fetch the offer first using getOffer or manually craft the HTTP request that TradeOfferManager makes.
  11. Added in 3.44.0.
  12. let friendsList = [array of steamids]; let chunks = []; for (let i = 0; i < friendsList.length; i += 100) { chunks.push(friendsList.slice(i, i + 100)); } let chunkResults = await Promise.all(chunks.map(ck => new Promise((resolve, reject) => { try { let result = await axios.get(`https://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key=&steamids=${ck.join(',')}`); if (result && result.data && result.data.players) { return resolve(result.data.players); } reject(new Error('Malformed API response')); } catch (ex) { reject(ex); } }))); let vacFriends = []; chunkResults.forEach((chunkPlayers) => { chunkPlayers.filter(player => player.VACBanned).forEach((bannedPlayer) => { vacFriends.push(bannedPlayer); }); }); Untested and might have bugs
  13. I should mention, if you want to be absolutely sure that a trade completed (and hasn't been rolled back), you should take the tradeID property from the trade offer and plug it into GetTradeStatus. The values for the status property are documented here in ETradeStatus. Or just use getExchangeDetails.
  14. This is not the best way to make sure you have the correct item IDs when crafting items. Just use node-tf2's backpack property, which contains an always-up-to-date copy of your backpack. To find metal, just check the defindexes. If memory serves, 5000 is scrap metal, 5001 is reclaimed, and 5002 is refined.
  15. I've never seen a trade offer go from Accepted to some other state and actually mean that the trade didn't go through. Once it goes to Accepted you're pretty safe to say that it's completed. It used to be possible for trades to go to InvalidItems after Accepted, but the trade had still gone through. I don't think that's possible anymore though.
  16. Steam is Steam and Steam sucks. It happens sometimes and you should probably either delay a little while before marking a trade as definitively closed, or otherwise allow for reopening trades in whatever system or database you're using if the offer should become Accepted.
  17. Because you're mixing up async and sync. forEach returns before your requests complete. Also, rather than looping through the friend list, you should split it into chunks of 100 and make one request per chunk, to avoid getting rate limited by the API.
  18. Sorry, I don't know. I wouldn't be surprised if Valve just hardcoded a list of items that can't be put into storage units in the game client.
  19. That schema entry is pointing to a musickit_prefab prefab. Check the prefabs section for an item by that name, and use that as a base for the item's data. I don't plan to decode every individual attribute onto the item object since there are tons of them. If you need to check the value of an attribute that isn't already decoded, you'll just need to decode it yourself.
  20. A little bit of both. Mostly I used Charles Proxy to snoop on the traffic, but these days that requires a rooted phone if you're using Android since apps won't trust user-installed root certificates by default.
  21. Make multiple requests. steamcommunity.com has stricter limits.
  22. It could be that you're running into rate limits. Checking multiple users for VAC bans is better done with the WebAPI.
  23. Ah yeah, there is a problem, but your fix doesn't properly fix it. Here's the proper fix: client.on('friendsList', function() { let friends = Object.keys(client.myFriends).filter(steamId => client.myFriends[steamId] == SteamUser.EFriendRelationship.Friend)); console.log('All Friends: ' + friends.length); });
  24. Sounds like you aren't providing valid SteamIDs.
×
×
  • Create New...