diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index f2fc1a9..9817a4c 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -4,7 +4,7 @@ net7.0-windows10.0.22621.0 True Resources\ini.ico - 4.9.7 + 4.9.8 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 06daa50..bc8cead 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -369,14 +369,11 @@ internal sealed partial class SelectForm : CustomForm } if (Program.Canceled) return; - ConcurrentDictionary catalogItems = new(); - // get catalog items - ConcurrentDictionary entitlements = new(); List dlcTasks = new(); - List<(string id, string name, string product, string icon, string developer)> - entitlementIds = await EpicStore.QueryEntitlements(@namespace); - if (entitlementIds.Count > 0) - foreach ((string id, string name, string product, string icon, string developer) in entitlementIds) + ConcurrentDictionary catalogItems = new(); + List<(string id, string name, string product, string icon, string developer)> catalogIds = await EpicStore.QueryCatalog(@namespace); + if (catalogIds.Count > 0) + foreach ((string id, string name, string product, string icon, string developer) in catalogIds) { if (Program.Canceled) return; @@ -385,11 +382,11 @@ internal sealed partial class SelectForm : CustomForm { if (Program.Canceled) return; - SelectionDLC entitlement = SelectionDLC.GetOrCreate(DLCType.EpicEntitlement, @namespace, id, name); - entitlement.Icon = icon; - entitlement.Product = product; - entitlement.Publisher = developer; - _ = entitlements.TryAdd(entitlement, default); + SelectionDLC catalogItem = SelectionDLC.GetOrCreate(DLCType.Epic, @namespace, id, name); + catalogItem.Icon = icon; + catalogItem.Product = product; + catalogItem.Publisher = developer; + _ = catalogItems.TryAdd(catalogItem, default); RemoveFromRemainingDLCs(id); }); dlcTasks.Add(task); @@ -402,14 +399,14 @@ internal sealed partial class SelectForm : CustomForm return; await task; } - if (catalogItems.IsEmpty && entitlements.IsEmpty) + if (catalogItems.IsEmpty) { RemoveFromRemainingGames(name); return; } Selection selection = Selection.GetOrCreate(Platform.Epic, @namespace, name, directory, dllDirectories, await directory.GetExecutableDirectories(true)); - foreach ((SelectionDLC dlc, _) in entitlements.Where(dlc => dlc.Key.Name == selection.Name)) + foreach ((SelectionDLC dlc, _) in catalogItems.Where(dlc => dlc.Key.Name == selection.Name)) { if (Program.Canceled) return; @@ -425,16 +422,9 @@ internal sealed partial class SelectForm : CustomForm return; if (selection.TreeNode.TreeView is null) _ = selectionTreeView.Nodes.Add(selection.TreeNode); - if (!catalogItems.IsEmpty) - foreach ((SelectionDLC dlc, _) in catalogItems) - { - if (Program.Canceled) - return; - dlc.Selection = selection; - } - if (entitlements.IsEmpty) + if (catalogItems.IsEmpty) return; - foreach ((SelectionDLC dlc, _) in entitlements) + foreach ((SelectionDLC dlc, _) in catalogItems) { if (Program.Canceled) return; diff --git a/CreamInstaller/Platforms/Epic/EpicLibrary.cs b/CreamInstaller/Platforms/Epic/EpicLibrary.cs index cd7f21a..93e8b2d 100644 --- a/CreamInstaller/Platforms/Epic/EpicLibrary.cs +++ b/CreamInstaller/Platforms/Epic/EpicLibrary.cs @@ -39,7 +39,8 @@ internal static class EpicLibrary try { Manifest manifest = JsonConvert.DeserializeObject(json); - if (manifest is not null && games.All(g => g.CatalogNamespace != manifest.CatalogNamespace)) + if (manifest is not null && (manifest.InstallLocation = manifest.InstallLocation.ResolvePath()) is not null + && games.All(g => g.CatalogNamespace != manifest.CatalogNamespace)) games.Add(manifest); } catch diff --git a/CreamInstaller/Platforms/Epic/EpicStore.cs b/CreamInstaller/Platforms/Epic/EpicStore.cs index 9c492e5..c8eaafa 100644 --- a/CreamInstaller/Platforms/Epic/EpicStore.cs +++ b/CreamInstaller/Platforms/Epic/EpicStore.cs @@ -12,22 +12,15 @@ namespace CreamInstaller.Platforms.Epic; internal static class EpicStore { - //private const int CooldownCatalogItem = 600; + private const int Cooldown = 600; - /* need a method to query catalog items - internal static async Task QueryCatalogItems(Manifest manifest) - { - }*/ - - private const int CooldownEntitlement = 600; - - internal static async Task> QueryEntitlements(string categoryNamespace) + internal static async Task> QueryCatalog(string categoryNamespace) { List<(string id, string name, string product, string icon, string developer)> dlcIds = new(); string cacheFile = ProgramData.AppInfoPath + @$"\{categoryNamespace}.json"; bool cachedExists = cacheFile.FileExists(); Response response = null; - if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, CooldownEntitlement)) + if (!cachedExists || ProgramData.CheckCooldown(categoryNamespace, Cooldown)) { response = await QueryGraphQL(categoryNamespace); try diff --git a/CreamInstaller/Platforms/Epic/Heroic/HeroicLibrary.cs b/CreamInstaller/Platforms/Epic/Heroic/HeroicLibrary.cs index f7ffeba..c39bba2 100644 --- a/CreamInstaller/Platforms/Epic/Heroic/HeroicLibrary.cs +++ b/CreamInstaller/Platforms/Epic/Heroic/HeroicLibrary.cs @@ -28,7 +28,7 @@ internal static class HeroicLibrary try { HeroicAppData appData = token.ToObject(); - if (appData is null || string.IsNullOrWhiteSpace(appData.Install.InstallPath)) + if (appData is null || string.IsNullOrWhiteSpace(appData.Install.InstallPath = appData.Install.InstallPath.ResolvePath())) continue; Manifest manifest = new() { diff --git a/CreamInstaller/Platforms/Steam/SteamLibrary.cs b/CreamInstaller/Platforms/Steam/SteamLibrary.cs index 4de8132..f26469d 100644 --- a/CreamInstaller/Platforms/Steam/SteamLibrary.cs +++ b/CreamInstaller/Platforms/Steam/SteamLibrary.cs @@ -79,19 +79,19 @@ internal static class SteamLibrary private static async Task> GetLibraryDirectories() => await Task.Run(() => { - HashSet gameDirectories = new(); + HashSet libraryDirectories = new(); if (Program.Canceled) - return gameDirectories; + return libraryDirectories; string steamInstallPath = InstallPath; if (steamInstallPath == null || !steamInstallPath.DirectoryExists()) - return gameDirectories; + return libraryDirectories; string libraryFolder = steamInstallPath + @"\steamapps"; if (!libraryFolder.DirectoryExists()) - return gameDirectories; - _ = gameDirectories.Add(libraryFolder); + return libraryDirectories; + _ = libraryDirectories.Add(libraryFolder); string libraryFolders = libraryFolder + @"\libraryfolders.vdf"; if (!libraryFolders.FileExists() || !ValveDataFile.TryDeserialize(libraryFolders.ReadFile(), out VProperty result)) - return gameDirectories; + return libraryDirectories; foreach (VToken vToken in result.Value.Where(p => p is VProperty property && int.TryParse(property.Key, out int _))) { VProperty property = (VProperty)vToken; @@ -100,8 +100,8 @@ internal static class SteamLibrary continue; path += @"\steamapps"; if (path.DirectoryExists()) - _ = gameDirectories.Add(path); + _ = libraryDirectories.Add(path); } - return gameDirectories; + return libraryDirectories; }); } \ No newline at end of file diff --git a/CreamInstaller/Resources/ScreamAPI.cs b/CreamInstaller/Resources/ScreamAPI.cs index be54244..7760c99 100644 --- a/CreamInstaller/Resources/ScreamAPI.cs +++ b/CreamInstaller/Resources/ScreamAPI.cs @@ -25,23 +25,36 @@ internal static class ScreamAPI internal static void CheckConfig(string directory, Selection selection, InstallForm installForm = null) { directory.GetScreamApiComponents(out _, out _, out _, out _, out string config, out _); - HashSet overrideCatalogItems = selection.DLC.Where(dlc => dlc.Type is DLCType.EpicCatalogItem && !dlc.Enabled).ToHashSet(); - HashSet overrideEntitlements = selection.DLC.Where(dlc => dlc.Type is DLCType.EpicEntitlement && !dlc.Enabled).ToHashSet(); + HashSet overrideCatalogItems = selection.DLC.Where(dlc => dlc.Type is DLCType.Epic && !dlc.Enabled).ToHashSet(); + int entitlementCount = 0; + HashSet injectedEntitlements = new(); + foreach (SelectionDLC dlc in selection.DLC.Where(dlc => dlc.Type is DLCType.EpicEntitlement)) + { + if (dlc.Enabled) + _ = injectedEntitlements.Add(dlc); + entitlementCount++; + } foreach (Selection extraSelection in selection.ExtraSelections) { - foreach (SelectionDLC extraDlc in extraSelection.DLC.Where(dlc => dlc.Type is DLCType.EpicCatalogItem && !dlc.Enabled)) + foreach (SelectionDLC extraDlc in extraSelection.DLC.Where(dlc => dlc.Type is DLCType.Epic && !dlc.Enabled)) _ = overrideCatalogItems.Add(extraDlc); - foreach (SelectionDLC extraDlc in extraSelection.DLC.Where(dlc => dlc.Type is DLCType.EpicEntitlement && !dlc.Enabled)) - _ = overrideEntitlements.Add(extraDlc); + foreach (SelectionDLC extraDlc in extraSelection.DLC.Where(dlc => dlc.Type is DLCType.EpicEntitlement)) + { + if (extraDlc.Enabled) + _ = injectedEntitlements.Add(extraDlc); + entitlementCount++; + } } - if (overrideCatalogItems.Count > 0 || overrideEntitlements.Count > 0) + if (injectedEntitlements.Count == entitlementCount) + injectedEntitlements.Clear(); + if (overrideCatalogItems.Count > 0 || injectedEntitlements.Count > 0) { /*if (installForm is not null) installForm.UpdateUser("Generating ScreamAPI configuration for " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);*/ config.CreateFile(true, installForm).Close(); StreamWriter writer = new(config, true, Encoding.UTF8); WriteConfig(writer, new(overrideCatalogItems.ToDictionary(dlc => dlc.Id, dlc => dlc), PlatformIdComparer.String), - new(overrideEntitlements.ToDictionary(dlc => dlc.Id, dlc => dlc), PlatformIdComparer.String), installForm); + new(injectedEntitlements.ToDictionary(dlc => dlc.Id, dlc => dlc), PlatformIdComparer.String), installForm); writer.Flush(); writer.Close(); } @@ -52,8 +65,8 @@ internal static class ScreamAPI } } - private static void WriteConfig(TextWriter writer, SortedList overrideCatalogItems, SortedList entitlements, - InstallForm installForm = null) + private static void WriteConfig(TextWriter writer, SortedList overrideCatalogItems, + SortedList injectedEntitlements, InstallForm installForm = null) { writer.WriteLine("{"); writer.WriteLine(" \"version\": 2,"); @@ -79,23 +92,27 @@ internal static class ScreamAPI writer.WriteLine(" \"override\": []"); writer.WriteLine(" },"); writer.WriteLine(" \"entitlements\": {"); - writer.WriteLine(" \"unlock_all\": true,"); - writer.WriteLine(" \"auto_inject\": true,"); - if (entitlements.Count > 0) + if (injectedEntitlements.Count > 0) { + writer.WriteLine(" \"unlock_all\": false,"); + writer.WriteLine(" \"auto_inject\": false,"); writer.WriteLine(" \"inject\": ["); - KeyValuePair lastEntitlement = entitlements.Last(); - foreach (KeyValuePair pair in entitlements) + KeyValuePair lastEntitlement = injectedEntitlements.Last(); + foreach (KeyValuePair pair in injectedEntitlements) { SelectionDLC selectionDlc = pair.Value; writer.WriteLine($" \"{selectionDlc.Id}\"{(pair.Equals(lastEntitlement) ? "" : ",")}"); - installForm?.UpdateUser($"Added locked entitlement to ScreamAPI.json with id {selectionDlc.Id} ({selectionDlc.Name})", LogTextBox.Action, + installForm?.UpdateUser($"Added injected entitlement to ScreamAPI.json with id {selectionDlc.Id} ({selectionDlc.Name})", LogTextBox.Action, false); } writer.WriteLine(" ]"); } else + { + writer.WriteLine(" \"unlock_all\": true,"); + writer.WriteLine(" \"auto_inject\": true,"); writer.WriteLine(" \"inject\": []"); + } writer.WriteLine(" }"); writer.WriteLine("}"); } diff --git a/CreamInstaller/SelectionDLC.cs b/CreamInstaller/SelectionDLC.cs index 33bae83..5692eb4 100644 --- a/CreamInstaller/SelectionDLC.cs +++ b/CreamInstaller/SelectionDLC.cs @@ -8,7 +8,7 @@ namespace CreamInstaller; public enum DLCType { None = 0, Steam, SteamHidden, - EpicCatalogItem, EpicEntitlement + Epic, EpicEntitlement } internal sealed class SelectionDLC : IEquatable