Talk:WebAPI/GetPlayerItems

From Team Fortress Wiki
< Talk:WebAPI
Revision as of 15:34, 23 November 2014 by Dreyfis (talk | contribs) (Accessing Private Backpacks: new section)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

404 Not Found

Running this method returns a 404 for me. GetSchema seems to work, but not GetPlayerItems.

*   Trying 63.228.223.110... connected
* Connected to api.steampowered.com (63.228.223.110) port 80 (#0)
> GET /IEconItems_440/GetPlayerItems/v0001/ HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3
> Host: api.steampowered.com
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< content-type: text/html; charset=UTF8
< expires: Sat, 26 Jul 1997 05:00:00 GMT
< cache-control: no-cache,must-revalidate
< Via: 1.1 api.steampowered.com
< Content-Length: 92
< Date: Sun, 04 Sep 2011 10:59:05 GMT
< X-Varnish: 1635405704
< Age: 0
< Via: 1.1 varnish
< Connection: keep-alive

I also tired with the ?key and ?steamID -- same result. It should have returned a 401 unauthorized.

Would really love to get this fixed. Hell, I'd do it for you if anyone from Valve actually reads this.

--Dum 03:45, 4 September 2011 (PDT) Dum

Try &SteamID rather than &steamID. Works fine for me. ~ Ath (talk) 07:36, 4 September 2011 (PDT)

PHP on Windows

It's not easy to extract the backpack position or perform any other operations on the inventory bitmask, as PHP_INT_MAX on Windows (even 64-bit) is 2147483647 (2^31 - 1) and PHP does not support unsigned integers. Netshroud 06:48, 24 November 2010 (UTC)

Sure it is. No matter what the integer value is, the binary value is the same. 4294967295 as an unsigned 32-bit integer has exactly the same binary representation as -1 as a signed 32-bit integer (32 ones). It doesn't matter that PHP only supports signed integers since you typically will never want to deal with the entire integer value directly anyway. Once you split the inventory value into its two 16-bit components, it is very simple to deal with.
Assuming the entire inventory value (ie: both backpack position and equipped values) is stored in $inventory, then you can split it into $position and $equipped like this:
$position = $inventory & 65535;
$equipped = ($inventory >> 16) & 511; //I only took the first 9 bits since there are only 9 classes. 
Using this will make $position equal to the numerical value of the position in the backpack (ie: between 1 and 200 inclusive) and $equipped will represent the classes that have the item equipped, as demonstrated in the schema. That is, each class is assigned a power of 2 and that number is the sum of all of the classes that are equipping it. For example, if both the Scout and the Demoman have the Ghastly Gibus equipped, then the Gibus would get an $equipped value of 9: the Scout's number is 1 and the Demoman's is 8. To find out if a class has an item equipped, you just need to do something like this:
$equippedPyro = $equipped & 64;
If it is equipped by the Pyro, $equippedPyro will be 64, otherwise it will be 0. Obviously, you're going to want to come up with a function that does this for you instead of having a whole bunch of "equipped" variables, but the point stands. -- Alex2539 - (talk | contribs) -- 18:49, 24 November 2010 (UTC)
Sure, the binary value is the same. But when parsing it from a string using json_decode() (or even loading it from MySQL), it ends up as a string because it's too big to be an int. Netshroud 23:22, 24 November 2010 (UTC)
PHP automatically converts between data types if possible when necessary. It doesn't matter that the value is coming from a string. I promise you, this works. Here, I've cut out bits from my own code to prove to you that this works. This script will output the info for every item in a given backpack. You just need to supply your own API key and a profile number:
<?php
	$APIkey = ''; // Use your own API key here
	$profile = ''; // Find some profile number and place it here
	
	// Put together the URL for the backpack
	$backpackURL = "http://api.steampowered.com/ITFItems_440/GetPlayerItems/v0001/?key=" . $APIkey . "&SteamID=" . $profile . "&format=json";
	
	// Download and decode the json file
	$userBackpack = json_decode(file_get_contents($backpackURL), true);
	
	$result = $userBackpack['result'];
	$items = $result['items'];
	
	// Iterate through each item
	foreach($items['item'] as $ind=>$item) {
		// Store all of the item's information in separate variables
		$id =  $item['id'];
		$defindex = $item['defindex'];
		$level = $item['level'];
		$quantity = $item['quantity'];
		$flag_cannot_trade = (array_key_exists('flag_cannot_trade', $item) ? $item['flag_cannot_trade'] : false); 
		$inventory = $item['inventory']; // The inventory value is stored just like all of the others
		$position = $inventory & 65535; // You can directly perform bitwise operations on the value. PHP understands that you mean this to be a number
		$equipped = ($inventory >> 16) & 1023; // More bitwise operations to get the equipped number
		$equippedString = getEquipped($equipped); // Convert the equipped number into a string
		$quality = $item['quality'];
		
		// Print out everything. It's ugly, but it does the job.
		echo "
			ID: $id <br/>
			Defindex: $defindex <br/>
			Level: $level <br/>
			Quantity: $quantity <br/>
			Cannot trade: $flag_cannot_trade <br/>
			Inventory: $inventory <br/>
			    Position: $position <br/>
			    Equipped: $equipped - $equippedString <br/>
			Quality: $quality <br/>
			<br/>";
	}
	
	function getEquipped($equipNumber) {
		// Create an array with all of the classes in the proper order
		$classList = array(0=>'Scout', 'Sniper', 'Soldier', 'Demoman', 'Medic', 'Heavy', 'Pyro', 'Spy', 'Engineer');
		// Start with an empty string
		$equippedString = '';
		for ($i = 0; $i < 10; $i++) {
			if ((1<<$i) & $equipNumber) { // Check that the class's bit appears in the number
				if ($equippedString)
					$equippedString .= ', '; // If the string is not empty, add a comma
					
				$equippedString .= $classList[$i]; // Add the name of the class to the string if it is equipped by that class
			}
		}
		if (!$equippedString)
			$equippedString = 'None'; // The string is "None" if no one has it equipped
		return $equippedString; 
	}	
?>

As you can see, I'm getting all of the information from json_decode and the inventory number is easily split into its two components. Also, the$equipped variable is passed to the getEquipped() function which handily returns a string listing the classes that have the item equipped (or "None" when no one has it equipped). Just to make sure this works, I tested it on my own profile and set an item in both extremes: one in position 1 with no one equipping it and one in position 200 with everyone equipping it. Both returned perfect values, as did every item in between. -- Alex2539 - (talk | contribs) -- 22:24, 25 November 2010 (UTC)

Well this is what I'm currently using (Kohana 3):
			$backpack_url = Model_TF_Backpack::url_for_user($_user->username);
			$url_contents = file_get_contents($backpack_url);
			$backpack_json = json_decode($url_contents);
			
			if($backpack_json->result->status != 1)
			{
				$this->template->error_message = 'Unable to load backpack.';
				if($backpack_json->result->status == 15)
				{
					$this->template->error_message .= ' This backpack is private.';
				}
				return;
			}
			
			$tf_backpack = ORM::factory('tf_backpack');
			$tf_backpack->user = $_user;
			$tf_backpack->save();
			foreach ($backpack_json->result->items->item as $item)
			{
				$tf_item = ORM::factory('tf_item');
				$tf_item->defindex = $item->defindex;
				$tf_item->level = $item->level;
				$tf_item->quality = $item->quality;
				$tf_item->quantity = $item->quantity;
				$tf_item->tradeable = isset($item->flag_cannot_trade) ? $item->flag_cannot_trade : TRUE;
				$tf_item->api_item_id = $item->id;
				$tf_item->inventory = $item->inventory;
				
				if (isset($item->custom_name))
				{
					$tf_item->custom_name = $item->custom_name;
				}
				if (isset($item->custom_desc))
				{
					$tf_item->custom_description = $item->custom_desc;
				}
				
				$tf_item->tf_backpack = $tf_backpack;
				$tf_item->save();
			}
		}
