From e7af4ac2527fb301dc1e68b7eb38cb476bc3b700 Mon Sep 17 00:00:00 2001 From: Terry MacDonald Date: Sat, 14 Nov 2020 17:42:53 +1300 Subject: [PATCH] Reads Uplay game info correctly Added the functionality to read the Uplay library correctly, but at present nothing is done with that information. Next step is to add it to the Shortcut Game selector logic. --- HeliosPlus/GameLibraries/UplayLibrary.cs | 109 ++++++++++++++++------- 1 file changed, 76 insertions(+), 33 deletions(-) diff --git a/HeliosPlus/GameLibraries/UplayLibrary.cs b/HeliosPlus/GameLibraries/UplayLibrary.cs index 97f42da..7c998b0 100644 --- a/HeliosPlus/GameLibraries/UplayLibrary.cs +++ b/HeliosPlus/GameLibraries/UplayLibrary.cs @@ -35,7 +35,7 @@ namespace HeliosPlus.GameLibraries { public uint GameID; public string GameName; - public List GameExes; + public string GameExe; public string GameInstallDir; public string GameUplayIconPath; } @@ -291,8 +291,8 @@ namespace HeliosPlus.GameLibraries //string uplayInstallDir = uplayInstallKey.GetValue("InstallDir", "C:\\Program Files (x86)\\Ubisoft\\Ubisoft Game Launcher\\").ToString(); // Access {installdir}\\cache\\configuration\\configurations file - string mypath = _uplayPath + @"cache\\configuration\\configurations"; - string uplayConfigFileString = File.ReadAllText(mypath); + string uplayConfigFilePath = _uplayPath + @"cache\configuration\configurations"; + string uplayConfigFileString = File.ReadAllText(uplayConfigFilePath); uplayConfigFileString = uplayConfigFileString.Remove(0, 12); // Split the file into records at the SOH unicode character List uplayConfigFile = uplayConfigFileString.Split((Char)1).ToList(); @@ -319,6 +319,10 @@ namespace HeliosPlus.GameLibraries // if we get here then we have a real game to parse! // Yay us :). + // First we want to know the index of the start_game entry to use later + int startGameIndex = uplayEntryLines.FindIndex(a => a == " start_game:"); + MatchCollection mc; + // First we check if there are any localization CONSTANTS that we will need to map later. Dictionary localizations = new Dictionary(); int localizationsIndex = uplayEntryLines.FindIndex(a => a == "localizations:"); @@ -331,56 +335,95 @@ namespace HeliosPlus.GameLibraries // Grab all EntryLines with 4 leading spaces (these are all the localizations) while (uplayEntryLines[currentIndex].StartsWith(" ")){ - string[] split = uplayEntryLines[currentIndex].Trim().Split(':'); - localizations.Add(split[0], split[1]); + string[] split = uplayEntryLines[currentIndex].Split(':'); + localizations.Add(split[0].Trim(), split[1].Trim()); currentIndex++; } } // for each game record grab: + UplayAppInfo uplayGameAppInfo = new UplayAppInfo(); + // name: (lookup the id in lookup table to find the name if needed) + if (uplayEntryLines.Exists(a => a.StartsWith(" name:", StringComparison.InvariantCultureIgnoreCase))) + { + mc = Regex.Matches(uplayEntry, @" name\: (.*)"); + uplayGameAppInfo.GameName = mc[0].Groups[1].ToString(); + // if the name contains a localization reference, then dereference it + if (localizations.ContainsKey(uplayGameAppInfo.GameName)) + { + uplayGameAppInfo.GameName = localizations[uplayGameAppInfo.GameName]; + } + } + else + continue; - - // thumb_image: (lookup the id in lookup table to find the thumbnail) // icon_image: (lookup the id in lookup table to find the ICON) + if (uplayEntryLines.Exists(a => a.StartsWith(" icon_image:", StringComparison.InvariantCultureIgnoreCase))) + { + mc = Regex.Matches(uplayEntry, @" icon_image: (.*)"); + string iconImageFileName = mc[0].Groups[1].ToString(); + // if the icon_image contains a localization reference, then dereference it + if (localizations.ContainsKey(iconImageFileName)) + { + iconImageFileName = localizations[iconImageFileName]; + } + //61fdd16f06ae08158d0a6d476f1c6bd5.ico + string uplayGameIconPath = _uplayPath + @"data\games\" + iconImageFileName; + if (File.Exists(uplayGameIconPath) && uplayGameIconPath.EndsWith(".ico")) + { + uplayGameAppInfo.GameUplayIconPath = uplayGameIconPath; + } + } + // find the exe name looking at root: -> start_game: -> online: -> executables: -> path: -> relative: (get ACU.exe) // Lookup the Game registry key from looking at root: -> start_game: -> online: -> executables: -> working_directory: -> register: (get HKEY_LOCAL_MACHINE\SOFTWARE\Ubisoft\Launcher\Installs\720\InstallDir) // Extract the GameAppID from the number in the working directory (e.g. 720) // Lookup the Game install path by reading the game registry key: D:/Ubisoft Game Launcher/Assassin's Creed Unity/ // join the Game install path and the exe name to get the full game exe path: D:/Ubisoft Game Launcher/Assassin's Creed Unity/ACU.exe - // Then we have the gameID, the thumbimage, the icon, the name, the exe path - } + //if (uplayEntryLines.Find (a => a.StartsWith(" icon_image:", StringComparison.InvariantCultureIgnoreCase))) - List uplayAppIdsInstalled = new List(); - // Now look for what games app id's are actually installed on this computer - using (RegistryKey uplayAppsKey = Registry.CurrentUser.OpenSubKey(registryUplayInstallsKey, RegistryKeyPermissionCheck.ReadSubTree)) - { - if (uplayAppsKey != null) + string gameFileName = ""; + bool gotGameFileName = false; + string gameId = ""; + bool gotGameId = false; + for (int i = startGameIndex; i<= (startGameIndex+30); i++) { - // Loop through the subKeys as they are the Uplay Game IDs - foreach (string uplayGameKeyName in uplayAppsKey.GetSubKeyNames()) + // Stop this loop once we have both filname and gameid + if (gotGameFileName && gotGameId) + break; + + // This line contains the filename + if (uplayEntryLines[i].StartsWith(" relative:") && !gotGameFileName) { - uint uplayAppId = 0; - if (uint.TryParse(uplayGameKeyName, out uplayAppId)) - { - string uplayGameKeyFullName = $"{ registryUplayInstallsKey}\\{uplayGameKeyName}"; - using (RegistryKey uplayGameKey = Registry.CurrentUser.OpenSubKey(uplayGameKeyFullName, RegistryKeyPermissionCheck.ReadSubTree)) - { - // If the Installed Value is set to 1, then the game is installed - // We want to keep track of that for later - if ((int)uplayGameKey.GetValue(@"Installed", 0) == 1) - { - // Add this Uplay App ID to the list we're keeping for later - uplayAppIdsInstalled.Add(uplayAppId); - } - - } - - } + mc = Regex.Matches(uplayEntryLines[i], @" relative: (.*)"); + gameFileName = mc[0].Groups[1].ToString(); + gotGameFileName = true; + } + // This line contains the registryKey + if (uplayEntryLines[i].StartsWith(" register: HKEY_LOCAL_MACHINE") && !gotGameId) + { + // Lookup the GameId within the registry key + mc = Regex.Matches(uplayEntryLines[i], @"Installs\\(\d+)\\InstallDir"); + gameId = mc[0].Groups[1].ToString(); + gotGameId = true; } } + + // Now we need to lookup the game install path in registry using the gameId + string registryUplayGameInstallsKey = registryUplayInstallsKey + "\\" + gameId; + RegistryKey uplayGameInstallKey = Registry.LocalMachine.OpenSubKey(registryUplayGameInstallsKey, RegistryKeyPermissionCheck.ReadSubTree); + + // From that we lookup the actual game path + uplayGameAppInfo.GameInstallDir = Path.GetFullPath(uplayGameInstallKey.GetValue("InstallDir", "").ToString()).TrimEnd('\\'); + uplayGameAppInfo.GameExe = uplayGameAppInfo.GameInstallDir + gameFileName; + uplayGameAppInfo.GameID = uint.Parse(gameId); + + // Then we have the gameID, the thumbimage, the icon, the name, the exe path + // And we add the Game to the list of games we have! + _allUplayGames.Add(new UplayGame(uplayGameAppInfo.GameID, uplayGameAppInfo.GameName, uplayGameAppInfo.GameExe, uplayGameAppInfo.GameUplayIconPath)); } }