public static Asset Get(long assetId, string idPiece = "/asset/?ID=") { if (!assetCache.ContainsKey(assetId)) { string appData = Environment.GetEnvironmentVariable("LocalAppData"); string assetCacheDir = Path.Combine(appData, "Rbx2Source", "AssetCache"); Directory.CreateDirectory(assetCacheDir); // Ping Roblox to figure out what this asset's cdn url is HttpWebRequest ping = WebRequest.CreateHttp("https://assetgame.roblox.com" + idPiece + assetId); ping.UserAgent = "Roblox"; ping.Method = "HEAD"; ping.AllowAutoRedirect = false; Asset asset = null; string location = ""; string identifier = ""; string cachedFile = ""; try { using (var response = ping.GetResponse() as HttpWebResponse) { location = response.GetResponseHeader("Location"); identifier = location.Remove(0, 8).Replace(".rbxcdn.com/", "-"); cachedFile = assetCacheDir + '\\' + identifier.Replace('/', '\\'); if (File.Exists(cachedFile)) { string cachedContent = File.ReadAllText(cachedFile); try { asset = JsonConvert.DeserializeObject <Asset>(cachedContent); if (asset.Content.Length == 0) { asset = null; throw new Exception(); } Rbx2Source.Print("Fetched pre-cached asset {0}", assetId); } catch { // Corrupted file? if (File.Exists(cachedFile)) { Rbx2Source.Print("Deleting corrupted file {0}", cachedFile); File.Delete(cachedFile); } } } } } catch { Console.WriteLine("Failed to fetch {0}?", assetId); } if (asset == null) { WebClient http = new WebClient(); http.UseDefaultCredentials = true; http.Headers.Set(HttpRequestHeader.UserAgent, "Roblox"); http.Proxy = null; asset = new Asset(); asset.Id = assetId; try { string productInfoJson = http.DownloadString("http://api.roblox.com/marketplace/productinfo?assetId=" + assetId); asset.ProductInfo = JsonConvert.DeserializeObject <ProductInfo>(productInfoJson); asset.ProductInfo.WindowsSafeName = FileUtility.MakeNameWindowsSafe(asset.ProductInfo.Name); asset.AssetType = asset.ProductInfo.AssetTypeId; } catch { ProductInfo dummyInfo = new ProductInfo(); dummyInfo.Name = "unknown_" + asset.Id; dummyInfo.WindowsSafeName = dummyInfo.Name; dummyInfo.AssetTypeId = AssetType.Model; } asset.CdnUrl = location; asset.CdnCacheId = identifier; asset.GetContent(); asset.Loaded = true; string serialized = JsonConvert.SerializeObject(asset, Formatting.None); try { File.WriteAllText(cachedFile, serialized); Rbx2Source.Print("Precached AssetId {0}", assetId); } catch { // Oh well. Rbx2Source.Print("Failed to cache AssetId {0}", assetId); } } assetCache[assetId] = asset; } return(assetCache[assetId]); }