With that code, binary operations to $tf_item->inventory results in the equivalent of $tf_item->inventory being 0xFFFFFFFF. Just looking at the code differences, it might be because you set assoc in json_decode to true and got an array instead of an object. Do you know if it's possible to get inventory working properly when decoding into an object? Netshroud 23:49, 25 November 2010 (UTC)

A note regarding the equipped array

I'll be documenting this when a few bugs are worked out of it. While doing some reviewing of it I noticed that my Vintage Bonk Helm was equipped by the Scout and Soldier. So yeah, it'll be documented soon after I get a hold of someone at Valve. -- Lagg Backpack Stickybomb Launcher.png 13:13, 18 October 2011 (PDT)

Is this a upcoming feature? I can't seem to find these fields in any of my GetPlayerItems requests. (xml nor json) I'm pretty sure my url's ok:
http://api.steampowered.com/ITFItems_440/GetPlayerItems/v0001/?key=KEY&SteamID=76561197991024644&format=json (Or format=xml)
Is there some additional parameter I should send in the request? -- Killicon machina penetratehs.png Cerbrus 22:47, 8 November 2011 (PST)
You're using a deprecated API call. Replace ITFItems with IEconItems. Your code will also require a change for the new structure of the JSON objects. -- Lagg Backpack Stickybomb Launcher.png 04:01, 9 November 2011 (PST)
Ah, I see. Did anything change in the xml structure? -- Killicon machina penetratehs.png Cerbrus 06:22, 9 November 2011 (PST)
To be honest I'm not sure. I maintain the documentation with the JSON feed in mind and haven't gave the XML much of a look beyond when I did the initial rewrite. I would assume not since many of the issues that people complained about with the JSON in the first place came about because Valve was doing a mirror of the XML's layout. -- Lagg Backpack Stickybomb Launcher.png 08:58, 9 November 2011 (PST)
As far as I noticed, the <equipped> element has been added, as well as <account_info> on attributes 186 and 228 (Gift from / Crafted by):
<attribute>
    <defindex>228</defindex>
    <value>30758916</value>
    <float_value>0.000000</float_value>
    <account_info>
        <steamid>76561197991024644</steamid>
        <personaname>๖ۣۣۜCerbrus</personaname>
    </account_info>
</attribute>
So that means no more secondary api requests to get a username form the steam ID --Killicon machina penetratehs.png Cerbrus 09:35, 9 November 2011 (PST)

Inventory token second bit

The page says that the second bit is unused, but in reality it is used to check if the item is placed in the backpack or not.

Items that have just been traded or dropped will have the value 1 while the items with a proper backpack location will have 0.

Can anyone else confirm this? The preceding unsigned comment was added by CXhristian (talk) • (contribs) 15:03, 22 October 2011

I just have been building a backpack viewer and the first method I used was just checking for duplicates and then declaring them as new items, however I stumbled across your comment and after trying it I can confirm that it is indeed used to check if it has been placed in the backpack or not.
--Liiiink 14:08, 31 December 2012 (PST)

Accessing Private Backpacks

Everybody has private backpacks by default nowadays, which pretty much makes this API a whole lot less useful. Is there any way of making this API request access a private backpack, but also authorized as a friend so that viewing inventory is allowed? I've been working on a backpack tool for a while now, and I need this part to work to make the tool more convenient. Dreyfis (talk) 07:34, 23 November 2014 (PST)