diff --git a/CreamInstaller/Components/ContextMenuItem.cs b/CreamInstaller/Components/ContextMenuItem.cs
index 15b5ce9..d063613 100644
--- a/CreamInstaller/Components/ContextMenuItem.cs
+++ b/CreamInstaller/Components/ContextMenuItem.cs
@@ -98,20 +98,27 @@ internal sealed class ContextMenuItem : ToolStripMenuItem
private static async Task TryImageIdentifierInfo(ContextMenuItem item, (string id, string iconUrl) imageIdentifierInfo, Action onFail = null)
=> await Task.Run(async () =>
{
- (string id, string iconUrl) = imageIdentifierInfo;
- string imageIdentifier = "Icon_" + id;
- if (Images.TryGetValue(imageIdentifier, out Image image) && image is not null)
- item.Image = image;
- else
+ try
{
- image = await HttpClientManager.GetImageFromUrl(iconUrl);
- if (image is not null)
- {
- Images[imageIdentifier] = image;
+ (string id, string iconUrl) = imageIdentifierInfo;
+ string imageIdentifier = "Icon_" + id;
+ if (Images.TryGetValue(imageIdentifier, out Image image) && image is not null)
item.Image = image;
- }
else
- onFail?.Invoke();
+ {
+ image = await HttpClientManager.GetImageFromUrl(iconUrl);
+ if (image is not null)
+ {
+ Images[imageIdentifier] = image;
+ item.Image = image;
+ }
+ else
+ onFail?.Invoke();
+ }
+ }
+ catch
+ {
+ // ignored
}
});
diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj
index 32629b6..cdc5f61 100644
--- a/CreamInstaller/CreamInstaller.csproj
+++ b/CreamInstaller/CreamInstaller.csproj
@@ -4,7 +4,7 @@
net7.0-windows
True
Resources\ini.ico
- 4.6.1.0
+ 4.7.0.0
2021, pointfeev (https://github.com/pointfeev)
CreamInstaller
Automatic DLC Unlocker Installer & Configuration Generator
diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs
index 5ccb44a..f6c735a 100644
--- a/CreamInstaller/Forms/SelectForm.cs
+++ b/CreamInstaller/Forms/SelectForm.cs
@@ -208,15 +208,17 @@ internal sealed partial class SelectForm : CustomForm
while (!Program.Canceled && steamGamesToCheck > 0);
if (Program.Canceled)
return;
+ string fullGameAppId = null;
string dlcName = null;
string dlcIcon = null;
bool onSteamStore = false;
AppData dlcAppData = await SteamStore.QueryStoreAPI(dlcAppId, true);
if (dlcAppData is not null)
{
- dlcName = dlcAppData.name;
- dlcIcon = dlcAppData.header_image;
+ dlcName = dlcAppData.Name;
+ dlcIcon = dlcAppData.HeaderImage;
onSteamStore = true;
+ fullGameAppId = dlcAppData.FullGame?.AppId;
}
else
{
@@ -229,8 +231,39 @@ internal sealed partial class SelectForm : CustomForm
dlcIconStaticId ??= dlcAppInfo.Value.GetChild("common")?.GetChild("logo")?.ToString();
if (dlcIconStaticId is not null)
dlcIcon = IconGrabber.SteamAppImagesPath + @$"\{dlcAppId}\{dlcIconStaticId}.jpg";
+ fullGameAppId = dlcAppInfo.Value.GetChild("common")?.GetChild("parent")?.ToString();
}
}
+ if (fullGameAppId != null && fullGameAppId != appId)
+ {
+ string fullGameName = null;
+ string fullGameIcon = null;
+ bool fullGameOnSteamStore = false;
+ AppData fullGameAppData = await SteamStore.QueryStoreAPI(fullGameAppId, true);
+ if (fullGameAppData is not null)
+ {
+ fullGameName = fullGameAppData.Name;
+ fullGameIcon = fullGameAppData.HeaderImage;
+ fullGameOnSteamStore = true;
+ }
+ else
+ {
+ VProperty fullGameAppInfo = await SteamCMD.GetAppInfo(fullGameAppId);
+ if (fullGameAppInfo is not null)
+ {
+ fullGameName = fullGameAppInfo.Value.GetChild("common")?.GetChild("name")?.ToString();
+ string fullGameIconStaticId = fullGameAppInfo.Value.GetChild("common")?.GetChild("icon")?.ToString();
+ fullGameIconStaticId ??= fullGameAppInfo.Value.GetChild("common")?.GetChild("logo_small")?.ToString();
+ fullGameIconStaticId ??= fullGameAppInfo.Value.GetChild("common")?.GetChild("logo")?.ToString();
+ if (fullGameIconStaticId is not null)
+ dlcIcon = IconGrabber.SteamAppImagesPath + @$"\{fullGameAppId}\{fullGameIconStaticId}.jpg";
+ }
+ }
+ if (Program.Canceled)
+ return;
+ if (!string.IsNullOrWhiteSpace(fullGameName))
+ dlc[fullGameAppId] = (fullGameOnSteamStore ? DlcType.Steam : DlcType.SteamHidden, fullGameName, fullGameIcon);
+ }
if (Program.Canceled)
return;
if (string.IsNullOrWhiteSpace(dlcName))
@@ -259,17 +292,17 @@ internal sealed partial class SelectForm : CustomForm
if (koaloaderAllCheckBox.Checked)
selection.Koaloader = true;
selection.Id = appId;
- selection.Name = appData?.name ?? name;
+ selection.Name = appData?.Name ?? name;
selection.RootDirectory = gameDirectory;
selection.ExecutableDirectories = await SteamLibrary.GetExecutableDirectories(selection.RootDirectory);
selection.DllDirectories = dllDirectories;
selection.Platform = Platform.Steam;
selection.ProductUrl = "https://store.steampowered.com/app/" + appId;
selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value.GetChild("common")?.GetChild("icon")}.jpg";
- selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath
+ selection.SubIconUrl = appData?.HeaderImage ?? IconGrabber.SteamAppImagesPath
+ @$"\{appId}\{appInfo?.Value.GetChild("common")?.GetChild("clienticon")}.ico";
- selection.Publisher = appData?.publishers[0] ?? appInfo?.Value.GetChild("extended")?.GetChild("publisher")?.ToString();
- selection.WebsiteUrl = appData?.website;
+ selection.Publisher = appData?.Publishers[0] ?? appInfo?.Value.GetChild("extended")?.GetChild("publisher")?.ToString();
+ selection.WebsiteUrl = appData?.Website;
if (Program.Canceled)
return;
selectionTreeView.Invoke(delegate
@@ -279,7 +312,7 @@ internal sealed partial class SelectForm : CustomForm
TreeNode programNode = treeNodes.Find(s => s.Tag is Platform.Steam && s.Name == appId) ?? new TreeNode();
programNode.Tag = selection.Platform;
programNode.Name = appId;
- programNode.Text = appData?.name ?? name;
+ programNode.Text = appData?.Name ?? name;
programNode.Checked = selection.Enabled;
if (programNode.TreeView is null)
_ = selectionTreeView.Nodes.Add(programNode);
diff --git a/CreamInstaller/Platforms/Steam/AppDetails.cs b/CreamInstaller/Platforms/Steam/AppDetails.cs
index cb19475..114482f 100644
--- a/CreamInstaller/Platforms/Steam/AppDetails.cs
+++ b/CreamInstaller/Platforms/Steam/AppDetails.cs
@@ -1,36 +1,49 @@
-#pragma warning disable IDE1006 // Naming Styles
-#pragma warning disable CA1002 // Do not expose generic lists
-#pragma warning disable CA1707 // Identifiers should not contain underscores
-#pragma warning disable CA2227 // Collection properties should be read only
-
-using System.Collections.Generic;
+using System.Collections.Generic;
+using Newtonsoft.Json;
namespace CreamInstaller.Platforms.Steam;
+public class AppFullGame
+{
+ [JsonProperty(PropertyName = "appid")] public string AppId { get; set; }
+
+ [JsonProperty(PropertyName = "name")] public string Name { get; set; }
+}
+
public class AppData
{
- public string type { get; set; }
+ [JsonProperty(PropertyName = "type")] public string Type { get; set; }
- public string name { get; set; }
+ [JsonProperty(PropertyName = "name")] public string Name { get; set; }
- public int steam_appid { get; set; }
+ [JsonProperty(PropertyName = "steam_appid")]
+ public int SteamAppId { get; set; }
- public List dlc { get; set; }
+ [JsonProperty(PropertyName = "fullgame")]
+ public AppFullGame FullGame { get; set; }
- public string header_image { get; set; }
+ [JsonProperty(PropertyName = "dlc")] public List DLC { get; set; }
- public string website { get; set; }
+ [JsonProperty(PropertyName = "header_image")]
+ public string HeaderImage { get; set; }
- public List developers { get; set; }
+ [JsonProperty(PropertyName = "website")]
+ public string Website { get; set; }
- public List publishers { get; set; }
+ [JsonProperty(PropertyName = "developers")]
+ public List Developers { get; set; }
- public List packages { get; set; }
+ [JsonProperty(PropertyName = "publishers")]
+ public List Publishers { get; set; }
+
+ [JsonProperty(PropertyName = "packages")]
+ public List Packages { get; set; }
}
public class AppDetails
{
- public bool success { get; set; }
+ [JsonProperty(PropertyName = "success")]
+ public bool Success { get; set; }
- public AppData data { get; set; }
+ [JsonProperty(PropertyName = "data")] public AppData Data { get; set; }
}
\ No newline at end of file
diff --git a/CreamInstaller/Platforms/Steam/SteamStore.cs b/CreamInstaller/Platforms/Steam/SteamStore.cs
index 05f256f..0d38df4 100644
--- a/CreamInstaller/Platforms/Steam/SteamStore.cs
+++ b/CreamInstaller/Platforms/Steam/SteamStore.cs
@@ -22,9 +22,9 @@ internal static class SteamStore
=> await Task.Run(() =>
{
List dlcIds = new();
- if (appData.dlc is null)
+ if (appData.DLC is null)
return dlcIds;
- dlcIds.AddRange(from appId in appData.dlc where appId > 0 select appId.ToString(CultureInfo.InvariantCulture));
+ dlcIds.AddRange(from appId in appData.DLC where appId > 0 select appId.ToString(CultureInfo.InvariantCulture));
return dlcIds;
});
@@ -48,8 +48,8 @@ internal static class SteamStore
AppDetails appDetails = JsonConvert.DeserializeObject(app.Value.ToString());
if (appDetails is not null)
{
- AppData data = appDetails.data;
- if (!appDetails.success)
+ AppData data = appDetails.Data;
+ if (!appDetails.Success)
{
#if DEBUG
DebugForm.Current.Log(
diff --git a/CreamInstaller/Utility/HttpClientManager.cs b/CreamInstaller/Utility/HttpClientManager.cs
index e0115be..af35eb6 100644
--- a/CreamInstaller/Utility/HttpClientManager.cs
+++ b/CreamInstaller/Utility/HttpClientManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Drawing;
+using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using HtmlAgilityPack;
@@ -28,6 +29,19 @@ internal static class HttpClientManager
_ = response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
+ catch (HttpRequestException e)
+ {
+ if (e.StatusCode != HttpStatusCode.TooManyRequests)
+ {
+ DebugForm.Current.Log("Get request failed to " + url + ": " + e, LogTextBox.Warning);
+ return null;
+ }
+#if DEBUG
+ DebugForm.Current.Log("Too many requests to " + url, LogTextBox.Error);
+#endif
+ // do something special?
+ return null;
+ }
#if DEBUG
catch (Exception e)
{
diff --git a/CreamInstaller/Utility/ProgramData.cs b/CreamInstaller/Utility/ProgramData.cs
index 9cadd53..2578a0b 100644
--- a/CreamInstaller/Utility/ProgramData.cs
+++ b/CreamInstaller/Utility/ProgramData.cs
@@ -17,7 +17,7 @@ internal static class ProgramData
internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo";
private static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt";
- private static readonly Version MinimumAppInfoVersion = Version.Parse("3.2.0.0");
+ private static readonly Version MinimumAppInfoVersion = Version.Parse("4.7.0.0");
internal static readonly string CooldownPath = DirectoryPath + @"\cooldown";