private string GetInstallPath(string steamInstallPath) { string installPath = string.Empty; string basePath = string.Format(@"{0}\{1}", steamInstallPath, "steamapps"); string[] files = Directory.GetFiles(basePath, "*.acf"); foreach (var file in files) { var reader = new AcfReader(file); if (reader.CheckIntegrity()) { var manifestObject = reader.ACFFileToStruct(); ACF_Struct appState = null; manifestObject.SubACF.TryGetValue("AppState", out appState); if (appState != null) { string gameName = null; appState.SubItems.TryGetValue("name", out gameName); if (gameName != null && gameName == ReflexNameInSteam) { installPath = string.Format(@"{0}\steamapps\common\{1}", steamInstallPath, manifestObject.SubACF["AppState"].SubItems["installdir"]); break; } } } } return(installPath); }
// // Load ACF files from a given directory and return the ACFs' data // static List <AppInfo> ReadSteamManifestsFromDir(string directory) { List <AppInfo> apps = new List <AppInfo>(); Console.WriteLine("Scanning for games in " + directory); if (Directory.Exists(directory)) { string[] files = Directory.GetFiles(directory); List <string> acfFiles = new List <string>(); foreach (string file in files) { if (file.Substring(file.Length - 4) == ".acf") { acfFiles.Add(file); } } foreach (string file in acfFiles) { AcfReader acfReader = new AcfReader(file); ACF_Struct acf = acfReader.ACFFileToStruct(); AppInfo app = new AppInfo(); app.name = acf.SubACF["AppState"].SubItems["name"]; app.id = acf.SubACF["AppState"].SubItems["appid"]; app.source = "Steam"; app.fileSource = file; apps.Add(app); //Console.WriteLine("Added " + app.name + " (" + app.id + ") to the database"); } } return(apps); }
private ACF_Struct ACFFileToStruct(string RegionToReadIn) { ACF_Struct ACF = new(); int LengthOfRegion = RegionToReadIn.Length; int CurrentPos = 0; while (LengthOfRegion > CurrentPos) { int FirstItemStart = RegionToReadIn.IndexOf('"', CurrentPos); if (FirstItemStart == -1) { break; } int FirstItemEnd = RegionToReadIn.IndexOf('"', FirstItemStart + 1); CurrentPos = FirstItemEnd + 1; string FirstItem = ""; if (FirstItemEnd - FirstItemStart - 1 >= 0) { FirstItem = RegionToReadIn.Substring(FirstItemStart + 1, FirstItemEnd - FirstItemStart - 1); } int SecondItemStartQuote = RegionToReadIn.IndexOf('"', CurrentPos); int SecondItemStartBraceleft = RegionToReadIn.IndexOf('{', CurrentPos); if (SecondItemStartBraceleft == -1 || SecondItemStartQuote < SecondItemStartBraceleft) { int SecondItemEndQuote = RegionToReadIn.IndexOf('"', SecondItemStartQuote + 1); string SecondItem = ""; if (SecondItemEndQuote - SecondItemStartQuote - 1 >= 0) { SecondItem = RegionToReadIn.Substring(SecondItemStartQuote + 1, SecondItemEndQuote - SecondItemStartQuote - 1); } CurrentPos = SecondItemEndQuote + 1; if (!ACF.SubItems.ContainsKey(FirstItem)) { ACF.SubItems.Add(FirstItem, SecondItem); } else { break; } } else { int SecondItemEndBraceright = RegionToReadIn.NextEndOf('{', '}', SecondItemStartBraceleft + 1); ACF_Struct ACFS = null; if (SecondItemEndBraceright - SecondItemStartBraceleft - 1 >= 0) { ACFS = ACFFileToStruct(RegionToReadIn.Substring(SecondItemStartBraceleft + 1, SecondItemEndBraceright - SecondItemStartBraceleft - 1)); } CurrentPos = SecondItemEndBraceright + 1; if (!ACF.SubACF.ContainsKey(FirstItem)) { ACF.SubACF.Add(FirstItem, ACFS); } } } return(ACF); }
// // Find extra Steam libraries // static string[] GetSteamLibraryFolders(string SteamAppsLocation) { List <string> outList = new List <string>(); if (Directory.Exists(SteamAppsLocation) && File.Exists(SteamAppsLocation + "/libraryfolders.vdf")) { AcfReader acfReader = new AcfReader(SteamAppsLocation + "/libraryfolders.vdf"); ACF_Struct acf = acfReader.ACFFileToStruct(); foreach (string key in acf.SubACF["LibraryFolders"].SubItems.Keys) { if (Regex.IsMatch(key, @"^\d+$")) { outList.Add(acf.SubACF["LibraryFolders"].SubItems[key] + "/steamapps"); Console.WriteLine("Found Steam library at " + acf.SubACF["LibraryFolders"].SubItems[key] + "/steamapps"); } } } return(outList.ToArray()); }
public void GetGames(List <ImportGameData> gameDataList, bool expensiveIcons = false) { string strInstallPath = ""; string strClientPath = ""; using (RegistryKey key = Registry.LocalMachine.OpenSubKey(STEAM_REG, RegistryKeyPermissionCheck.ReadSubTree)) // HKLM32 { if (key == null) { CLogger.LogInfo("{0} client not found in the registry.", _name.ToUpper()); return; } strInstallPath = GetRegStrVal(key, GAME_INSTALL_PATH); strClientPath = Path.Combine(strInstallPath, STEAM_PATH); } if (!Directory.Exists(strClientPath)) { CLogger.LogInfo("{0} library not found: {1}", _name.ToUpper(), strClientPath); return; } string libFile = Path.Combine(strClientPath, STEAM_LIBFILE); List <string> libs = new() { strClientPath }; int nLibs = 1; try { if (File.Exists(libFile)) { SteamWrapper document = new(libFile); ACF_Struct documentData = document.ACFFileToStruct(); ACF_Struct folders = new(); if (documentData.SubACF.ContainsKey(STEAM_LIBARR)) { folders = documentData.SubACF[STEAM_LIBARR]; } else if (documentData.SubACF.ContainsKey(STEAM_LIBARR.ToLower())) { folders = documentData.SubACF[STEAM_LIBARR.ToLower()]; } for (; nLibs <= STEAM_MAX_LIBS; ++nLibs) { folders.SubItems.TryGetValue(nLibs.ToString(), out string library); if (string.IsNullOrEmpty(library)) { if (folders.SubACF.ContainsKey(nLibs.ToString())) { folders.SubACF[nLibs.ToString()].SubItems.TryGetValue("path", out library); } if (string.IsNullOrEmpty(library)) { nLibs--; break; } } library = Path.Combine(library, STEAM_PATH); if (!library.Equals(strClientPath) && Directory.Exists(library)) { libs.Add(library); } } } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} file: {1}", _name.ToUpper(), libFile)); nLibs--; } int i = 0; List <string> allFiles = new(); foreach (string lib in libs) { List <string> libFiles = new(); try { libFiles = Directory.GetFiles(lib, "appmanifest_*.acf", SearchOption.TopDirectoryOnly).ToList(); allFiles.AddRange(libFiles); CLogger.LogInfo("{0} {1} games found in library {2}", libFiles.Count, _name.ToUpper(), lib); } catch (Exception e) { CLogger.LogError(e, string.Format("{0} directory read error: {1}", _name.ToUpper(), lib)); continue; } foreach (string file in libFiles) { try { SteamWrapper document = new(file); ACF_Struct documentData = document.ACFFileToStruct(); ACF_Struct app = documentData.SubACF["AppState"]; string id = app.SubItems["appid"]; if (id.Equals("228980")) // Steamworks Common Redistributables { continue; } string strID = Path.GetFileName(file); string strTitle = app.SubItems["name"]; CLogger.LogDebug($"- {strTitle}"); string strLaunch = START_GAME + "/" + id; string strIconPath = ""; string strUninstall = ""; string strAlias = ""; string strPlatform = GetPlatformString(ENUM); strAlias = GetAlias(strTitle); if (!string.IsNullOrEmpty(strLaunch)) { using (RegistryKey key = Registry.LocalMachine.OpenSubKey(Path.Combine(NODE64_REG, STEAM_GAME_PREFIX + id), RegistryKeyPermissionCheck.ReadSubTree), // HKLM64 key2 = Registry.LocalMachine.OpenSubKey(Path.Combine(NODE32_REG, STEAM_GAME_PREFIX + id), RegistryKeyPermissionCheck.ReadSubTree)) // HKLM32 { if (key != null) { strIconPath = GetRegStrVal(key, GAME_DISPLAY_ICON).Trim(new char[] { ' ', '"' }); } else if (key2 != null) { strIconPath = GetRegStrVal(key2, GAME_DISPLAY_ICON).Trim(new char[] { ' ', '"' }); } } if (string.IsNullOrEmpty(strIconPath) && expensiveIcons) { bool success = false; // Search for an .exe to use as icon strIconPath = CGameFinder.FindGameBinaryFile(Path.Combine(lib, "common", app.SubItems["installdir"]), strTitle); if (!string.IsNullOrEmpty(strIconPath)) { success = true; strAlias = GetAlias(Path.GetFileNameWithoutExtension(strIconPath)); if (strAlias.Length > strTitle.Length) { strAlias = GetAlias(strTitle); } } if (!success && !(bool)(CConfig.GetConfigBool(CConfig.CFG_IMGDOWN))) { // Download missing icons string iconUrl = $"https://cdn.cloudflare.steamstatic.com/steam/apps/{id}/capsule_184x69.jpg"; if (CDock.DownloadCustomImage(strTitle, iconUrl)) { success = true; } } } if (strAlias.Equals(strTitle, CDock.IGNORE_CASE)) { strAlias = ""; } strUninstall = UNINST_GAME + "/" + id; gameDataList.Add(new ImportGameData(strID, strTitle, strLaunch, strIconPath, strUninstall, strAlias, true, strPlatform)); } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} file: {1}", _name.ToUpper(), file)); } } i++; /* * if (i > nLibs) * CLogger.LogDebug("---------------------"); */ } // Get not-installed games if (!(bool)CConfig.GetConfigBool(CConfig.CFG_INSTONLY)) { // First get Steam user ID ulong userId = (ulong)CConfig.GetConfigULong(CConfig.CFG_STEAMID); if (userId < 1) { try { ulong userIdTmp = 0; string userName = ""; string userNameTmp = ""; string strConfigPath = Path.Combine(strInstallPath, "config"); string appFile = Path.Combine(strConfigPath, STEAM_APPFILE); if (File.Exists(appFile)) { SteamWrapper appDoc = new(appFile); ACF_Struct appDocData = appDoc.ACFFileToStruct(); ACF_Struct appData = appDocData.SubACF["SteamAppData"]; appData.SubItems.TryGetValue("AutoLoginUser", out userName); SteamWrapper usrDoc = new(Path.Combine(strConfigPath, STEAM_USRFILE)); ACF_Struct usrDocData = usrDoc.ACFFileToStruct(); ACF_Struct usrData = usrDocData.SubACF["users"]; foreach (KeyValuePair <string, ACF_Struct> user in usrData.SubACF) { if (!ulong.TryParse(user.Key, out userIdTmp)) { userIdTmp = 0; } foreach (KeyValuePair <string, string> userVal in user.Value.SubItems) { if (userVal.Key.Equals("AccountName")) { userNameTmp = userVal.Value; if (userNameTmp.Equals(userName)) { if (!ulong.TryParse(user.Key, out userId)) { userId = 0; } } } if (userVal.Key.Equals("MostRecent") && userVal.Value.Equals("1") && string.IsNullOrEmpty(userName)) { userId = userIdTmp; userName = userNameTmp; break; } } } if (userId < 1) { userId = userIdTmp; userName = userNameTmp; } } if (userId > 0) { CLogger.LogInfo("Setting default {0} user to {1} #{2}", _name.ToUpper(), userName, userId); CConfig.SetConfigValue(CConfig.CFG_STEAMID, userId); ExportConfig(); } } catch (Exception e) { CLogger.LogError(e, string.Format("Malformed {0} file: {1} or {2}", _name.ToUpper(), STEAM_APPFILE, STEAM_USRFILE)); } } if (userId > 0) { // Download game list from public user profile try { string url = string.Format("https://steamcommunity.com/profiles/{0}/games/?tab=all", userId); /* #if DEBUG * // Don't re-download if file exists * string tmpfile = $"tmp_{NAME}.html"; * if (!File.Exists(tmpfile)) * { * using (var client = new WebClient()); * client.DownloadFile(url, tmpfile); * } * HtmlDocument doc = new HtmlDocument * { * OptionUseIdAttribute = true * }; * doc.Load(tmpfile); #else */ HtmlWeb web = new() { UseCookies = true }; HtmlDocument doc = web.Load(url); doc.OptionUseIdAttribute = true; //#endif HtmlNode gameList = doc.DocumentNode.SelectSingleNode("//script[@language='javascript']"); if (gameList != null) { CLogger.LogDebug("{0} not-installed games (user #{1}):", _name.ToUpper(), userId); var options = new JsonDocumentOptions { AllowTrailingCommas = true }; string rgGames = gameList.InnerText.Remove(0, gameList.InnerText.IndexOf('[')); rgGames = rgGames.Remove(rgGames.IndexOf(';')); using JsonDocument document = JsonDocument.Parse(@rgGames, options); foreach (JsonElement game in document.RootElement.EnumerateArray()) { ulong id = GetULongProperty(game, "appid"); if (id > 0) { // Check if game is already installed string strID = $"appmanifest_{id}.acf"; bool found = false; foreach (string file in allFiles) { if (file.EndsWith(strID)) { found = true; } } if (!found) { string strTitle = GetStringProperty(game, "name"); string strPlatform = GetPlatformString(ENUM); // Add not-installed games CLogger.LogDebug($"- *{strTitle}"); gameDataList.Add(new ImportGameData(strID, strTitle, "", "", "", "", false, strPlatform)); // Use logo to download not-installed icons if (!(bool)(CConfig.GetConfigBool(CConfig.CFG_IMGDOWN))) { string iconUrl = GetStringProperty(game, "logo"); CDock.DownloadCustomImage(strTitle, iconUrl); } } } } } else { CLogger.LogInfo("Can't get not-installed {0} games. Profile may not be public.\n" + "To change this, go to <https://steamcommunity.com/my/edit/settings>.", _name.ToUpper()); } /* #if DEBUG * File.Delete(tmpfile); #endif */ } catch (Exception e) { CLogger.LogError(e); } CLogger.LogDebug("---------------------"); } } }