StoreObject( 'captcha_' . $key, $strCaptcha, $nTimeout ); return $strCaptcha; } public static function BValidateCaptcha( $key, $strCaptchaAttempt ) { return self::EValidateCaptcha( $key, $strCaptchaAttempt ) == k_EResultOK; } public static function EValidateCaptcha( $key, $strCaptchaAttempt ) { $strCaptchaAttempt = strtoupper( $strCaptchaAttempt ); $strLockKey = 'captcha_lock_' . $key; if ( !GetSharedObjectCache()->BLock( $strLockKey, 2 ) ) return k_EResultLockingFailed; $strCaptcha = GetSharedObjectCache()->GetObject( 'captcha_' . $key ); GetSharedObjectCache()->BDelete( 'captcha_' . $key ); GetSharedObjectCache()->BUnlock( $strLockKey ); if ( empty( $strCaptcha ) ) { return k_EResultTimeout; } if ( strlen( $strCaptcha ) != self::CAPTCHA_LENGTH ) { return k_EResultUnexpectedError; } if ( strcmp( $strCaptcha, $strCaptchaAttempt ) === 0 ) return k_EResultOK; else return k_EResultNoMatch; } public static function EValidateRecaptcha( $strCaptchaResponse, $strRemoteIP ) { $response = curl_url_fetch( "https://www.google.com/recaptcha/api/siteverify?secret=6LdlRgATAAAAAJPeL4w-IsD_fxhh4iY2VUfAyZVS&response=" . urlencode( $strCaptchaResponse ) . "&remoteip=" . urlencode( $strRemoteIP) ); if ( empty($response) ) { return k_EResultRemoteCallFailed; } $jsonResponse = json_decode( $response ); if ( empty($jsonResponse) ) { return k_EResultBadResponse; } return $jsonResponse->success ? k_EResultOK : k_EResultFail; } public static function RenderCaptchaForString( $strCaptcha ) { $width = 206; $height = 40; $rectangles = rand( 3, 4 ); $yvariance = 3; $minwidth = 24; $maxwidth = 27; $anglevariance = 12; // the hex code broken down - #67c1f5 $fgR = 0x67 / 0xff; $fgG = 0xc1 / 0xff; $fgB = 0xf5 / 0xff; // #131f2f $bgR = 0x13 / 0xff; $bgG = 0x1f / 0xff; $bgB = 0x2f / 0xff; $fonts = Array(); $fonts[] = realpath( dirname( __FILE__ ) ) . '/resources/arial.ttf'; $fonts[] = realpath( dirname( __FILE__ ) ) . '/resources/comic.ttf'; $fonts[] = realpath( dirname( __FILE__ ) ) . '/resources/tahoma.ttf'; $fontsize = 18; // Create image and draw basic background $image = imagecreatetruecolor( $width, $height ); $shade = 150; $bgcolor = imagecolorallocate( $image, $shade * $bgR, $shade * $bgG, $shade * $bgB ); imagefilledrectangle( $image, 0, 0, $width, $height, $bgcolor ); // Draw some random rectangles (wide ones) for( $i = 0; $i < $rectangles; ++$i ) { $shade = rand( 100, 140 ); $color = imagecolorallocatealpha( $image, $shade* $fgR, $shade* $fgG, $shade* $fgB, rand( 30, 60 ) ); $ypos0 = rand( 0, $height ); $xpos0 = rand( 0, $width ); $ypos1 = $ypos0 + rand( -$height/8, $height/8 ); $xpos1 = $xpos0 + rand( -$width/6, $width/6 ); imagefilledrectangle( $image, min( $xpos0, $xpos1 ), min( $ypos0, $ypos1 ), max( $xpos0, $xpos1 ), max( $ypos0, $ypos1 ), $color ); } // Again, but ones that are tall this time for( $i = 0; $i < $rectangles; ++$i ) { $shade = rand( 100, 140 ); $color = imagecolorallocatealpha( $image, $shade * $fgR, $shade* $fgG, $shade* $fgB, rand( 30, 60 ) ); $ypos0 = rand( 0, $height/2 ); $xpos0 = rand( 0, $width/2 ); $ypos1 = $ypos0 + rand( -$height/1.5, $height/1.5 ); $xpos1 = $xpos0 + rand( -$width/15, $width/15 ); imagefilledrectangle( $image, min( $xpos0, $xpos1 ), min( $ypos0, $ypos1 ), max( $xpos0, $xpos1 ), max( $ypos0, $ypos1 ), $color ); } // Set thickness for line drawing used below imagesetthickness( $image, 1.2 ); // Draw Text $x = rand( 20, 50 ); $y = 30; for( $i=0; $i array( 'howtoget' => Localize('#Economy_HowToGetItems_TF2'), ), // portal2 620 => array( 'howtoget' => Localize('#Economy_HowToGetItems_Portal2'), ), //steam (1 = gifts, 2 = profile items) 753 => array( 1 => array ( 'howtoget' => Localize('#Economy_HowToGetItems_SteamGifts'), ), ), ); //spiral knights self::$sm_rgAppDisplayRules[99900] = array( 'logo' => IMG_URL . 'economy/applogos/99900.png' ); self::$sm_rgAppDisplayRules[99920] = self::$sm_rgAppDisplayRules[99900]; // add staging tf2 as a copy of tf2 if ( WEB_UNIVERSE != 'public' ) { // staging tf2 self::$sm_rgAppDisplayRules[810] = self::$sm_rgAppDisplayRules[440]; } } return self::$sm_rgAppDisplayRules; } /** * @static * @param $steamId * @param $rgAppContextData * @param CEconAppsForUserLoader $wgLoader */ protected static function InitAppsAndContexts( $steamId, &$rgAppContextData, $wgLoader = null, $rgFilterApps = null ) { if ( $wgLoader ) { $rgAvailableApps = $wgLoader->Get(); } else { $rgAvailableApps = CWGEconomy::GetAppsForUser( GSiteAdaptor()->GetToken(), $steamId ); } if ( !empty( $rgFilterApps ) && is_array( $rgFilterApps ) && isset( $rgAvailableApps['apps'] ) && is_array( $rgAvailableApps['apps'] ) ) { foreach ( $rgAvailableApps['apps'] as $i => $rgApp ) { if ( !in_array( $rgApp['appid'], $rgFilterApps ) ) { unset( $rgAvailableApps['apps'][$i] ); } } } $rgAppContextData = self::FilterPrivateApps( $rgAvailableApps ); foreach ( $rgAppContextData as $rgApp ) { CAppDataCache::QueueAppRequest( $rgApp['appid'] ); } } public static function FilterPrivateApps( $rgAvailableApps ) { $rgAppContextData = array(); if( isset( $rgAvailableApps[ 'apps' ] ) && is_array( $rgAvailableApps['apps'] ) ) { foreach ( $rgAvailableApps[ 'apps' ] as $rgApp ) { if( isset( $rgApp['private'] ) && $rgApp['private'] ) { if( !BHaveCurrentUser() ) continue; if( !GetCurrentUser()->BCanSeePrivateEconomyApp( $rgApp['appid'] ) ) continue; } $rgAppContextData[] = $rgApp; } } return $rgAppContextData; } /** outputs a data-economy-item attribute which javascript will add hovers to. * @param $rgItem * @param int $appid required if rgItem does not have 'appid' set * @param int $contextid required if rgItem does not have 'contextid' set */ public static function OutputEconomyHoverAttribute( $rgItem, $appid = null, $contextid = null ) { if ( !empty( $rgItem ) && isset( $rgItem['classid'] ) ) { echo self::GetEconomyHoverAttributeForClassInfo( isset( $rgItem['appid'] ) ? $rgItem['appid'] : $appid, $rgItem['classid'], isset( $rgItem['instanceid'] ) ? $rgItem['instanceid'] : null ); } } public static function GetEconomyHoverAttributeDataForIdentifiers( $appid, $contextid, $assetid, $owner = null, $amount = null ) { $strData = $appid . '/' . $contextid . '/' . $assetid; if ( $owner ) $strData .= '/' . $owner; if ( $amount && $amount > 1 ) $strData .= '/a:' . $amount; return $strData; } public static function GetEconomyHoverAttributeDataForClassIdentifiers( $appid, $classid, $instanceid = 0, $amount = null ) { $strData = 'classinfo/' . $appid . '/' . $classid; if ( $instanceid ) $strData .= '/' . $instanceid; if ( $amount && $amount > 1 ) $strData .= '/a:' . $amount; return $strData; } public static function GetEconomyHoverAttributeForClassInfo( $appid, $classid, $instanceid = 0, $amount = null ) { $strData = 'classinfo/' . $appid . '/' . $classid; if ( $instanceid ) $strData .= '/' . $instanceid; if ( $amount && $amount > 1 ) $strData .= '/a:' . $amount; return 'data-economy-item="' . $strData . '"'; } public static function GetAppDataJSONArray( $rgAppIDs ) { $rgAppData = array(); foreach ( $rgAppIDs as $appid ) { $rgAppData[ $appid ] = self::AppDataForJSON( CAppDataCache::GetAppData( $appid ) ); } return $rgAppData; } public static function AppDataForJSON( $rgAppInfo ) { return array( 'appid' => $rgAppInfo['appid'], 'name' => $rgAppInfo['name'], 'icon' => GetAppIcon( $rgAppInfo ), 'link' => GetAppLink( $rgAppInfo ), ); } // can optionall pass in a CEconAppsForUserLoader and we will use that instead of making another WG call public static function GetUserContexts( $steamId, $wgLoader = null, $rgFilterApps = null ) { $rgAppContextData = array(); CEconomyUtils::InitAppsAndContexts( $steamId, $rgAppContextData, $wgLoader, $rgFilterApps ); // build a list of contexts that the user has a tradeable inventory in $rgAvailableContextsByApp = array(); foreach ( $rgAppContextData as $rgApp ) { $appid = $rgApp['appid']; // try regular appinfo first $rgAppInfo = CAppDataCache::GetAppData( $appid ); if ( !BIsAppVisibleToUser( $rgAppInfo ) ) { // the appinfo is private, but the user may be allowed to see it, so check again $rgResults = GetWG()->GetAppInfoSection( GSiteAdaptor()->GetToken(), $appid, 'common' ); if ( empty( $rgResults['common'] ) ) continue; $rgAppInfo = $rgResults['common']; $rgAppInfo['appid'] = $appid; //to match the GetApps response } $rgAppContextInfo = self::AppDataForJSON( $rgAppInfo ); $rgAppContextInfo['asset_count'] = 0; if ( isset( $rgApp['alerts'] ) ) $rgAppContextInfo['alerts'] = $rgApp['alerts']; if ( isset( $rgApp['inventory_logo'] ) ) $rgAppContextInfo['inventory_logo'] = APP_BASE_URL . $appid . '/' . $rgApp['inventory_logo'] . '.png'; if ( isset( $rgApp['trade_permissions'] ) ) $rgAppContextInfo['trade_permissions'] = $rgApp['trade_permissions']; else $rgAppContextInfo['trade_permissions'] = TRADE_PERMISSIONS_FULL; if ( isset( $rgApp['load_failed'] ) ) $rgAppContextInfo['load_failed'] = $rgApp['load_failed']; else $rgAppContextInfo['load_failed'] = 0; $rgContexts = array(); if ( !empty( $rgApp['contexts']) ) { foreach ( $rgApp['contexts'] as $rgContext ) { $contextid = $rgContext['id']; // eliminate contexts that aren't meant to be shown if ( empty($rgContext['user_facing']) ) continue; // prepare data for the web $rgContextData = array(); $rgContextData['asset_count'] = $rgContext['asset_count']; $rgAppContextInfo['asset_count'] += $rgContext['asset_count']; $rgContextData['id'] = $rgContext['id']; $rgContextData['name'] = $rgContext['name']; if ( $appid == k_AppId_SteamEconomy ) { // hard-coded localized names for steam contexts // econ server caching does not cache metadata with language information, so // cannot yet localize on backpack server switch ( $rgContext['id'] ) { case k_ContextId_SteamGifts: $rgContextData['name'] = Localize( '#Economy_SteamContext_Gifts' ); break; case k_ContextId_SteamCoupons: $rgContextData['name'] = Localize( '#Economy_SteamContext_Coupons' ); break; case k_ContextId_SteamCommunity: $rgContextData['name'] = Localize( '#Economy_SteamContext_Community' ); break; case k_ContextId_ItemRewards: $rgContextData['name'] = Localize( '#Economy_SteamContext_ItemRewards' ); break; } } $rgContexts[$rgContext['id']] = $rgContextData; } } // if we have some contexts (meaning we have some inventory) set up the data for the page if ( !empty( $rgApp['load_failed'] ) || !empty( $rgContexts ) ) { $rgAppContextInfo['rgContexts'] = $rgContexts; $rgAvailableContextsByApp[ $rgApp['appid'] ] = $rgAppContextInfo; } } // sort available contexts by games with the most items (should be by name?) uasort( $rgAvailableContextsByApp, function( $rgAppA, $rgAppB ) { return $rgAppB['asset_count'] - $rgAppA['asset_count']; }); return $rgAvailableContextsByApp; } public static function GetUserInventory( $steamId, $appid, $contextid, $start, &$iMoreStart, $inventoryLoadFlags = k_EInventoryLoadInventory ) { $bLowPriority = ( ( $inventoryLoadFlags & k_EInventoryLowPriority ) == k_EInventoryLowPriority ); $rgInventory = CWGEconomy::GetInventoryContentsWithDescriptions( GSiteAdaptor()->GetToken(), $steamId, $appid, $contextid, $start, $bLowPriority ); if ( !is_array( $rgInventory ) || ( isset( $rgInventory['success'] ) && $rgInventory['success'] != k_EResultOK ) ) return array( false, false, false ); // if the inventory is from a private app, don't let the user see it if ( !empty( $rgInventory['context_info']['private'] ) && ( !GSiteAdaptor()->BCanSeePrivateEconomyApp( $appid ) ) ) return array( false, false, false ); $rgDescriptionData = array(); $rgInventoryData = array(); $rgCurrencyData = array(); if ( empty( $rgInventory ) || empty( $rgInventory['asset_descriptions'] ) ) { return array( array(), array(), array() ); } if ( !empty( $rgInventory['more'] ) ) { $iMoreStart = $rgInventory['more_start']; } else { $iMoreStart = false; } self::ProcessInventoryDescriptions( $rgDescriptionData, $inventoryLoadFlags, $rgInventory['asset_descriptions'] ); // load the inventory for this app and context if ( !empty( $rgInventory ) && !empty( $rgInventory['currency'] ) && ( $inventoryLoadFlags & k_EInventoryLoadCurrency ) ) { self::ProcessInventoryData( $rgCurrencyData, $inventoryLoadFlags, $appid, $contextid, $start, $rgInventory['currency'], $rgDescriptionData, true ); } if ( !empty( $rgInventory ) && !empty( $rgInventory['assets'] ) ) { self::ProcessInventoryData( $rgInventoryData, $inventoryLoadFlags, $appid, $contextid, $start, $rgInventory['assets'], $rgDescriptionData, false ); } // now go back and remove descriptions if necessary $rgDescriptionData = self::PostProcessInventoryDescriptions( $rgDescriptionData, $inventoryLoadFlags ); return array( $rgInventoryData, $rgCurrencyData, $rgDescriptionData ); } public static function GetAssetInfo( $appid, $contextid, $rgAssetIds, $inventoryLoadFlags = k_EInventoryLoadInventory, $language = null ) { $rgResults = CWGEconomy::GetAssetInfo( GSiteAdaptor()->GetToken(), $appid, $contextid, $rgAssetIds, $language ); if ( !is_array( $rgResults ) || ( isset( $rgResults['success'] ) && $rgResults['success'] != k_EResultOK ) ) return false; // if the inventory is from a private app, don't let the user see it if ( !empty( $rgResults['context_info']['private'] ) && ( !GSiteAdaptor()->BCanSeePrivateEconomyApp( $appid ) ) ) return false; $rgAssets = array(); if ( !empty( $rgResults['assets'] ) ) { self::ProcessInventoryDescriptions( $rgAssets, $inventoryLoadFlags, $rgResults['assets'], true ); self::ProcessInventoryData( $rgAssets, $inventoryLoadFlags, $appid, $contextid, 0, $rgAssets, $rgAssets, false, true ); } foreach ( $rgAssets as &$rgAsset ) { $rgAsset['appid'] = $appid; $rgAsset['contextid'] = $contextid; } return $rgAssets; } // Like GetAssetInfo, but we'll avoid the GetAssetClass call to the asset // server and pull from the econ server's cache if possible. static function GetAssetFromInventory( $steamid, $appid, $contextid, $assetid, $inventoryLoadFlags = k_EInventoryLoadInventory, $language = null ) { // Find the item in the user's inventory $bMore = true; $iStart = 0; $strAssetId = strval( $assetid ); while ( $bMore ) { $iMoreStart = 0; $rgInventory = CWGEconomy::GetInventoryContentsWithDescriptions( GSiteAdaptor()->GetToken(), $steamid, $appid, $contextid, $iStart, false, $language ); if ( !is_array( $rgInventory ) || ( isset( $rgInventory['success'] ) && $rgInventory['success'] != k_EResultOK ) ) return false; // if the inventory is from a private app, don't let the user see it if ( !empty( $rgInventory['context_info']['private'] ) && ( !GSiteAdaptor()->BCanSeePrivateEconomyApp( $appid ) ) ) return false; $rgDescriptionData = array(); $rgInventoryData = array(); $rgCurrencyData = array(); if ( empty( $rgInventory ) || empty( $rgInventory['assets'] ) || empty( $rgInventory['asset_descriptions'] ) ) { return false; } if ( !empty( $rgInventory['more'] ) ) { $iMoreStart = $rgInventory['more_start']; } else { $bMore = false; $iMoreStart = 0; } $rgAssetData = false; $rgDescriptionData = false; // Find the right item foreach( $rgInventory['assets'] as &$rgAsset ) { if ( $rgAsset['id'] === $strAssetId ) { $rgAssetData = $rgAsset; } } if ( empty( $rgAssetData ) ) { // Didn't find the item. If we have more to look through, then go do that. continue; } // Find the right description foreach( $rgInventory['asset_descriptions'] as &$rgDescription ) { if ( $rgDescription['classid'] == $rgAssetData['classid'] && $rgDescription['instanceid'] == $rgAssetData['instanceid'] ) { $rgDescriptionData = $rgDescription; } } if ( empty( $rgDescriptionData ) ) { return false; } $rgAssets = array( $strAssetId => array_merge( $rgAssetData, $rgDescriptionData ) ); $rgItems = array(); self::ProcessInventoryDescriptions( $rgItems, $inventoryLoadFlags, $rgAssets, true ); return $rgItems; } return false; } public static function BuildInventoryFromAssetIds( $appid, $contextid, $rgAssetIds, $inventoryLoadFlags = k_EInventoryLoadInventory, $language = null ) { $ret = array(); // Make the request in smaller batches so that the econ server's request to the asset server is less likely to timeout for ( $i = 0; $i < count( $rgAssetIds ); $i += 50 ) { $rgAssetsThisBatch = array_slice( $rgAssetIds, $i, 50 ); $info = self::GetAssetInfo( $appid, $contextid, $rgAssetsThisBatch, $inventoryLoadFlags, $language ); if ( $info !== false ) { foreach ( $info as $id => $rgAsset ) { $ret[$id] = $rgAsset; } } } return $ret; } /** Expects an array of objects with values "appid", "contextid", and "assetid". * Calls GetAssetInfo for all items * If a name other than assetid is used (like "assetidnew"), that can be passed in */ public static function ConsolidateAndLoadAssets( $rgItems, $strAssetKey = 'assetid' ) { $rgInventoryToLoad = array(); // create an array of ( appid => array of ( contextid => array of assetids ) ) self::ConsolidateForLoading( $rgInventoryToLoad, $rgItems, $strAssetKey ); $rgInventory = array(); // load inventory foreach( $rgInventoryToLoad as $appid => $rgContexts ) { $rgInventory[$appid] = array(); foreach ( $rgContexts as $contextid => $rgAssetIds ) { $rgInventory[$appid][$contextid] = self::BuildInventoryFromAssetIds( $appid, $contextid, $rgAssetIds, k_EInventorySetAppAndContextIds ); } } return $rgInventory; } public static function GetCurrencyInfo( $appid, $currencyid, $inventoryLoadFlags = k_EInventoryLoadInventory, $language = null ) { $rgResults = CWGEconomy::GetCurrencyInfo( GSiteAdaptor()->GetToken(), $appid, $currencyid, $language ); if ( !is_array( $rgResults ) || ( isset( $rgResults['success'] ) && $rgResults['success'] != k_EResultOK ) ) return false; $rgCurrency = array(); if ( !empty( $rgResults['currency'] ) ) { if ( array_key_exists( 'id', $rgResults['currency'] ) ) { $rgResults['currency']['currencyid'] = $rgResults['currency']['id']; } else { $rgResults['currency']['id'] = $currencyid; $rgResults['currency']['currencyid'] = $currencyid; } $rgResults['currency']['is_stackable'] = true; self::ProcessInventoryDescriptions( $rgCurrency, $inventoryLoadFlags, $rgCurrency, true ); self::ProcessInventoryData( $rgCurrency, $inventoryLoadFlags, $appid, null, 0, array( $rgResults['currency'] ), $rgCurrency, true ); } if ( !empty( $rgCurrency[ $currencyid ] ) ) return $rgCurrency[ $currencyid ]; else return false; } public static function GetTradeHistory( $count, $rtStart, $gidStartTrade, $bNavigatingBack ) { $wgRequest = EconService::GetTradeHistory( $count, $rtStart, $gidStartTrade, $bNavigatingBack, true, CLocalizationManager::GetLanguage(), false ); $wgRequest->GetResultsAsArray(); $rgResults = $wgRequest->Get(); if ( !$wgRequest->BSuccess() || !is_array( $rgResults ) ) return array( array(), array(), array(), array(), 0, false, ($wgRequest->GetEResult()) ); if ( empty( $rgResults['trades'] ) ) $rgResults['trades'] = array(); $rgDescriptions = array(); if ( !empty( $rgResults['descriptions'] ) ) { foreach( $rgResults['descriptions'] as &$rgDescription ) { $rgDescriptions[$rgDescription['classid'] . '_' . $rgDescription['instanceid']] = &$rgDescription; } } // consolidate everything we'll need to load $rgInventory = array(); $rgCurrency = array(); $rgPlayersToLoad = array(); $rgTrades = array(); foreach ( $rgResults['trades'] as $idx => &$rgTrade ) { if ( !empty( $rgTrade['assets_given'] ) ) { self::ConsolidateWithDescriptions( $rgInventory, $rgTrade['assets_given'], 'assetid', $rgDescriptions, $rgTrade['steamid_other'] ); } else { $rgTrade['assets_given'] = array(); } if ( !empty( $rgTrade['assets_received'] ) ) { // We might not have assetidnew if the trade is still in escrow. Set assetidnew to something else that we can identify the item with foreach ( $rgTrade['assets_received'] as &$rgItem ) { if ( empty( $rgItem['new_assetid'] ) ) { $rgItem['new_assetid'] = "class_" . $rgItem['classid']; if ( !empty( $rgItem['instanceid'] ) ) { $rgItem['new_assetid'] .= '_instance_' . $rgItem['instanceid']; } } } self::ConsolidateWithDescriptions( $rgInventory, $rgTrade['assets_received'], 'new_assetid', $rgDescriptions, GetCurrentUserSteamID() ); } else { $rgTrade['assets_received'] = array(); } if ( !empty( $rgTrade['currency_given'] ) ) { self::ConsolidateCurrencyWithDescriptions( $rgCurrency, $rgTrade['currency_given'], $rgDescriptions ); } else { $rgTrade['currency_given'] = array(); } if ( !empty( $rgTrade['currency_received'] ) ) { self::ConsolidateCurrencyWithDescriptions( $rgCurrency, $rgTrade['currency_received'], $rgDescriptions ); } else { $rgTrade['currency_received'] = array(); } if ( !isset( $rgPlayersToLoad[ $rgTrade['steamid_other'] ] ) ) $rgPlayersToLoad[ $rgTrade['steamid_other'] ] = new CSteamID( $rgTrade['steamid_other'] ); $rgTrades[] = $rgTrade; } $rgAppIds = array(); foreach( $rgInventory as $appid => &$rgAppInventory ) { CAppDataCache::QueueAppRequest( $appid ); $rgAppIds[$appid] = true; } foreach( $rgCurrency as $appid => &$rgAppCurrency ) { CAppDataCache::QueueAppRequest( $appid ); $rgAppIds[$appid] = true; } // load appinfo $rgAppData = self::GetAppDataJSONArray( array_keys( $rgAppIds ) ); // load players (trading partners) GSiteAdaptor()->HintLoadPlayers( $rgPlayersToLoad ); $cTotalRecords = isset( $rgResults['total_trades'] ) ? $rgResults['total_trades'] : 0; return array( $rgTrades, $rgInventory, $rgCurrency, $rgAppData, $cTotalRecords, $rgResults['more'], k_EResultOK ); } /** Expects a steam user. Returns a url, and outputs get parameters and a hashtag string for passing to RedirectAndHalt(). * Calls GetAssetInfo for all items * If a name other than assetid is used (like "assetidnew"), that can be passed in */ public static function GetPostMicroTxnPurchaseCommunityProfileURL( $communityBaseURL, $rgFinalizeTxnResult, $steamid, $appid, &$rgRedirectArgs, &$redirectHash ) { // Build up the URL based on the contents of $result. $profile_url = $communityBaseURL . 'profiles/' . $steamid->ConvertTo64BitString() . '/'; $url = $profile_url . "inventory/"; $rgRedirectArgs = array(); $rgRedirectArgs['showpurchasemsg'] = 1; if ( isset( $rgFinalizeTxnResult['displaytext'] ) && strlen( $rgFinalizeTxnResult['displaytext'] ) ) { // Add user-facing message, already localized $rgRedirectArgs['purchasemsg'] = $rgFinalizeTxnResult['displaytext']; } // Select the first asset that was returned, if there is one. Pin this onto the end of the URL, for JavaScript. $hash = ""; if ( array_key_exists( 'assets', $rgFinalizeTxnResult ) && is_array( $rgFinalizeTxnResult['assets'] ) && count( $rgFinalizeTxnResult['assets'] ) > 0 ) { $asset = $rgFinalizeTxnResult['assets'][0]; $redirectHash = $appid . "_" . $asset['contextid'] . "_" . $asset['assetid']; } return $url; } protected static function ConsolidateForLoading( &$rgInventoryToLoad, $rgItems, $strAssetKey = 'assetid' ) { foreach ( $rgItems as $rgItem ) { $appid = $rgItem['appid']; $contextid = $rgItem['contextid']; $assetid = $rgItem[ $strAssetKey ]; if ( !isset( $rgInventoryToLoad[$appid] ) ) $rgInventoryToLoad[$appid] = array( ); if ( !isset( $rgInventoryToLoad[$appid][$contextid] ) ) $rgInventoryToLoad[$appid][$contextid] = array( ); $rgInventoryToLoad[$appid][$contextid][] = $assetid; } } protected static function ConsolidateWithDescriptions( &$rgInventory, $rgItems, $strAssetKey, $rgDescriptionsByClass, $strOwnerSteamId ) { foreach ( $rgItems as $rgItem ) { $appid = $rgItem['appid']; $contextid = $rgItem['contextid']; $assetid = $rgItem[$strAssetKey]; $classid = isset( $rgItem['classid'] ) ? $rgItem['classid'] : $rgItem['assetclass']; $instanceid = isset( $rgItem['instanceid'] ) ? $rgItem['instanceid'] : $rgItem['assetinstance']; if ( !isset( $rgInventory[$appid] ) ) $rgInventory[$appid] = array( ); if ( !isset( $rgInventory[$appid][$contextid] ) ) $rgInventory[$appid][$contextid] = array( ); $rgInventory[$appid][$contextid][$assetid] = array_merge( array( 'id' => $assetid, 'contextid' => $rgItem['contextid'], 'amount' => $rgItem['amount'], 'owner' => $strOwnerSteamId ), $rgDescriptionsByClass[$classid . '_' . $instanceid] ); } } protected static function ConsolidateCurrencyWithDescriptions( &$rgCurrency, $rgCurrencies, $rgDescriptionsByClass ) { foreach ( $rgCurrencies as $rgThisCurrency ) { $appid = $rgThisCurrency['appid']; $currencyid = $rgThisCurrency['currencyid']; $classid = isset( $rgThisCurrency['classid'] ) ? $rgThisCurrency['classid'] : $rgThisCurrency['assetclass']; if ( !isset( $rgCurrency[$appid] ) ) $rgCurrency[$appid] = array( ); $rgCurrency[$appid][$currencyid] = array_merge( array( 'id' => $currencyid, 'currencyid' => $currencyid ), $rgDescriptionsByClass[$classid . '_' . 0] ); } } protected static function ConsolidateCurrencyForLoading( &$rgCurrencyToLoad, $rgCurrencies ) { foreach ( $rgCurrencies as $rgCurrency ) { $appid = $rgCurrency['appid']; $currencyid = $rgCurrency['currencyid']; if ( !isset( $rgCurrencyToLoad[$appid] ) ) $rgCurrencyToLoad[$appid] = array(); if ( !isset( $rgCurrencyToLoad[$appid][$currencyid] ) ) $rgCurrencyToLoad[$appid][$currencyid] = true; } } public static function ProcessInventoryData( &$rgInventoryData, $inventoryLoadFlags, $appid, $contextid, $start, $rgInventory, $rgDescriptions, $bIsCurrency = false, $bIsCombinedData = false ) { $sortOrder = $start; foreach ( $rgInventory as $rgItem ) { $classid = ( array_key_exists( 'currencyid', $rgItem ) ? $rgItem['currencyid'] : $rgItem['classid'] ); $instanceid = ( array_key_exists( 'instanceid', $rgItem ) ? $rgItem['instanceid'] : 0 ); if ( $bIsCombinedData ) $rgDescriptionKey = $rgItem['id']; else $rgDescriptionKey = $classid . '_' . $instanceid; $rgDescription = isset( $rgDescriptions[ $rgDescriptionKey ] ) ? $rgDescriptions[$rgDescriptionKey] : null; if ( ( $inventoryLoadFlags & k_EInventoryLoadTradableOnly ) && empty( $rgItem['tradable'] ) && // make sure tradable isn't set on the item empty( $rgDescription['tradable'] ) ) // make sure tradable isn't set on the description continue; if ( ( $inventoryLoadFlags & k_EInventoryLoadMarketableOnly ) && empty( $rgItem['marketable'] ) && // make sure marketable isn't set on the item empty( $rgDescription['marketable'] ) ) // make sure marketable isn't set on the description continue; if ( $appid == 753 && ( $classid == 176056164 || $classid == 667078269 ) && !($inventoryLoadFlags & k_EInventoryLoadOwnerData) ) //goo continue; if ( $bIsCurrency ) { $rgItem['is_currency'] = true; // only the owner of the inventory can see the amount of currency they have if ( !($inventoryLoadFlags & k_EInventoryLoadOwnerData) ) unset ( $rgItem['amount'] ); } if ( $inventoryLoadFlags & k_EInventorySetAppAndContextIds ) { $rgItem['appid'] = $appid; if ( $contextid ) $rgItem['contextid'] = $contextid; } $rgItem['pos'] = ++$sortOrder; $rgInventoryData[ $rgItem['id'] ] = $rgItem; } } /** * @param CEconItem_Description[] $rgDescriptions */ public static function ProcessEconItemDescriptions( &$rgDescriptions ) { foreach ( $rgDescriptions as &$rgDescription ) { self::ProcessItemAssetClassInfo( $rgDescription ); } } public static function ProcessItemAssetClassInfo( &$rgItem ) { // Make sure name is set and valid $strItemName = !empty( $rgItem['name'] ) ? $rgItem['name'] : ''; if ( !mb_check_encoding( $strItemName, 'UTF-8' ) ) $strItemName = mb_convert_encoding( $strItemName, 'UTF-8', 'UTF-8' ); $rgItem['name'] = $strItemName; if ( !empty( $rgItem['market_name'] ) ) { // Replace market_name if it has bogus characters $strItemMarketName = $rgItem['market_name']; if ( !mb_check_encoding( $strItemMarketName, 'UTF-8' ) ) { $strItemMarketName = mb_convert_encoding( $strItemMarketName, 'UTF-8', 'UTF-8' ); $rgItem['market_name'] = $strItemMarketName; } } if ( !empty( $rgItem['market_hash_name'] ) ) { // Replace market_hash_name if it has bogus characters $strItemMarketHashName = $rgItem['market_hash_name']; if ( !mb_check_encoding( $strItemMarketHashName, 'UTF-8' ) ) { $strItemMarketHashName = mb_convert_encoding( $strItemMarketHashName, 'UTF-8', 'UTF-8' ); $rgItem['market_hash_name'] = $strItemMarketHashName; } } // catch bogus color values if ( !empty( $rgItem['name_color'] ) && !preg_match( '/[0-9A-Fa-f]{6}/', $rgItem['name_color'] ) ) unset( $rgItem['name_color'] ); foreach ( array( 'actions', 'owner_actions', 'market_actions' ) as $actionType ) { if ( !empty( $rgItem[$actionType] ) ) { foreach ( $rgItem[$actionType] as $index => $rgAction ) { // localize old action names. TODO: backpack server should localize these itself. if ( !empty( $rgAction['name'] ) && $rgAction['name'][0] == '#' ) $rgItem[$actionType][$index]['name'] = Localize( $rgAction['name'] ); // prefix external links with steam://openurl if ( isset( $rgAction['link'] ) && BIsUserInSteamClient() && strncmp( $rgAction['link'], 'steam://', 8 ) !== 0 && strncmp( $rgAction['link'], 'javascript:', 11 ) !== 0) { $rgItem[$actionType][$index]['link'] = 'steam://openurl/' . $rgAction['link']; } } } } foreach ( array( 'descriptions', 'owner_descriptions' ) as $desctype ) { if ( !empty( $rgItem[$desctype] ) ) { foreach ( $rgItem[$desctype] as $iDescription => $rgDescription ) { if ( !isset( $rgDescription['value'] ) ) continue; // Fix any broken UTF-8 characters $strDescriptionValue = $rgDescription['value']; if ( !mb_check_encoding( $strDescriptionValue, 'UTF-8' ) ) { $strDescriptionValue = mb_convert_encoding( $strDescriptionValue, 'UTF-8', 'UTF-8' ); $rgItem[$desctype][$iDescription]['value'] = $strDescriptionValue; } if ( $rgDescription['type'] == 'bbcode' ) { $rgItem[$desctype][$iDescription]['type'] = 'html'; $rgItem[$desctype][$iDescription]['value'] = CFormattingTools::FormatEconDescriptionBBCode( $strDescriptionValue ); } if ( isset( $rgDescription['type'] ) && $rgDescription['type'] == 'text' ) unset( $rgItem[$desctype][$iDescription]['type'] ); if ( isset( $rgDescription['time_tradable'] ) ) { $rgItem[$desctype][$iDescription]['type'] = 'html'; $rgItem[$desctype][$iDescription]['value'] = self::GetGiftNotTradableNotice( $rgDescription['time_tradable'] ); unset( $rgItem[$desctype][$iDescription]['time_tradable'] ); } if ( isset( $rgItem[$desctype][$iDescription]['app_data'] ) && empty( $rgItem[$desctype][$iDescription]['app_data'] ) ) unset( $rgItem[$desctype][$iDescription]['app_data'] ); } } } if ( !empty( $rgItem['fraudwarnings'] ) ) { foreach ( $rgItem['fraudwarnings'] as &$strFraudWarning ) { // Fix any broken UTF-8 characters if ( !mb_check_encoding( $strFraudWarning, 'UTF-8' ) ) { $strFraudWarning = mb_convert_encoding( $strFraudWarning, 'UTF-8', 'UTF-8' ); } } } if ( isset( $rgItem['icon_url'] ) ) $rgItem['icon_url'] = trim( $rgItem['icon_url'] ); if ( isset( $rgItem['icon_url_large'] ) ) $rgItem['icon_url_large'] = trim( $rgItem['icon_url_large'] ); // clean up some unnecessary data - the web will default if ( empty( $rgItem['fraudwarnings'] ) ) unset( $rgItem['fraudwarnings'] ); if ( empty( $rgItem['icon_url_large'] ) ) unset( $rgItem['icon_url_large'] ); // None of the Community code uses app_data, so strip it. // Leave some app_data fields which community members have been or might be using. if ( !empty( $rgItem['app_data'] ) && isset( $rgItem['appid'] ) && $rgItem['appid'] != k_AppId_SteamEconomy ) { $rgAppData = $rgItem['app_data']; unset( $rgItem['app_data'] ); $rgItem['app_data'] = array(); if ( !empty( $rgAppData['quantity'] ) ) $rgItem['app_data']['quantity'] = $rgAppData['quantity']; if ( !empty( $rgAppData['def_index'] ) ) $rgItem['app_data']['def_index'] = $rgAppData['def_index']; if ( !empty( $rgAppData['quality'] ) ) $rgItem['app_data']['quality'] = $rgAppData['quality']; if ( count( $rgItem['app_data'] ) == 0 ) { unset( $rgItem['app_data'] ); } } } public static function ProcessInventoryDescriptions( &$rgDescriptionData, $inventoryLoadFlags, $rgDescriptions, $bIsCombinedData = false ) { foreach ( $rgDescriptions as $rgItem ) { if ( !is_array( $rgItem ) ) $rgItem = array(); $classid = ( isset( $rgItem['currencyid'] ) ? $rgItem['currencyid'] : ( isset( $rgItem['classid'] ) ? $rgItem['classid'] : 0 ) ); $instanceid = ( isset( $rgItem['instanceid'] ) ? $rgItem['instanceid'] : 0 ); CEconomyUtils::ProcessItemAssetClassInfo( $rgItem ); if ( !($inventoryLoadFlags & k_EInventoryLoadActions) ) { unset( $rgItem['actions'] ); unset( $rgItem['owner_actions'] ); unset( $rgItem['market_actions'] ); } else if ( !($inventoryLoadFlags & k_EInventoryLoadOwnerData) ) { unset( $rgItem['owner_actions'] ); } if ( !($inventoryLoadFlags & k_EInventoryLoadOwnerData) ) { unset( $rgItem['owner_descriptions'] ); } if ( $bIsCombinedData ) $rgDescriptionData[ $rgItem['id'] ] = $rgItem; else $rgDescriptionData[ $classid . '_' . $instanceid ] = $rgItem; } } protected static function PostProcessInventoryDescriptions( &$rgDescriptionData, $inventoryLoadFlags ) { $ret = array(); foreach ( $rgDescriptionData as $key => $rgItem ) { if ( ( $inventoryLoadFlags & k_EInventoryLoadTradableOnly ) && ( empty( $rgItem['tradable'] ) || !$rgItem['tradable'] ) ) continue; if ( ( $inventoryLoadFlags & k_EInventoryLoadMarketableOnly ) && ( empty( $rgItem['marketable'] ) || !$rgItem['marketable'] ) ) continue; // skip currencies if that load flag wasn't specified if ( !( $inventoryLoadFlags & k_EInventoryLoadCurrency ) && !empty( $rgItem['is_currency'] ) && $rgItem['is_currency'] ) continue; unset( $rgItem['is_currency'] ); $ret[ $key ] = $rgItem; } return $ret; } private static function GetGiftNotTradableNotice( $time_tradable ) { $str = '
' . Localize( '#Economy_Inventory_NotTradable' ) . '
'; if ( $time_tradable != -1 ) $str .= '
' . LocalizeFmt( '#Economy_Inventory_GiftNotTradableNote_Flat', 30, LocalizeShortDate( $time_tradable ) ) . '
'; return $str; } public static function RenderItemInfoBlock( $name, $class, $rgParams = array(), $rgAsset = null ) { $bShowFraudWarnings = isset( $rgParams['fraudwarnings'] ) ? !empty( $rgParams['fraudwarnings'] ) : true; $bShowActions = !empty( $rgParams['actions'] ); $bShowOwnerInfo = !empty( $rgParams['ownerinfo'] ); $bShowMarket = !empty( $rgParams['showmarket'] ); $bShowAddToTrade = !empty( $rgParams['addtotrade'] ); $bHideOwnerActions = !empty( $rgParams['hideowneractions'] ); require( 'templates/partials/economy_iteminfo_block.php' ); } public static function GetPendingAndSentGifts( $token ) { return self::LoadGiftData( $token, true, false ); } public static function GetPendingGifts( $token ) { $results = self::LoadGiftData( $token, false, false ); return $results[0]; } public static function GetSentGiftHistory( $token ) { $results = self::LoadGiftData( $token, true, true ); return $results[1]; } public static function LoadGiftData( $token, $bLoadPendingSentGifts = false, $bLoadSentGiftHistory = false ) { $rgPendingGifts = null; if ( !$bLoadSentGiftHistory ) { $rgPendingGifts = CWGGifts::GetGiftsRedeemable( $token, true ); } $rgPendingSentGifts = null; if ( $bLoadPendingSentGifts ) { $rgPendingSentGifts = CWGGifts::GetGiftsSent( $token, $bLoadSentGiftHistory ); } if ( !is_array( $rgPendingGifts ) ) $rgPendingGifts = array(); if ( !is_array( $rgPendingSentGifts ) ) $rgPendingSentGifts = array(); if ( !empty( $rgPendingGifts ) || !empty( $rgPendingSentGifts ) ) { $rgGiftGIDs = array(); $rgSteamIDs = array(); foreach( $rgPendingGifts as $rgPendingGift ) { $rgGiftGIDs[] = $rgPendingGift['gid']; $rgSteamIDs[] = $rgPendingGift['sender']; } foreach ( $rgPendingSentGifts as $rgSentGift ) { $rgGiftGIDs[] = $rgSentGift['gid']; $steamid = new CSteamID( $rgSentGift['steamid_sentto'] ); if ( $steamid->BIsValid() ) { $rgSteamIDs[] = $steamid; } } GSiteAdaptor()->HintLoadPlayers( $rgSteamIDs ); $rgPendingGiftAssets = self::BuildInventoryFromAssetIds( k_AppId_SteamEconomy, k_ContextId_SteamGifts, $rgGiftGIDs, k_EInventoryLoadInventory | k_EInventorySetAppAndContextIds | k_EInventoryLoadActions, CLocalizationManager::GetLanguage() ); foreach ( $rgPendingGifts as &$rgPendingGift ) { $rgPendingGift['asset'] = $rgPendingGiftAssets[$rgPendingGift['gid']]; } foreach ( $rgPendingSentGifts as &$rgSentGift ) { if ( isset( $rgPendingGiftAssets[$rgSentGift['gid'] ] ) ) $rgSentGift['asset'] = $rgPendingGiftAssets[$rgSentGift['gid']]; } } return array( $rgPendingGifts, $rgPendingSentGifts ); } // By default, the image will be sized to best fit the dimensions given. Append an 'f' to the width or height to pad // any extra space with transparent pixels. public static function BuildAssetImageURL( $iconUrl, $width = '128', $height = '128' ) { return BASE_URL_COMMUNITY_CDN_SECURE . 'economy/image/' . $iconUrl . '/' . $width . 'x' . $height; } // same as above, but from class info public static function BuildAssetImageURLForClass( $appid, $classid, $width = null, $height = null ) { $strURL = BASE_URL_COMMUNITY_CDN_SECURE . 'economy/image/class/' . $appid . '/' . $classid; if ( $width || $height ) { $strURL .= '/' . $width . 'x' . $height; } $strURL .= '?language=' . CLocalizationManager::GetLanguage(); return $strURL; } public static function AssetImgSrcAttributes( $iconUrl, $width = 128, $height = 128 ) { $fullUrl = BASE_URL_COMMUNITY_CDN_SECURE . 'economy/image/' . $iconUrl . '/'; $str1xURL = $fullUrl . $width . 'fx' . $height . 'f'; $str2xURL = $str1xURL . 'dpx2x'; return 'src="' . $str1xURL . '" srcset="' . $str1xURL . ' 1x, ' . $str2xURL . ' 2x"'; } public static function AssetImgSrcAttributesForClass( $appid, $classid, $width = 128, $height = 128 ) { $fullUrl = BASE_URL_COMMUNITY_CDN_SECURE . 'economy/image/class/' . $appid . '/' . $classid . '/'; $str1xURL = $fullUrl . $width . 'fx' . $height . 'f'; $str2xURL = $str1xURL . 'dpx2x'; return 'src="' . $str1xURL . '" srcset="' . $str1xURL . ' 1x, ' . $str2xURL . ' 2x"'; } public static function GetDisplayStringForTradeResponseAndInfo( $appid, $eTradeResponse, $strPartnerName, $nSteamguardRequiredDays, $nNewDeviceCooldownDays, $nDefaultPasswordResetProbationDays, $nPasswordResetProbationDays, $nEmailChangeProbationDays ) { switch ( $eTradeResponse ) { case k_EEconTradeResponse_Declined: $strError = LocalizeFmt( "#friends_trade_declined", $strPartnerName ); break; case k_EEconTradeResponse_CyberCafe_Initiator: $strError = LocalizeFmt( "#friends_trade_you_are_cafe", $strPartnerName ); break; case k_EEconTradeResponse_CyberCafe_Target: $strError = LocalizeFmt( "#friends_trade_they_are_cafe", $strPartnerName ); break; case k_EEconTradeResponse_SchoolLab_Initiator: $strError = LocalizeFmt( "#friends_trade_you_are_school", $strPartnerName ); break; case k_EEconTradeResponse_SchoolLab_Target: $strError = LocalizeFmt( "#friends_trade_they_are_school", $strPartnerName ); break; case k_EEconTradeResponse_TradeBanned_Initiator: $strError = LocalizeFmt( "#friends_trade_you_are_banned", $strPartnerName ); break; case k_EEconTradeResponse_TradeBanned_Target: $strError = LocalizeFmt( "#friends_trade_they_are_banned", $strPartnerName ); break; case k_EEconTradeResponse_Target_Already_Trading: $strError = LocalizeFmt( "#friends_trade_they_are_trading", $strPartnerName ); break; case k_EEconTradeResponse_Disabled: $strError = LocalizeFmt( "#friends_trade_disabled", $strPartnerName ); break; case k_EEconTradeResponse_NotLoggedIn: $strError = LocalizeFmt( "#friends_trade_not_logged_in", $strPartnerName ); break; case k_EEconTradeResponse_Cancel: $strError = LocalizeFmt( "#friends_trade_cancelled", $strPartnerName ); break; case k_EEconTradeResponse_TooSoon: $strError = LocalizeFmt( "#friends_trade_too_soon", $strPartnerName ); break; case k_EEconTradeResponse_TooSoonPenalty: $strError = LocalizeFmt( "#friends_trade_too_soon_penalty", $strPartnerName ); break; case k_EEconTradeResponse_ConnectionFailed: $strError = LocalizeFmt( "#friends_trade_connection_failed", $strPartnerName ); break; case k_EEconTradeResponse_Already_Trading: $strError = LocalizeFmt( "#friends_trade_you_are_already_trading", $strPartnerName ); break; case k_EEconTradeResponse_Already_Has_Trade_Request: $strError = LocalizeFmt( "#friends_trade_you_are_already_requesting_trade", $strPartnerName ); break; case k_EEconTradeResponse_NoResponse: $strError = LocalizeFmt( "#friends_trade_no_respond", $strPartnerName ); break; case k_EEconTradeResponse_Initiator_Blocked_Target: $strError = LocalizeFmt( "#friends_trade_they_are_blocked", $strPartnerName ); break; case k_EEconTradeResponse_Initiator_Needs_Verified_Email: $strError = LocalizeFmt( "#friends_trade_you_need_verified_email", $strPartnerName ); break; case k_EEconTradeResponse_Initiator_Needs_Steam_Guard: $strError = LocalizeFmt( "#friends_trade_you_have_steam_guard_disabled", $strPartnerName ); break; case k_EEconTradeResponse_Target_Account_Cannot_Trade: $strError = LocalizeFmt( "#friends_trade_their_account_cannot_trade", $strPartnerName, $strPartnerName ); break; case k_EEconTradeResponse_Initiator_Steam_Guard_Duration: $strError = LocalizeFmt( '#friends_trade_you_havent_had_steam_guard_enabled_long_enough', $nSteamguardRequiredDays ); break; case k_EEconTradeResponse_Initiator_Recent_Password_Reset: if ( !empty( $nDefaultPasswordResetProbationDays ) && !empty( $nPasswordResetProbationDays ) ) { if ( $nPasswordResetProbationDays > $nDefaultPasswordResetProbationDays ) { $strError = LocalizeFmt( "#friends_trade_you_recently_reset_password_long", $nPasswordResetProbationDays ); } else if ( $nPasswordResetProbationDays == 1 ) { $strError = Localize( "#friends_trade_you_recently_reset_password_oneday" ); } else { $strError = LocalizeFmt( "#friends_trade_you_recently_reset_password_short", $nPasswordResetProbationDays ); } } else { $strError = Localize( "#friends_trade_you_recently_reset_password" ); } break; case k_EEconTradeResponse_Initiator_Recent_Email_Change: if ( !empty( $nEmailChangeProbationDays ) ) { if ( $nEmailChangeProbationDays == 1 ) { $strError = Localize( "#friends_trade_you_recently_changed_email_oneday" ); } else { $strError = LocalizeFmt( "#friends_trade_you_recently_changed_email_days", $nEmailChangeProbationDays ); } } else { $strError = Localize( "#friends_trade_you_recently_changed_email" ); } break; case k_EEconTradeResponse_Initiator_Using_New_Device: $strError = LocalizeFmt( '#friends_trade_you_are_using_new_device', $nNewDeviceCooldownDays ); break; case k_EEconTradeResponse_TradingHoldForClearedTradeOffers_Initiator: $strError = LocalizeFmt( '#friends_trade_trade_hold_for_cleared_trades_initiator', $strPartnerName ); break; case k_EEconTradeResponse_WouldExceedMaxAssetCount: $appName = CAppDataCache::GetAppName( $appid ); $strError = LocalizeFmt( '#friends_trade_would_exceed_max_asset_count', $appName ); break; case k_EEconTradeResponse_OKToDeliver: case k_EEconTradeResponse_Initiator_Sent_Invalid_Cookie: default: $strError = LocalizeFmt( "#friends_trade_generic_failure", $strPartnerName ) . " (" . k_EEconTradeResponse_OKToDeliver . ")"; break; } return $strError; } /** * @param int $appid * @param int $trade_response * @param CSteamID $steamidPartner * @return null|string */ public static function GetDisplayStringForTradeResponse( $appid, $trade_response, $steamidPartner ) { if ( !$steamidPartner || !$steamidPartner->BIsIndividualID() ) return null; $CanTradeResults = EconService::CanUserTradeWithPartner( $steamidPartner ); CPlayerCache::PreLoadPlayerLink( $steamidPartner->GetAccountID() ); if ( $CanTradeResults->BSuccess() ) { // It's expected that CanUserTradeWithPartner will not return the "using new device" or // "would exceed max asset count" error, so allow those differences, but no others. if ( $trade_response != k_EEconTradeResponse_Initiator_Using_New_Device && $trade_response != k_EEconTradeResponse_WouldExceedMaxAssetCount ) { AssertAndConsolidateByMsg( $trade_response == $CanTradeResults->Get()->trade_response, 'Blocking user for trade response ' . $trade_response . ' even though CanUserTrade reports ' . $CanTradeResults->Get()->trade_response ); } return CEconomyUtils::GetDisplayStringForTradeResponseAndInfo( $appid, $trade_response, CPlayerCache::GetPlayerLink( $steamidPartner->GetAccountID() )->getPersonaName(), $CanTradeResults->Get()->steamguard_required_days, $CanTradeResults->Get()->new_device_cooldown_days, $CanTradeResults->Get()->default_password_reset_probation_days, $CanTradeResults->Get()->password_reset_probation_days, $CanTradeResults->Get()->email_change_probation_days ); } return null; } /** * @param $PartnerTrustworthiness CEcon_CheckTradePartnerTrustworthiness_Response_LazyLoader * @return bool */ public static function BPartnerTrustworthinessShouldWarnOnLoad( $PartnerTrustworthiness ) { if ( !$PartnerTrustworthiness || !$PartnerTrustworthiness->BSuccess() ) return false; return $PartnerTrustworthiness->Get()->trade_abuse_score >= 3; // has recently been reported } /** * @param $PartnerTrustworthiness CEcon_CheckTradePartnerTrustworthiness_Response_LazyLoader * @return bool */ public static function BPartnerTrustworthinessShouldWarnOnReady( $PartnerTrustworthiness ) { if ( !$PartnerTrustworthiness || !$PartnerTrustworthiness->BSuccess() ) return false; return $PartnerTrustworthiness->Get()->keyword_abuse_score > 0 || $PartnerTrustworthiness->Get()->trade_abuse_score >= 3 || $PartnerTrustworthiness->Get()->abuse_score >= 3; } private static $sm_nItemRewardEventID = k_EVirtualItemRewardEvent_Summer2014; private static $sm_rgItemREwardEventJSONData = null; /** @var CQuest_GetVirtualItemRewardGrantCounts_Response_LazyLoader */ private static $sm_ItemRewardEventLoader = null; public static function HintLoadItemRewardEventData() { if ( !defined( 'VIRTUAL_ITEM_REWARD_EVENT_ACTIVE' ) || !VIRTUAL_ITEM_REWARD_EVENT_ACTIVE ) return; if ( !self::$sm_rgItemREwardEventJSONData && !self::$sm_ItemRewardEventLoader ) { self::$sm_rgItemREwardEventJSONData = GetSharedObjectCache()->GetObject( 'wintersale_reward_data_' . CLocalizationManager::GetLanguage() ); if ( !self::$sm_rgItemREwardEventJSONData ) { self::$sm_ItemRewardEventLoader = QuestService::GetVirtualItemRewardGrantCounts( self::$sm_nItemRewardEventID ); self::$sm_ItemRewardEventLoader->SetTimeoutMS( 10000 ); } } } public static function GetItemRewardEventDataAsArray() { if ( !defined( 'VIRTUAL_ITEM_REWARD_EVENT_ACTIVE' ) || !VIRTUAL_ITEM_REWARD_EVENT_ACTIVE ) return null; if ( !self::$sm_rgItemREwardEventJSONData ) { if ( !self::$sm_ItemRewardEventLoader ) self::$sm_ItemRewardEventLoader = QuestService::GetVirtualItemRewardGrantCounts( self::$sm_nItemRewardEventID ); self::$sm_rgItemREwardEventJSONData = self::WinterSaleRewardsToJSONArray( self::$sm_ItemRewardEventLoader ); if ( !empty( self::$sm_rgItemREwardEventJSONData ) ) GetSharedObjectCache()->StoreObject( 'wintersale_reward_data_' . CLocalizationManager::GetLanguage(), self::$sm_rgItemREwardEventJSONData, 30 ); } return self::$sm_rgItemREwardEventJSONData; } public static function GetItemRewardEventData() { if ( !defined( 'VIRTUAL_ITEM_REWARD_EVENT_ACTIVE' ) || !VIRTUAL_ITEM_REWARD_EVENT_ACTIVE ) return null; return json_encode( self::GetItemRewardEventDataAsArray() ); } /** * @param $RewardLoader CQuest_GetVirtualItemRewardGrantCounts_Response_LazyLoader * @return string */ public static function WinterSaleRewardsToJSONArray( $RewardLoader ) { $rgResults = array(); if ( $RewardLoader && $RewardLoader->BSuccess() && !empty( $RewardLoader->Get()->rewards ) ) { foreach( $RewardLoader->Get()->rewards as $Reward ) { if ( $Reward->market_hash_name ) { $rgResults[ $Reward->econ_appid ][ $Reward->market_hash_name ] = array( 'item_reward_event_baseapp' => $Reward->appid, 'item_reward_event_rarity' => $Reward->rarity, 'item_reward_event_rarity_desc' => Localize( '#economy_itemreward_rarity' . $Reward->rarity ), 'item_reward_event_craftcount_desc' => LocalizeFmt( '#Promo_Winter2013_Rewards_XItemsCrafted', number_format( $Reward->creation_count ) ), ); } } } return $rgResults; } public static function GetMarketRestrictionData( $controller, $rgMarketplaceAllowed ) { $bMarketAllowed = ($rgMarketplaceAllowed == false || $rgMarketplaceAllowed['allowed']); /* if ( !$bMarketAllowed ) { $rgMarketplaceAllowed['reason'] = 0xffffffff; $rgMarketplaceAllowed['reason'] = $rgMarketplaceAllowed['reason'] & ~k_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified; } */ /* $rgMarketplaceAllowed['sales_this_year'] = $rgMarketplaceAllowed['max_sales_per_year'] * .75 + 1; $rgMarketplaceAllowed['forms_require_verification'] = 1; */ $bAccountLocked = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AccountDisabled || $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AccountLockedDown ); $bAccountLimited = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AccountLimited ); $bTradeBannedAccount = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_TradeBanned ); $bUntrustedAccount = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AccountNotTrusted ); $bRecentPasswordReset = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_RecentPasswordReset ); $bNewPaymentMethod = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_NewPaymentMethod ); $bAcceptedWalletGift = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AcceptedWalletGift ); $bLimitedAccount = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_AccountLimited ); $bSteamGuardOnlyRecentlyEnabled = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled ); $bSteamGuardNotEnabledAtAll = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_SteamGuardNotEnabled ); $bSteamGuardIsEnabled = !$bSteamGuardNotEnabledAtAll; // code legibility $bInvalidSteamGuardCookie = !$bMarketAllowed && $bSteamGuardIsEnabled && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_InvalidCookie ); $bUsingNewDevice = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_UsingNewDevice ); $bRecentSelfRefund = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_RecentSelfRefund ); $bSteamguardDisabled = !$bMarketAllowed && ( ($rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_SteamGuardNotEnabled) || ($rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled) ); $bNoRecentPurchasesAtAll = !$bMarketAllowed && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_NoRecentPurchases ); $bAnyRecentPurchase = !$bNoRecentPurchasesAtAll; // code legibility // Don't display the time the user can use the market if it's 30 days out. // This would indicate that the user hasn't actually made a purchase on Steam in the last year, so the time they can really use the market is 30 days after the next purchase. $bWeKnowWhenUserCanUseMarket = !$bMarketAllowed && !$bAccountLocked && $bSteamGuardIsEnabled && !$bLimitedAccount && !$bInvalidSteamGuardCookie && (!$bUntrustedAccount || $bAnyRecentPurchase); $rgRestrictions = array( 'locked' => $bAccountLocked, 'banned' => $bTradeBannedAccount, 'trusted' => $bUntrustedAccount && !$bWeKnowWhenUserCanUseMarket, 'trustedwaiting' => $bUntrustedAccount && $bWeKnowWhenUserCanUseMarket, 'pwreset' => $bRecentPasswordReset, 'newpaymentmethod' => $bNewPaymentMethod && !( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified ), 'newpaymentnoverify' => $bNewPaymentMethod && ( $rgMarketplaceAllowed['reason'] & k_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified ), 'acceptedwalletgift' => $bAcceptedWalletGift, 'cookie' => $bInvalidSteamGuardCookie, 'newdevice' => $bUsingNewDevice, 'selfrefund' => $bRecentSelfRefund, 'limiteduser' => $bAccountLimited, 'sgrecent' => $bSteamGuardOnlyRecentlyEnabled, 'sgdisabled' => $bSteamguardDisabled, ); $rgRestrictionData = array( 'locked' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_AccountLocked' ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_AccountLocked' ), 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_AccountLocked' ), 'link' => 'https://support.steampowered.com/newticket.php?category=15', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_RemoveRestrictionLink' ) ), 'banned' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_AccountTradeBanned' ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_AccountTradeBanned' ), 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_AccountTradeBanned' ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#tradeban', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'trusted' => array( 'text' => LocalizeFmt( 'Economy_Market_TopLevelReason_AccountNotTrusted', 30 ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_AccountNotTrusted' ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_AccountNotTrusted', 30 ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#nottrusted', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_RemoveRestrictionLink' ) ), 'trustedwaiting' => array( 'text' => LocalizeFmt('Economy_Market_TopLevelReason_AccountNotTrusted_Waiting', 30), 'moreinfotooltip' => LocalizeFmt('Economy_Market_TTopLevelTooltip_AccountNotTrusted_Waiting', 30), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_AccountNotTrusted', 30 ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#nottrusted', 'linktext' => Localize('Economy_Market_TopLevelTooltip_MoreInfoLink') ), 'pwreset' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_AccountPasswordRecentlyReset' ), 'moreinfotooltip' => LocalizeFmt( 'Economy_Market_TopLevelTooltip_AccountPasswordRecentlyReset', 5, 30 ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_AccountPasswordRecentlyReset', 5 ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#pwreset', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'newpaymentmethod' => array( 'text' => LocalizeFmt( 'Economy_Market_HeaderTip_NewPaymentMethod_NoDate', 'a class="tooltip verify" href="' . STORE_BASE_URL . 'account/verifycards' . '"', 'a') . '

' . Localize( 'Economy_Market_TopLevelReason_NewPaymentMethodMore' ), 'moreinfotooltip' => '', 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_AccountHasNewPaymentMethod' ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=6088-UDXM-7214#whatisit', 'panoramalink' => STORE_BASE_URL . 'account/verifycards', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'newpaymentnoverify' => array( 'text' => LocalizeFmt('Economy_Market_TopLevelReason_AccountHasNewPaymentMethod' ), 'moreinfotooltip' => '', 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_AccountHasNewPaymentMethod' ), 'link' => BASE_URL_CURRENT . '/market/faq/', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'acceptedwalletgift' => array( 'text' => LocalizeFmt('Economy_Market_TopLevelReason_AcceptedWalletGift' ), 'moreinfotooltip' => '', 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_AcceptedWalletGift', 3 ), 'link' => STORE_BASE_URL . '/digitalgiftcards/selectgiftcard/', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'cookie' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_InvalidCookie' ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_InvalidCookie' ), 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_InvalidCookie' ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#cookie', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_RemoveRestrictionLink' ) ), 'newdevice' => array( 'text' => LocalizeFmt( 'Economy_Market_TopLevelReason_NewDevice', 7 ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_NewDevice' ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_NewDevice', !empty( $rgMarketplaceAllowed['new_device_cooldown_days'] ) ? $rgMarketplaceAllowed['new_device_cooldown_days'] : 15 ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#newdevice', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'selfrefund' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_SelfRefund' ), 'moreinfotooltip' => LocalizeFmt( 'Economy_Market_TopLevelTooltip_SelfRefund', 7 ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_SelfRefund', 7 ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#selfrefund', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'limiteduser' => array( 'text' => Localize( 'Economy_Market_TopLevelReason_LimitedUser' ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_LimitedUser' ), 'buttontooltip' => Localize( 'Economy_Market_HeaderTip_LimitedUser' ), 'link' => 'http://support.steampowered.com/kb_article.php?ref=3330-IAGK-7663', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_RemoveRestrictionLink' ) ), 'sgrecent' => array( 'text' => LocalizeFmt( 'Economy_Market_HeaderTip_SteamGuardOnlyRecentlyEnabled', $rgMarketplaceAllowed['steamguard_required_days'] ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_SteamGuardRecentlyEnabled' ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_SteamGuardOnlyRecentlyEnabled', $rgMarketplaceAllowed['steamguard_required_days'] ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=1047-EDFM-2932#sgrecent', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_MoreInfoLink' ) ), 'sgdisabled' => array( 'text' => LocalizeFmt( 'Economy_Market_TopLevelReason_NoSteamGuard', $rgMarketplaceAllowed['steamguard_required_days'] ), 'moreinfotooltip' => Localize( 'Economy_Market_TopLevelTooltip_SteamGuardDisabled' ), 'buttontooltip' => LocalizeFmt( 'Economy_Market_HeaderTip_NoSteamGuard', $rgMarketplaceAllowed['steamguard_required_days'] ), 'link' => 'https://support.steampowered.com/kb_article.php?ref=4020-ALZM-5519#how', 'linktext' => Localize( 'Economy_Market_TopLevelTooltip_RemoveRestrictionLink' ) ) ); $controller->SetVar( 'rgMarketplaceAllowed', $rgMarketplaceAllowed ); $controller->SetVar( 'bMarketAllowed', $bMarketAllowed ); $controller->SetVar( 'rgRestrictions', $rgRestrictions ); $controller->SetVar( 'rgRestrictionData', $rgRestrictionData ); $controller->SetVar( 'bWeKnowWhenUserCanUseMarket', $bWeKnowWhenUserCanUseMarket ); // // Sales limit data // $bApproachingNumberOfSalesLimit = $rgMarketplaceAllowed !== false && $rgMarketplaceAllowed['max_sales_per_year'] > 0 && $rgMarketplaceAllowed['sales_this_year'] > ( $rgMarketplaceAllowed['max_sales_per_year'] * 0.75 ); $bUserShouldFillOutForms = $rgMarketplaceAllowed !== false && array_key_exists( 'forms_requested', $rgMarketplaceAllowed ) && $rgMarketplaceAllowed['forms_requested']; $bUserFormsRequireVerification = $rgMarketplaceAllowed !== false && array_key_exists( 'forms_require_verification', $rgMarketplaceAllowed ) && $rgMarketplaceAllowed['forms_require_verification']; $controller->SetVar( 'bApproachingNumberOfSalesLimit', $bApproachingNumberOfSalesLimit ); $controller->SetVar( 'bUserShouldFillOutForms', $bUserShouldFillOutForms ); $controller->SetVar( 'bUserFormsRequireVerification', $bUserFormsRequireVerification ); } public static function DisplayPriceForMarketListing( $rgListing, $userCountryCode, $bIncludePublisherFee = false, $bIncludeSteamFee = false ) { if ( $rgListing['price'] == 0 || ( array_key_exists( 'active', $rgListing ) && !$rgListing['active'] && $rgListing['status'] != k_EMarketListingStatus_RequiresConfirmation && $rgListing['status'] != k_EMarketListingStatus_OnHold ) ) return Localize( 'Economy_Market_Sold' ); if ( !empty( $rgListing['item_expired'] ) ) return Localize( 'Economy_Market_MyHistory_Event_ListedItemExpired' ); if ( isset( $rgListing['converted_price'] ) && isset( $rgListing['converted_currencyid'] ) ) { $amount = $rgListing['converted_price_per_unit']; $amount += $bIncludePublisherFee ? $rgListing['converted_publisher_fee_per_unit'] : 0; $amount += $bIncludeSteamFee ? $rgListing['converted_steam_fee_per_unit'] : 0; return FormatCurrency( $amount, GetCurrencyCode( $rgListing['converted_currencyid']-2000 ), $userCountryCode ); } else { $amount = $rgListing['original_price_per_unit']; $amount += $bIncludePublisherFee ? $rgListing['publisher_fee_per_unit'] : 0 ; $amount += $bIncludeSteamFee ? $rgListing['steam_fee_per_unit'] : 0 ; return FormatCurrency( $amount, GetCurrencyCode( $rgListing['currencyid']-2000 ), $userCountryCode ); } } /* @return CEconMarket_GetPriceOverviewForItem_Response */ public static function GetPriceOverviewForItem( $nWalletCurrency, $unAppId, $strMarketHashName ) { $strPriceOverviewMemcachedKey = "price_overview_" . $unAppId . "_" . md5( $strMarketHashName ) . "_" . $nWalletCurrency; $protoPriceOverview = GetSharedObjectCache()->GetObject( $strPriceOverviewMemcachedKey ); if ( $protoPriceOverview === false ) { $wgPriceOverviewLoader = EconMarketService::GetPriceOverviewForItem( $nWalletCurrency, $unAppId, $strMarketHashName ); if ( $wgPriceOverviewLoader->GetEResult() == k_EResultOK ) { $protoPriceOverview = $wgPriceOverviewLoader->Get(); GetSharedObjectCache()->StoreObject( $strPriceOverviewMemcachedKey, $protoPriceOverview, 15 ); } } return $protoPriceOverview; } } /** implements a WGLoader-like interface, but really maintains several WG loaders */ class CEconomyAssetInfoBatcher { private $m_eInventoryLoadFlags; private $m_language; private $m_rgAssetsByAppContext = array(); /** @var CEconomyAssetInfoWGLoader[] */ private $m_rgWGLoaders = null; private $m_rgResults = null; public function __construct( $inventoryLoadFlags = k_EInventoryLoadInventory, $language = null ) { $this->m_eInventoryLoadFlags = $inventoryLoadFlags; $this->m_language = ( $language ? $language : CLocalizationManager::GetLanguage() ); } public function AddAssetToLoad( $appid, $contextid, $assetid ) { AssertMsg( is_array( $this->m_rgAssetsByAppContext ), 'Can\'t AddAssetToLoad after calling HintLoad' ); if ( !isset( $this->m_rgAssetsByAppContext[$appid] ) ) $this->m_rgAssetsByAppContext[$appid] = array( ); if ( !isset( $this->m_rgAssetsByAppContext[$appid]['c'.$contextid] ) ) $this->m_rgAssetsByAppContext[$appid]['c'.$contextid] = array( ); $this->m_rgAssetsByAppContext[$appid]['c'.$contextid][$assetid] = $assetid; } public function HintLoad() { if ( $this->m_rgWGLoaders == null && !empty( $this->m_rgAssetsByAppContext ) ) { $this->m_rgWGLoaders = array(); foreach ( $this->m_rgAssetsByAppContext as $appid => $rgContexts ) { foreach ( $rgContexts as $contextid => $rgAssetIds ) { $this->m_rgWGLoaders[] = new CEconomyAssetInfoWGLoader( $this->m_eInventoryLoadFlags, $appid, substr( $contextid, 1 ), $rgAssetIds, $this->m_language ); } } $this->m_rgAssetsByAppContext = null; } } protected function EnsureLoaded() { if ( $this->m_rgResults != null ) return; if ( !$this->m_rgWGLoaders ) $this->HintLoad(); // we have no data if ( !$this->m_rgWGLoaders ) return; $this->m_rgResults = array(); foreach ( $this->m_rgWGLoaders as $wgloader ) { $appid = $wgloader->GetAppID(); $contextid = $wgloader->GetContextID(); if ( !isset( $this->m_rgResults[$appid] ) ) $this->m_rgResults[$appid] = array(); $this->m_rgResults[$appid]['c'.$contextid] = $wgloader->Get(); } } public function GetEResult() { $this->EnsureLoaded(); foreach( $this->m_rgWGLoaders as $wgloader ) { if ( $wgloader->GetEResult() != k_EResultOK ) return $wgloader->GetEResult(); } return k_EResultOK; } public function Get() { $this->EnsureLoaded(); return $this->m_rgResults; } public function GetItem( $appid, $contextid, $assetid ) { $this->EnsureLoaded(); $strContextID = 'c'.$contextid; if ( !isset( $this->m_rgResults[$appid][$strContextID][$assetid] ) ) return null; return $this->m_rgResults[$appid][$strContextID][$assetid]; } } ?>