From 7d9c80aef39171a7103073ffa6438b3ee5d00f74 Mon Sep 17 00:00:00 2001 From: erri120 Date: Sat, 30 Nov 2019 11:31:41 +0100 Subject: [PATCH 1/2] SteamHandler will skip broken acf files --- Wabbajack.Common/SteamHandler.cs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Wabbajack.Common/SteamHandler.cs b/Wabbajack.Common/SteamHandler.cs index 0d91a489..54f492a2 100644 --- a/Wabbajack.Common/SteamHandler.cs +++ b/Wabbajack.Common/SteamHandler.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -8,7 +8,7 @@ using Microsoft.Win32; namespace Wabbajack.Common { - [DebuggerDisplay("{Name}")] + [DebuggerDisplay("{" + nameof(Name) + "}")] public class SteamGame { public int AppId; @@ -94,16 +94,26 @@ namespace Wabbajack.Common Directory.EnumerateFiles(p, "*.acf", SearchOption.TopDirectoryOnly).Do(f => { var steamGame = new SteamGame(); + var valid = false; File.ReadAllLines(f, Encoding.UTF8).Do(l => { - if(l.Contains("\"appid\"")) - steamGame.AppId = int.Parse(GetVdfValue(l)); - if (l.Contains("\"name\"")) - steamGame.Name = GetVdfValue(l); - if (l.Contains("\"installdir\"")) - steamGame.InstallDir = Path.Combine(p, "common", GetVdfValue(l)); + if (!l.Contains("\"appid\"")) + return; + if (!l.Contains("\"name\"")) + return; + if (!l.Contains("\"installdir\"")) + return; + + steamGame.AppId = int.Parse(GetVdfValue(l)); + steamGame.Name = GetVdfValue(l); + steamGame.InstallDir = Path.Combine(p, "common", GetVdfValue(l)); + + valid = true; }); + if (!valid) + return; + steamGame.Game = GameRegistry.Games.Values .FirstOrDefault(g => g.SteamIDs.Contains(steamGame.AppId) From c15ab95517b4ce38b17d691dd47089036076a0c3 Mon Sep 17 00:00:00 2001 From: erri120 Date: Sat, 30 Nov 2019 12:20:23 +0100 Subject: [PATCH 2/2] SteamHandler: added LoadWorkshopItems function --- Wabbajack.Common/SteamHandler.cs | 141 ++++++++++++++++++++++++++++--- 1 file changed, 130 insertions(+), 11 deletions(-) diff --git a/Wabbajack.Common/SteamHandler.cs b/Wabbajack.Common/SteamHandler.cs index 54f492a2..7093a748 100644 --- a/Wabbajack.Common/SteamHandler.cs +++ b/Wabbajack.Common/SteamHandler.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text; +using DynamicData; using Microsoft.Win32; namespace Wabbajack.Common @@ -15,6 +16,22 @@ namespace Wabbajack.Common public string Name; public string InstallDir; public Game? Game; + + public HashSet WorkshopItems; + /// + /// Combined size of all installed workshop items on disk in bytes + /// + public int WorkshopItemsSize; + } + + public class SteamWorkshopItem + { + public SteamGame Game; + public int ItemID; + /// + /// Size is in bytes + /// + public int Size; } /// @@ -97,18 +114,17 @@ namespace Wabbajack.Common var valid = false; File.ReadAllLines(f, Encoding.UTF8).Do(l => { - if (!l.Contains("\"appid\"")) - return; - if (!l.Contains("\"name\"")) - return; - if (!l.Contains("\"installdir\"")) - return; + if(l.Contains("\"appid\"")) + if (!int.TryParse(GetVdfValue(l), out steamGame.AppId)) + return; + if(l.Contains("\"name\"")) + steamGame.Name = GetVdfValue(l); + if(l.Contains("\"installdir\"")) + steamGame.InstallDir = Path.Combine(p, "common", GetVdfValue(l)); - steamGame.AppId = int.Parse(GetVdfValue(l)); - steamGame.Name = GetVdfValue(l); - steamGame.InstallDir = Path.Combine(p, "common", GetVdfValue(l)); - - valid = true; + if (steamGame.AppId != 0 && !string.IsNullOrWhiteSpace(steamGame.Name) && + !string.IsNullOrWhiteSpace(steamGame.InstallDir)) + valid = true; }); if (!valid) @@ -127,11 +143,114 @@ namespace Wabbajack.Common Games = games; } + public void LoadWorkshopItems(SteamGame game) + { + if(game.WorkshopItems == null) + game.WorkshopItems = new HashSet(); + + InstallFolders.Do(p => + { + var workshop = Path.Combine(p, "workshop"); + Directory.EnumerateFiles(workshop, "*.acf", SearchOption.TopDirectoryOnly).Do(f => + { + if (Path.GetFileName(f) != $"appworkshop_{game.AppId}.acf") + return; + + var foundAppID = false; + var workshopItemsInstalled = 0; + var workshopItemDetails = 0; + var currentItem = new SteamWorkshopItem(); + var bracketStart = 0; + var bracketEnd = 0; + var lines = File.ReadAllLines(f, Encoding.UTF8); + var end = false; + lines.Do(l => + { + if (end) + return; + if(currentItem == null) + currentItem = new SteamWorkshopItem(); + + var currentLine = lines.IndexOf(l); + if (l.Contains("\"appid\"") && !foundAppID) + { + if (!int.TryParse(GetVdfValue(l), out var appID)) + return; + + foundAppID = true; + + if (appID != game.AppId) + return; + } + + if (!foundAppID) + return; + + if (l.Contains("\"SizeOnDisk\"")) + { + if (!int.TryParse(GetVdfValue(l), out var sizeOnDisk)) + return; + + game.WorkshopItemsSize = sizeOnDisk; + } + + if (l.Contains("\"WorkshopItemsInstalled\"")) + workshopItemsInstalled = currentLine; + + if (l.Contains("\"WorkshopItemDetails\"")) + workshopItemDetails = currentLine; + + if (workshopItemsInstalled == 0) + return; + + if (currentLine <= workshopItemsInstalled + 1 && currentLine >= workshopItemDetails - 1) + return; + + if (currentItem.ItemID == 0) + if (!int.TryParse(GetSingleVdfValue(l), out currentItem.ItemID)) + return; + + if (currentItem.ItemID == 0) + return; + + if (bracketStart == 0 && l.Contains("{")) + bracketStart = currentLine; + + if (bracketEnd == 0 && l.Contains("}")) + bracketEnd = currentLine; + + if (bracketStart == 0) + return; + + if (currentLine == bracketStart + 1) + if (!int.TryParse(GetVdfValue(l), out currentItem.Size)) + return; + + if (bracketStart == 0 || bracketEnd == 0 || currentItem.ItemID == 0 || currentItem.Size == 0) + return; + + bracketStart = 0; + bracketEnd = 0; + currentItem.Game = game; + game.WorkshopItems.Add(currentItem); + currentItem = null; + end = true; + }); + }); + }); + } + private static string GetVdfValue(string line) { var trim = line.Trim('\t').Replace("\t", ""); string[] s = trim.Split('\"'); return s[3].Replace("\\\\", "\\"); } + + private static string GetSingleVdfValue(string line) + { + var trim = line.Trim('\t').Replace("\t", ""); + return trim.Split('\"')[1]; + } } }