v2.2.4.1
- Vastly improved the stability of VDF file parsing
This commit is contained in:
parent
ffbbeedeff
commit
f1b7e04842
4 changed files with 76 additions and 62 deletions
|
@ -9,7 +9,6 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Gameloop.Vdf;
|
||||
using Gameloop.Vdf.Linq;
|
||||
|
||||
namespace CreamInstaller
|
||||
|
@ -78,7 +77,6 @@ namespace CreamInstaller
|
|||
|
||||
internal static async Task<VProperty> GetAppInfo(int appId, string branch = "public", int buildId = 0)
|
||||
{
|
||||
VProperty appInfo = null;
|
||||
if (Program.Canceled) return null;
|
||||
string output;
|
||||
string appUpdatePath = $@"{AppInfoPath}\{appId}";
|
||||
|
@ -99,8 +97,7 @@ namespace CreamInstaller
|
|||
}
|
||||
}
|
||||
if (Program.Canceled || output is null) return null;
|
||||
try { appInfo = VdfConvert.Deserialize(output); }
|
||||
catch
|
||||
if (!ValveDataFile.TryDeserialize(output, out VProperty appInfo))
|
||||
{
|
||||
if (Directory.Exists(appUpdatePath))
|
||||
{
|
||||
|
@ -109,12 +106,11 @@ namespace CreamInstaller
|
|||
}
|
||||
}
|
||||
if (appInfo.Value is VValue) goto restart;
|
||||
if (appInfo is null || appInfo.Value is not VValue && appInfo.Value.Children().ToList().Count == 0)
|
||||
return appInfo;
|
||||
VToken type = appInfo.Value is VValue ? null : appInfo.Value?["common"]?["type"];
|
||||
if (appInfo is null || appInfo.Value?.Children()?.ToList()?.Count == 0) return appInfo;
|
||||
VToken type = appInfo.Value?.TryGet("common")?.TryGet("type");
|
||||
if (type is null || type.ToString() == "Game")
|
||||
{
|
||||
string buildid = appInfo.Value is VValue ? null : appInfo.Value["depots"]?["branches"]?[branch]?["buildid"]?.ToString();
|
||||
string buildid = appInfo.Value?.TryGet("depots")?.TryGet("branches")?.TryGet(branch)?.TryGet("buildid")?.ToString();
|
||||
if (buildid is null && type is not null) return appInfo;
|
||||
if (type is null || int.Parse(buildid) < buildId)
|
||||
{
|
||||
|
@ -135,17 +131,16 @@ namespace CreamInstaller
|
|||
{
|
||||
List<int> dlcIds = new();
|
||||
if (Program.Canceled || appInfo is not VProperty) return dlcIds;
|
||||
if (appInfo.Value["extended"] is not null)
|
||||
foreach (VProperty property in appInfo.Value["extended"])
|
||||
if (property.Key.ToString() == "listofdlc")
|
||||
foreach (string id in property.Value.ToString().Split(","))
|
||||
if (!dlcIds.Contains(int.Parse(id)))
|
||||
dlcIds.Add(int.Parse(id));
|
||||
if (appInfo.Value["depots"] is not null)
|
||||
foreach (VProperty _property in appInfo.Value["depots"])
|
||||
if (int.TryParse(_property.Key.ToString(), out int _))
|
||||
if (int.TryParse(_property.Value?["dlcappid"]?.ToString(), out int appid) && !dlcIds.Contains(appid))
|
||||
dlcIds.Add(appid);
|
||||
VToken extended = appInfo.Value.TryGet("extended");
|
||||
if (extended is not null) foreach (VProperty property in extended)
|
||||
if (property.Key.ToString() == "listofdlc") foreach (string id in property.Value.ToString().Split(","))
|
||||
if (!dlcIds.Contains(int.Parse(id))) dlcIds.Add(int.Parse(id));
|
||||
VToken depots = appInfo.Value.TryGet("depots");
|
||||
if (depots is not null) foreach (VProperty property in depots)
|
||||
if (int.TryParse(property.Key.ToString(), out int _)
|
||||
&& int.TryParse(property.Value.TryGet("dlcappid")?.ToString(), out int appid)
|
||||
&& !dlcIds.Contains(appid))
|
||||
dlcIds.Add(appid);
|
||||
return dlcIds;
|
||||
});
|
||||
|
||||
|
|
29
CreamInstaller/Classes/ValveDataFile.cs
Normal file
29
CreamInstaller/Classes/ValveDataFile.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using Gameloop.Vdf;
|
||||
using Gameloop.Vdf.Linq;
|
||||
|
||||
namespace CreamInstaller;
|
||||
|
||||
internal static class ValveDataFile
|
||||
{
|
||||
internal static bool TryDeserialize(string value, out VProperty result)
|
||||
{
|
||||
result = null;
|
||||
try
|
||||
{
|
||||
result = VdfConvert.Deserialize(value);
|
||||
return true;
|
||||
}
|
||||
catch { }
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static VToken TryGet(this VToken token, string index)
|
||||
{
|
||||
try
|
||||
{
|
||||
return token[index];
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
|
||||
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
|
||||
<Version>2.2.4.0</Version>
|
||||
<Version>2.2.4.1</Version>
|
||||
<PackageIcon>Resources\ini.ico</PackageIcon>
|
||||
<PackageIconUrl />
|
||||
<Description>Automatically generates and installs CreamAPI files for Steam games on the user's computer. It can also generate and install CreamAPI for the Paradox Launcher should the user select a Paradox Interactive game.</Description>
|
||||
|
|
|
@ -10,7 +10,6 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Gameloop.Vdf;
|
||||
using Gameloop.Vdf.Linq;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
@ -38,22 +37,18 @@ namespace CreamInstaller
|
|||
if (Directory.Exists(libraryFolder))
|
||||
{
|
||||
gameDirectories.Add(libraryFolder);
|
||||
try
|
||||
string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
|
||||
if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty _result))
|
||||
{
|
||||
string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
|
||||
if (File.Exists(libraryFolders))
|
||||
{
|
||||
dynamic property = VdfConvert.Deserialize(File.ReadAllText(libraryFolders, Encoding.UTF8)).Value;
|
||||
foreach (dynamic _property in property)
|
||||
if (int.TryParse(_property.Key, out int _))
|
||||
{
|
||||
string path = _property.Value.path.ToString() + @"\steamapps";
|
||||
if (string.IsNullOrWhiteSpace(path) || !Directory.Exists(path)) continue;
|
||||
if (!gameDirectories.Contains(path)) gameDirectories.Add(path);
|
||||
}
|
||||
}
|
||||
dynamic result = _result;
|
||||
foreach (dynamic property in result?.Value) if (int.TryParse(property.Key, out int _))
|
||||
{
|
||||
string path = property.Value?.path?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(path)) continue;
|
||||
path += @"\steamapps";
|
||||
if (Directory.Exists(path) && !gameDirectories.Contains(path)) gameDirectories.Add(path);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
return gameDirectories;
|
||||
|
@ -89,28 +84,24 @@ namespace CreamInstaller
|
|||
foreach (string file in files)
|
||||
{
|
||||
if (Program.Canceled) return null;
|
||||
if (Path.GetExtension(file) == ".acf")
|
||||
if (Path.GetExtension(file) == ".acf" && ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty _result))
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic property = VdfConvert.Deserialize(File.ReadAllText(file, Encoding.UTF8));
|
||||
string _appid = property.Value.appid.ToString();
|
||||
string installdir = property.Value.installdir.ToString();
|
||||
string name = property.Value.name.ToString();
|
||||
string _buildid = property.Value.buildid.ToString();
|
||||
if (string.IsNullOrWhiteSpace(_appid)
|
||||
|| string.IsNullOrWhiteSpace(installdir)
|
||||
|| string.IsNullOrWhiteSpace(name)
|
||||
|| string.IsNullOrWhiteSpace(_buildid))
|
||||
continue;
|
||||
string branch = property.Value.UserConfig?.betakey?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(branch)) branch = "public";
|
||||
string gameDirectory = libraryDirectory + @"\common\" + installdir;
|
||||
if (!int.TryParse(_appid, out int appid)) continue;
|
||||
if (!int.TryParse(_buildid, out int buildid)) continue;
|
||||
games.Add(new(appid, name, branch, buildid, gameDirectory));
|
||||
}
|
||||
catch { }
|
||||
dynamic result = _result;
|
||||
string _appid = result.Value?.appid?.ToString();
|
||||
string installdir = result.Value?.installdir?.ToString();
|
||||
string name = result.Value?.name?.ToString();
|
||||
string _buildid = result.Value?.buildid?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(_appid)
|
||||
|| string.IsNullOrWhiteSpace(installdir)
|
||||
|| string.IsNullOrWhiteSpace(name)
|
||||
|| string.IsNullOrWhiteSpace(_buildid))
|
||||
continue;
|
||||
string branch = result.Value?.UserConfig?.betakey?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(branch)) branch = "public";
|
||||
string gameDirectory = libraryDirectory + @"\common\" + installdir;
|
||||
if (!int.TryParse(_appid, out int appid)) continue;
|
||||
if (!int.TryParse(_buildid, out int buildid)) continue;
|
||||
games.Add(new(appid, name, branch, buildid, gameDirectory));
|
||||
}
|
||||
}
|
||||
if (!games.Any()) return null;
|
||||
|
@ -182,8 +173,7 @@ namespace CreamInstaller
|
|||
if (Program.Canceled) return;
|
||||
string dlcName = null;
|
||||
VProperty dlcAppInfo = await SteamCMD.GetAppInfo(id);
|
||||
if (dlcAppInfo is not null)
|
||||
dlcName = dlcAppInfo?.Value?["common"]?["name"]?.ToString();
|
||||
if (dlcAppInfo is not null) dlcName = dlcAppInfo.Value?.TryGet("common")?.TryGet("name")?.ToString();
|
||||
if (Program.Canceled) return;
|
||||
if (string.IsNullOrWhiteSpace(dlcName)) return; //dlcName = "Unknown DLC";
|
||||
dlc[id] = /*$"[{id}] " +*/ dlcName;
|
||||
|
@ -211,8 +201,8 @@ namespace CreamInstaller
|
|||
if (appId == 0) selection.Icon = Program.GetFileIconImage(directory + @"\launcher\bootstrapper-v2.exe");
|
||||
else
|
||||
{
|
||||
selection.IconStaticID = appInfo?.Value?["common"]?["icon"]?.ToString();
|
||||
selection.ClientIconStaticID = appInfo?.Value?["common"]?["clienticon"]?.ToString();
|
||||
selection.IconStaticID = appInfo?.Value?.TryGet("common")?.TryGet("icon")?.ToString();
|
||||
selection.ClientIconStaticID = appInfo?.Value?.TryGet("common")?.TryGet("clienticon")?.ToString();
|
||||
}
|
||||
}
|
||||
if (allCheckBox.Checked) selection.Enabled = true;
|
||||
|
@ -453,14 +443,14 @@ namespace CreamInstaller
|
|||
foreach (ProgramSelection selection in ProgramSelection.AllUsableEnabled)
|
||||
{
|
||||
if (selection.Name == paradoxLauncher.Name) continue;
|
||||
if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") continue;
|
||||
if (selection.AppInfo.Value?.TryGet("extended")?.TryGet("publisher")?.ToString() != "Paradox Interactive") continue;
|
||||
paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.SelectedSteamDlc));
|
||||
}
|
||||
if (!paradoxLauncher.ExtraSteamAppIdDlc.Any())
|
||||
foreach (ProgramSelection selection in ProgramSelection.AllUsable)
|
||||
{
|
||||
if (selection.Name == paradoxLauncher.Name) continue;
|
||||
if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") continue;
|
||||
if (selection.AppInfo.Value?.TryGet("extended")?.TryGet("publisher")?.ToString() != "Paradox Interactive") continue;
|
||||
paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.AllSteamDlc));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue