proper game gathering, depot dlcs, appinfo caching

This commit is contained in:
pointfeev 2021-11-06 04:55:37 -04:00
parent b11e5e9fcb
commit 351847727b
No known key found for this signature in database
GPG key ID: AA14DC36C4D7D13C
6 changed files with 195 additions and 178 deletions

View file

@ -52,7 +52,7 @@ namespace CreamInstaller
int cur = 0; int cur = 0;
foreach (string directory in selection.SteamApiDllDirectories) foreach (string directory in selection.SteamApiDllDirectories)
{ {
UpdateUser("Installing CreamAPI for " + selection.DisplayName + $" in directory \"{directory}\" . . . ", LogColor.Operation); UpdateUser("Installing CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", LogColor.Operation);
if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException(); if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException();
string api = directory + @"\steam_api.dll"; string api = directory + @"\steam_api.dll";
string api_o = directory + @"\steam_api_o.dll"; string api_o = directory + @"\steam_api_o.dll";
@ -89,7 +89,7 @@ namespace CreamInstaller
writer.WriteLine($"appid = {selection.SteamAppId}"); writer.WriteLine($"appid = {selection.SteamAppId}");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("[dlc]"); writer.WriteLine("[dlc]");
UpdateUser($"Added game to cream_api.ini with appid {selection.SteamAppId} ({selection.DisplayName})", LogColor.Resource); UpdateUser($"Added game to cream_api.ini with appid {selection.SteamAppId} ({selection.Name})", LogColor.Resource);
foreach (Tuple<int, string> dlcApp in selection.SelectedSteamDlc) foreach (Tuple<int, string> dlcApp in selection.SelectedSteamDlc)
{ {
writer.WriteLine($"{dlcApp.Item1} = {dlcApp.Item2}"); writer.WriteLine($"{dlcApp.Item1} = {dlcApp.Item2}");
@ -129,12 +129,12 @@ namespace CreamInstaller
try try
{ {
await OperateFor(selection); await OperateFor(selection);
UpdateUser($"Operation succeeded for {selection.DisplayName}.", LogColor.Success); UpdateUser($"Operation succeeded for {selection.Name}.", LogColor.Success);
selection.Enabled = false; selection.Enabled = false;
} }
catch (Exception exception) catch (Exception exception)
{ {
UpdateUser($"Operation failed for {selection.DisplayName}: " + exception.ToString(), LogColor.Error); UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), LogColor.Error);
} }
++CompleteOperationsCount; ++CompleteOperationsCount;
} }
@ -144,7 +144,7 @@ namespace CreamInstaller
{ {
if (FailedSelections.Count == 1) if (FailedSelections.Count == 1)
{ {
throw new CustomMessageException($"Operation failed for {FailedSelections.First().DisplayName}."); throw new CustomMessageException($"Operation failed for {FailedSelections.First().Name}.");
} }
else else
{ {

View file

@ -39,7 +39,7 @@ namespace CreamInstaller
if (selection.AreSteamApiDllsLocked) if (selection.AreSteamApiDllsLocked)
{ {
if (new DialogForm(form).Show(ApplicationName, SystemIcons.Error, if (new DialogForm(form).Show(ApplicationName, SystemIcons.Error,
$"ERROR: {selection.DisplayName} is currently running!" + $"ERROR: {selection.Name} is currently running!" +
"\n\nPlease close the program/game to continue . . . ", "\n\nPlease close the program/game to continue . . . ",
"Retry", "Cancel") == DialogResult.OK) "Retry", "Cancel") == DialogResult.OK)
{ {

View file

@ -1,4 +1,5 @@
using System; using Gameloop.Vdf.Linq;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -8,13 +9,13 @@ namespace CreamInstaller
{ {
public bool Enabled = true; public bool Enabled = true;
public string Identifier; public string Name;
public string DisplayName;
public string RootDirectory; public string RootDirectory;
public int SteamAppId; public int SteamAppId;
public List<string> SteamApiDllDirectories; public List<string> SteamApiDllDirectories;
public Dictionary<string, string> AppInfo = new(); public VProperty AppInfo = null;
public List<Tuple<int, string>> AllSteamDlc = new(); public List<Tuple<int, string>> AllSteamDlc = new();
public List<Tuple<int, string>> SelectedSteamDlc = new(); public List<Tuple<int, string>> SelectedSteamDlc = new();
public List<Tuple<int, string, List<Tuple<int, string>>>> ExtraSteamAppIdDlc = new(); public List<Tuple<int, string, List<Tuple<int, string>>>> ExtraSteamAppIdDlc = new();
@ -47,9 +48,10 @@ namespace CreamInstaller
} }
} }
else SelectedSteamDlc.Remove(dlcApp); else SelectedSteamDlc.Remove(dlcApp);
return; break;
} }
} }
if (!SelectedSteamDlc.Any()) this.Enabled = false;
} }
public ProgramSelection() => All.Add(this); public ProgramSelection() => All.Add(this);
@ -60,8 +62,6 @@ namespace CreamInstaller
public static List<ProgramSelection> AllSafeEnabled => AllSafe.FindAll(s => s.Enabled); public static List<ProgramSelection> AllSafeEnabled => AllSafe.FindAll(s => s.Enabled);
public static ProgramSelection FromIdentifier(string identifier) => AllSafe.Find(s => s.Identifier == identifier); public static ProgramSelection FromName(string displayName) => AllSafe.Find(s => s.Name == displayName);
public static ProgramSelection FromDisplayName(string displayName) => AllSafe.Find(s => s.DisplayName == displayName);
} }
} }

View file

@ -108,11 +108,11 @@ namespace CreamInstaller
this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.treeView1.BackColor = System.Drawing.SystemColors.Control;
this.treeView1.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.treeView1.CheckBoxes = true; this.treeView1.CheckBoxes = true;
this.treeView1.Location = new System.Drawing.Point(6, 22); this.treeView1.Location = new System.Drawing.Point(6, 22);
this.treeView1.Name = "treeView1"; this.treeView1.Name = "treeView1";
this.treeView1.ShowPlusMinus = false;
this.treeView1.ShowRootLines = false;
this.treeView1.Size = new System.Drawing.Size(448, 208); this.treeView1.Size = new System.Drawing.Size(448, 208);
this.treeView1.TabIndex = 1001; this.treeView1.TabIndex = 1001;
// //

View file

@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -32,63 +31,70 @@ namespace CreamInstaller
if (steamInstallPath == null) steamInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Valve\\Steam", "InstallPath", null) as string; if (steamInstallPath == null) steamInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Valve\\Steam", "InstallPath", null) as string;
if (steamInstallPath != null) if (steamInstallPath != null)
{ {
string mainLibraryFolder = steamInstallPath + "\\steamapps\\common"; string libraryFolder = steamInstallPath + @"\steamapps";
gameDirectories.Add(mainLibraryFolder); gameDirectories.Add(libraryFolder);
string libraryFolders = steamInstallPath + "\\steamapps\\libraryfolders.vdf"; string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
VProperty property = VdfConvert.Deserialize(File.ReadAllText(libraryFolders)); dynamic property = VdfConvert.Deserialize(File.ReadAllText(libraryFolders));
foreach (VProperty _property in property.Value) foreach (dynamic _property in property.Value)
if (int.TryParse(_property.Key, out _) && Directory.Exists(_property.Value.ToString())) {
gameDirectories.Add(_property.Value.ToString()); if (int.TryParse(_property.Key, out int _))
{
string path = _property.Value.path.ToString() + @"\steamapps";
if (string.IsNullOrWhiteSpace(path)) continue;
if (!gameDirectories.Contains(path)) gameDirectories.Add(path);
}
}
} }
return gameDirectories; return gameDirectories;
} }
} }
private bool GetSteamApiDllDirectoriesFromGameDirectory(string gameDirectory, out List<string> steamApiDllDirectories) private bool GetDllDirectoriesFromGameDirectory(string gameDirectory, out List<string> dllDirectories)
{ {
steamApiDllDirectories = new(); dllDirectories = new();
if (Program.Canceled) return false; if (Program.Canceled) return false;
string api = gameDirectory + @"\steam_api.dll"; string api = gameDirectory + @"\steam_api.dll";
string api64 = gameDirectory + @"\steam_api64.dll"; string api64 = gameDirectory + @"\steam_api64.dll";
if (File.Exists(api) || File.Exists(api64)) steamApiDllDirectories.Add(gameDirectory); if (File.Exists(api) || File.Exists(api64)) dllDirectories.Add(gameDirectory);
foreach (string _directory in Directory.GetDirectories(gameDirectory)) foreach (string _directory in Directory.GetDirectories(gameDirectory))
{ {
if (Program.Canceled) return false; if (Program.Canceled) return false;
try try
{ {
if (GetSteamApiDllDirectoriesFromGameDirectory(_directory, out List<string> _steamApiDllDirectories)) if (GetDllDirectoriesFromGameDirectory(_directory, out List<string> _dllDirectories))
steamApiDllDirectories.AddRange(_steamApiDllDirectories); dllDirectories.AddRange(_dllDirectories);
} }
catch { } catch { }
} }
if (!steamApiDllDirectories.Any()) return false; if (!dllDirectories.Any()) return false;
return true; return true;
} }
private bool GetSteamAppIdFromGameDirectory(string gameDirectory, out int appId) private bool GetGamesFromLibraryDirectory(string libraryDirectory, out List<Tuple<int, string, int, string>> games)
{ {
appId = 0; games = new();
if (Program.Canceled) return false; if (Program.Canceled) return false;
string file = gameDirectory + "\\steam_appid.txt"; foreach (string directory in Directory.GetFiles(libraryDirectory))
if (File.Exists(file) && int.TryParse(File.ReadAllText(file), out appId)) return true;
foreach (string _directory in Directory.GetDirectories(gameDirectory))
{ {
if (Program.Canceled) return false; if (Program.Canceled) return false;
if (GetSteamAppIdFromGameDirectory(_directory, out appId)) return true; if (Path.GetExtension(directory) == ".acf")
{
dynamic property = VdfConvert.Deserialize(File.ReadAllText(directory));
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 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, buildid, gameDirectory));
}
} }
return false; if (!games.Any()) return false;
}
private bool GetGameDirectoriesFromLibraryDirectory(string libraryDirectory, out List<string> gameDirectories)
{
gameDirectories = new();
if (Program.Canceled) return false;
foreach (string _directory in Directory.GetDirectories(libraryDirectory))
{
if (Program.Canceled) return false;
if (Directory.Exists(_directory)) gameDirectories.Add(_directory);
}
if (!gameDirectories.Any()) return false;
return true; return true;
} }
@ -102,120 +108,121 @@ namespace CreamInstaller
{ {
int cur = 0; int cur = 0;
if (Program.Canceled) return; if (Program.Canceled) return;
List<Tuple<string, string>> applicablePrograms = new(); List<Tuple<int, string, int, string>> applicablePrograms = new();
string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive"; string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive";
if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new Tuple<string, string>("Paradox Launcher", launcherRootDirectory)); if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new(0, "Paradox Launcher", 0, launcherRootDirectory));
foreach (string libraryDirectory in GameLibraryDirectories) foreach (string libraryDirectory in GameLibraryDirectories)
if (GetGameDirectoriesFromLibraryDirectory(libraryDirectory, out List<string> gameDirectories)) if (GetGamesFromLibraryDirectory(libraryDirectory, out List<Tuple<int, string, int, string>> games))
foreach (string gameDirectory in gameDirectories) foreach (Tuple<int, string, int, string> game in games)
applicablePrograms.Add(new Tuple<string, string>(Path.GetFileName(gameDirectory) ?? "unknown_" + applicablePrograms.Count, gameDirectory)); applicablePrograms.Add(game);
RunningTasks = new(); RunningTasks = new();
foreach (Tuple<string, string> program in applicablePrograms) foreach (Tuple<int, string, int, string> program in applicablePrograms)
{ {
string identifier = program.Item1; int appId = program.Item1;
string rootDirectory = program.Item2; string name = program.Item2;
int buildId = program.Item3;
string directory = program.Item4;
if (Program.Canceled) return; if (Program.Canceled) return;
if (Directory.Exists(directory + @"\EasyAntiCheat")) continue;
Task task = new(() => Task task = new(() =>
{ {
try if (Program.Canceled || !GetDllDirectoriesFromGameDirectory(directory, out List<string> dllDirectories)) return;
VProperty appInfo = null;
if (Program.Canceled || (name != "Paradox Launcher" && !SteamCMD.GetAppInfo(appId, buildId, out appInfo))) return;
List<Tuple<int, string>> dlc = null;
if (!DLC.TryGetValue(appId, out dlc))
{ {
int steamAppId = 0; dlc = new();
if (Program.Canceled DLC.Add(appId, dlc);
|| (identifier != "Paradox Launcher" && !GetSteamAppIdFromGameDirectory(rootDirectory, out steamAppId)) }
|| !GetSteamApiDllDirectoriesFromGameDirectory(rootDirectory, out List<string> steamApiDllDirectories)) if (Program.Canceled) return;
return; List<Task> dlcTasks = new();
List<int> dlcIds = new();
Dictionary<string, string> appInfo = null; if (!(appInfo is null))
if (Program.Canceled || (identifier != "Paradox Launcher" && !SteamCMD.GetAppInfo(steamAppId, out appInfo))) return; {
string list = null; try
List<Tuple<int, string>> dlc = null;
if (!DLC.TryGetValue(steamAppId, out dlc))
{ {
dlc = new(); if (!(appInfo.Value["extended"] is null))
DLC.Add(steamAppId, dlc); 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 (Program.Canceled) return; catch { }
List<Task> dlcTasks = new(); try
if (!(appInfo is null) && appInfo.TryGetValue("listofdlc", out list)) {
if (!(appInfo.Value["depots"] is 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);
}
catch { }
}
if (!(dlcIds is null) && dlcIds.Count > 0)
{
foreach (int id in dlcIds)
{ {
if (Program.Canceled) return; if (Program.Canceled) return;
string[] nums = Regex.Replace(list, "[^0-9,]+", "").Split(",");
List<int> ids = new();
foreach (string s in nums)
{
if (Program.Canceled) return;
ids.Add(int.Parse(s));
}
Task task = new(() => Task task = new(() =>
{ {
try if (Program.Canceled) return;
{ string dlcName = null;
foreach (int id in ids) VProperty dlcAppInfo = null;
{ if (SteamCMD.GetAppInfo(id, 0, out dlcAppInfo)) try { dlcName = dlcAppInfo?.Value?["common"]?["name"]?.ToString(); } catch { }
if (Program.Canceled) return; if (Program.Canceled) return;
string dlcName = null; if (string.IsNullOrWhiteSpace(dlcName)) dlcName = $"Unnamed DLC ({id})";
Dictionary<string, string> dlcAppInfo = null; dlc.Add(new Tuple<int, string>(id, dlcName));
if (SteamCMD.GetAppInfo(id, out dlcAppInfo)) dlcAppInfo.TryGetValue("name", out dlcName);
if (Program.Canceled) return;
if (string.IsNullOrWhiteSpace(dlcName)) dlcName = "Unknown DLC";
dlc.Add(new Tuple<int, string>(id, dlcName));
}
}
catch { }
}); });
dlcTasks.Add(task); dlcTasks.Add(task);
RunningTasks.Add(task); RunningTasks.Add(task);
task.Start(); task.Start();
progress.Report(-RunningTasks.Count); progress.Report(-RunningTasks.Count);
} }
else if (identifier != "Paradox Launcher") return;
if (Program.Canceled) return;
if (string.IsNullOrWhiteSpace(identifier)) return;
string displayName = identifier;
if (!(appInfo is null)) appInfo.TryGetValue("name", out displayName);
if (string.IsNullOrWhiteSpace(displayName)) displayName = "Unknown Game";
if (Program.Canceled) return;
ProgramSelection selection = ProgramSelection.FromIdentifier(identifier) ?? new();
selection.Identifier = identifier;
selection.DisplayName = displayName;
selection.RootDirectory = rootDirectory;
selection.SteamAppId = steamAppId;
selection.SteamApiDllDirectories = steamApiDllDirectories;
selection.AppInfo = appInfo;
foreach (Task task in dlcTasks.ToList())
{
if (Program.Canceled) return;
progress.Report(cur++);
task.Wait();
}
if (Program.Canceled) return;
treeView1.Invoke((MethodInvoker)delegate
{
if (Program.Canceled) return;
TreeNode programNode = treeNodes.Find(s => s.Text == displayName) ?? new();
programNode.Text = displayName;
programNode.Remove();
treeView1.Nodes.Add(programNode);
treeNodes.Remove(programNode);
treeNodes.Add(programNode);
foreach (Tuple<int, string> dlcApp in dlc.ToList())
{
if (Program.Canceled || programNode is null) return;
TreeNode dlcNode = treeNodes.Find(s => s.Text == dlcApp.Item2) ?? new();
dlcNode.Text = dlcApp.Item2;
dlcNode.Remove();
programNode.Nodes.Add(dlcNode);
treeNodes.Remove(dlcNode);
treeNodes.Add(dlcNode);
selection.AllSteamDlc.Add(dlcApp);
selection.SelectedSteamDlc.Add(dlcApp);
}
});
} }
catch { } else if (name != "Paradox Launcher") return;
if (Program.Canceled) return;
if (string.IsNullOrWhiteSpace(name)) return;
if (Program.Canceled) return;
ProgramSelection selection = ProgramSelection.FromName(name) ?? new();
selection.Name = name;
selection.RootDirectory = directory;
selection.SteamAppId = appId;
selection.SteamApiDllDirectories = dllDirectories;
selection.AppInfo = appInfo;
foreach (Task task in dlcTasks.ToList())
{
if (Program.Canceled) return;
progress.Report(cur++);
task.Wait();
}
if (Program.Canceled) return;
treeView1.Invoke((MethodInvoker)delegate
{
if (Program.Canceled) return;
TreeNode programNode = treeNodes.Find(s => s.Text == name) ?? new();
programNode.Text = name;
programNode.Remove();
treeView1.Nodes.Add(programNode);
treeNodes.Remove(programNode);
treeNodes.Add(programNode);
foreach (Tuple<int, string> dlcApp in dlc.ToList())
{
if (Program.Canceled || programNode is null) return;
TreeNode dlcNode = treeNodes.Find(s => s.Text == dlcApp.Item2) ?? new();
dlcNode.Text = dlcApp.Item2;
dlcNode.Remove();
programNode.Nodes.Add(dlcNode);
treeNodes.Remove(dlcNode);
treeNodes.Add(dlcNode);
selection.AllSteamDlc.Add(dlcApp);
selection.SelectedSteamDlc.Add(dlcApp);
}
});
}); });
RunningTasks.Add(task); RunningTasks.Add(task);
task.Start(); task.Start();
@ -282,7 +289,7 @@ namespace CreamInstaller
ProgramSelection.All.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any()); ProgramSelection.All.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any());
foreach (TreeNode treeNode in treeNodes) foreach (TreeNode treeNode in treeNodes)
{ {
if (treeNode.Parent is null && ProgramSelection.FromDisplayName(treeNode.Text) is null) if (treeNode.Parent is null && ProgramSelection.FromName(treeNode.Text) is null)
{ {
treeNode.Remove(); treeNode.Remove();
} }
@ -297,7 +304,6 @@ namespace CreamInstaller
{ {
allCheckBox.Enabled = true; allCheckBox.Enabled = true;
treeView1.CheckBoxes = true; treeView1.CheckBoxes = true;
treeView1.ExpandAll();
treeNodes.ForEach(node => node.Checked = true); treeNodes.ForEach(node => node.Checked = true);
if (ProgramSelection.AllSafeEnabled.Any()) if (ProgramSelection.AllSafeEnabled.Any())
{ {
@ -315,10 +321,10 @@ namespace CreamInstaller
private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e) private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e)
{ {
ProgramSelection selection = ProgramSelection.FromDisplayName(e.Node.Text); ProgramSelection selection = ProgramSelection.FromName(e.Node.Text);
if (selection is null) if (selection is null)
{ {
selection = ProgramSelection.FromDisplayName(e.Node.Parent.Text); selection = ProgramSelection.FromName(e.Node.Parent.Text);
treeView1.AfterCheck -= OnTreeViewNodeCheckedChanged; treeView1.AfterCheck -= OnTreeViewNodeCheckedChanged;
e.Node.Parent.Checked = e.Node.Parent.Nodes.Cast<TreeNode>().ToList().Any(treeNode => treeNode.Checked); e.Node.Parent.Checked = e.Node.Parent.Nodes.Cast<TreeNode>().ToList().Any(treeNode => treeNode.Checked);
treeView1.AfterCheck += OnTreeViewNodeCheckedChanged; treeView1.AfterCheck += OnTreeViewNodeCheckedChanged;
@ -339,30 +345,29 @@ namespace CreamInstaller
private void OnLoad(object sender, EventArgs e) private void OnLoad(object sender, EventArgs e)
{ {
treeView1.BeforeCollapse += (sender, e) => e.Cancel = true;
treeView1.AfterCheck += OnTreeViewNodeCheckedChanged; treeView1.AfterCheck += OnTreeViewNodeCheckedChanged;
OnLoad(); OnLoad();
} }
private static bool ParadoxLauncherDlcDialog(Form form) private static bool ParadoxLauncherDlcDialog(Form form)
{ {
ProgramSelection paradoxLauncher = ProgramSelection.FromIdentifier("Paradox Launcher"); ProgramSelection paradoxLauncher = ProgramSelection.FromName("Paradox Launcher");
if (!(paradoxLauncher is null) && paradoxLauncher.Enabled) if (!(paradoxLauncher is null) && paradoxLauncher.Enabled)
{ {
paradoxLauncher.ExtraSteamAppIdDlc = new(); paradoxLauncher.ExtraSteamAppIdDlc = new();
foreach (ProgramSelection selection in ProgramSelection.AllSafeEnabled) foreach (ProgramSelection selection in ProgramSelection.AllSafeEnabled)
{ {
if (selection.Identifier == paradoxLauncher.Identifier) continue; if (selection.Name == paradoxLauncher.Name) continue;
if (!selection.AppInfo.TryGetValue("publisher", out string publisher) || publisher != "Paradox Interactive") continue; if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") continue;
paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.DisplayName, selection.SelectedSteamDlc)); paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.SelectedSteamDlc));
} }
if (!paradoxLauncher.ExtraSteamAppIdDlc.Any()) if (!paradoxLauncher.ExtraSteamAppIdDlc.Any())
{ {
foreach (ProgramSelection selection in ProgramSelection.AllSafe) foreach (ProgramSelection selection in ProgramSelection.AllSafe)
{ {
if (selection.Identifier == paradoxLauncher.Identifier) continue; if (selection.Name == paradoxLauncher.Name) continue;
if (!selection.AppInfo.TryGetValue("publisher", out string publisher) || publisher != "Paradox Interactive") continue; if (selection.AppInfo.Value["extended"]["publisher"].ToString() != "Paradox Interactive") continue;
paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.DisplayName, selection.AllSteamDlc)); paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.Name, selection.AllSteamDlc));
} }
} }
if (!paradoxLauncher.ExtraSteamAppIdDlc.Any()) if (!paradoxLauncher.ExtraSteamAppIdDlc.Any())

View file

@ -1,4 +1,5 @@
using System; using Gameloop.Vdf;
using Gameloop.Vdf.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -53,37 +54,48 @@ namespace CreamInstaller
if (!File.Exists(DllPath)) Run($@"+quit", out _); if (!File.Exists(DllPath)) Run($@"+quit", out _);
} }
public static bool GetAppInfo(int steamAppId, out Dictionary<string, string> appInfo) private static Dictionary<int, int> retries = new();
public static bool GetAppInfo(int appId, int buildId, out VProperty appInfo)
{ {
appInfo = new(); appInfo = null;
if (Program.Canceled) return false; if (Program.Canceled) return false;
string output; string output;
string appUpdatePath = $@"{AppInfoCachePath}\{steamAppId}"; string appUpdatePath = $@"{AppInfoCachePath}\{appId}";
string appUpdateFile = $@"{appUpdatePath}\appinfo.txt"; string appUpdateFile = $@"{appUpdatePath}\appinfo.txt";
// need a fast way to make sure the cached info is up-to-date and correct if (Directory.Exists(appUpdatePath) && File.Exists(appUpdateFile)) output = File.ReadAllText(appUpdateFile);
//if (Directory.Exists(appUpdatePath) && File.Exists(appUpdateFile)) output = File.ReadAllText(appUpdateFile); else
//else
//{
Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {steamAppId} +force_install_dir {appUpdatePath} +app_update 4 +quit", out _);
Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {steamAppId} +quit", out output);
File.WriteAllText(appUpdateFile, output);
//}
if (Program.Canceled || output is null) return false;
foreach (string s in output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
{ {
if (Program.Canceled) return false; Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +force_install_dir {appUpdatePath} +app_update 4 +quit", out _);
int first = s.IndexOf("\""); Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +quit", out output);
int second = 1 + first + s.Substring(first + 1).IndexOf("\""); int openBracket = output.IndexOf("{");
int third = 1 + second + s.Substring(second + 1).IndexOf("\""); int closeBracket = output.LastIndexOf("}");
int fourth = 1 + third + s.Substring(third + 1).IndexOf("\""); output = $"\"{appId}\"\n" + output.Substring(openBracket, 1 + closeBracket - openBracket);
if (first > -1 && second > 0 && third > 0 && fourth > 0) File.WriteAllText(appUpdateFile, output);
}
if (Program.Canceled || output is null) return false;
appInfo = VdfConvert.Deserialize(output);
try
{
VToken type = appInfo?.Value?["common"]?["type"];
if (type is null || type.ToString() == "Game")
{ {
string a = s.Substring(first + 1, Math.Max(second - first - 1, 0)); string buildid = appInfo.Value["depots"]?["public"]?["buildid"]?.ToString();
string b = s.Substring(third + 1, Math.Max(fourth - third - 1, 0)); buildid = buildid ?? appInfo.Value["depots"]?["branches"]?["public"]?["buildid"]?.ToString();
if (string.IsNullOrWhiteSpace(a) || string.IsNullOrWhiteSpace(b)) continue; if (type is null || int.Parse(buildid) < buildId
if (!appInfo.TryGetValue(a, out _)) appInfo.Add(a, b); || appInfo.Value["extended"] is null
|| appInfo.Value["depots"] is null)
{
if (retries.TryGetValue(appId, out int count)) retries[appId] = ++count;
else retries.Add(appId, 1);
if (count > 3) return false;
File.Delete(appUpdateFile);
bool success = GetAppInfo(appId, buildId, out appInfo);
return success;
}
} }
} }
catch { }
return true; return true;
} }