Skip to content

Commit 1e3c532

Browse files
committed
Rework to use .NET 6 build
Separate into Core and Cli, rework the build to be using `dotnet build`/`dotnet publish` and target `net6`
1 parent 9ae466a commit 1e3c532

28 files changed

+720
-711
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[*]
2+
charset = utf-8
3+
insert_final_newline = true
4+
trim_trailing_whitespace = true
5+
end_of_line = crlf
6+
indent_style = space
7+
indent_size = 4
8+
tab_width = 4
9+
10+
[*.csproj]
11+
indent_size = 2
12+
tab_width = 2

.gitattributes

Lines changed: 0 additions & 2 deletions
This file was deleted.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[Bb]in/
2+
[Oo]bj/
3+
.vscode/

README

Whitespace-only changes.

VDFparse.Cli/Program.cs

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
using System.Text;
2+
using Microsoft.Win32;
3+
using VDFparse;
4+
5+
namespace VDFParse.Cli;
6+
7+
static class Program
8+
{
9+
static int Main(string[] args)
10+
{
11+
Console.OutputEncoding = Encoding.UTF8;
12+
switch (args.ElementAtOrDefault(0))
13+
{
14+
case "-v":
15+
case "--version":
16+
Console.WriteLine(typeof(Program).Assembly.GetName().Version);
17+
return 0;
18+
case "-?":
19+
case "/?":
20+
case "-h":
21+
case "--help":
22+
case null:
23+
Console.WriteLine(Translations.Get("HelpMessage"),
24+
typeof(Program).Assembly.GetName().Name);
25+
return 0;
26+
default:
27+
break;
28+
}
29+
switch (args[0])
30+
{
31+
case "list":
32+
case "info":
33+
if (args.Length < 2)
34+
{
35+
Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments"));
36+
return 4;
37+
}
38+
break;
39+
case "json":
40+
if (args.Length < 3)
41+
{
42+
Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments"));
43+
return 4;
44+
}
45+
break;
46+
case "query":
47+
if (args.Length < 4)
48+
{
49+
Console.Error.WriteLine(Translations.Get("ErrorNotEnoughArguments"));
50+
return 4;
51+
}
52+
break;
53+
default:
54+
Console.Error.WriteLine(Translations.Get("ErrorUnknownParameter"), args[0]);
55+
return 3;
56+
}
57+
VDFFile vdfFile = new VDFFile();
58+
string filePath;
59+
if (args[1] == "appinfo" || args[1] == "packageinfo")
60+
{
61+
string? steamPath;
62+
try
63+
{
64+
steamPath = GetSteamPath();
65+
Console.WriteLine(steamPath);
66+
if (steamPath is null)
67+
{
68+
Console.Error.WriteLine(Translations.Get("ErrorCannotFindSteam"));
69+
return 1;
70+
}
71+
}
72+
catch (PlatformNotSupportedException)
73+
{
74+
Console.Error.WriteLine(Translations.Get("ErrorPlatformUnsupported"));
75+
return 2;
76+
}
77+
if (args[1] == "appinfo")
78+
{
79+
filePath = Path.Combine(steamPath, "appcache", "appinfo.vdf");
80+
}
81+
else
82+
{
83+
filePath = Path.Combine(steamPath, "appcache", "packageinfo.vdf");
84+
}
85+
}
86+
else
87+
{
88+
filePath = args[1];
89+
}
90+
vdfFile.Read(filePath);
91+
try
92+
{
93+
vdfFile.Read(filePath);
94+
}
95+
// TODO: Catch explicit errors
96+
#pragma warning disable CA1031
97+
catch
98+
{
99+
Console.Error.WriteLine(Translations.Get("ErrorParsingFile"), filePath);
100+
return 7;
101+
}
102+
try
103+
{
104+
switch (args[0])
105+
{
106+
case "list":
107+
return List(vdfFile);
108+
case "info":
109+
return Info(vdfFile);
110+
}
111+
List<Dataset> processing;
112+
if (args[2] == "*")
113+
{
114+
processing = vdfFile.Datasets;
115+
}
116+
else
117+
{
118+
uint id;
119+
bool success = uint.TryParse(args[2], out id);
120+
if (!success)
121+
{
122+
Console.Error.WriteLine(Translations.Get("ErrorInvalidNumber"), args[2]);
123+
return 5;
124+
}
125+
var dataset = vdfFile.FindByID(id);
126+
if (dataset == null)
127+
{
128+
Console.Error.WriteLine(Translations.Get("ErrorNoId"), id);
129+
return 6;
130+
}
131+
processing = new List<Dataset> { dataset };
132+
}
133+
switch (args[0])
134+
{
135+
case "json":
136+
#pragma warning disable CA1806
137+
int.TryParse(args.ElementAtOrDefault(4), out int indent);
138+
return Json(processing, indent: 4);
139+
case "query":
140+
return Query(processing, args.Skip(3).ToArray());
141+
}
142+
}
143+
// TODO: catch explicit errors
144+
#pragma warning disable CA1031
145+
catch (Exception e)
146+
{
147+
Console.Error.WriteLine(Translations.Get("ErrorUnknown"), e.Message);
148+
}
149+
return 9;
150+
}
151+
152+
static int List(VDFFile source)
153+
{
154+
Console.WriteLine(String.Join("\n", source.Datasets.Select(dataset => dataset.ID)));
155+
return 0;
156+
}
157+
158+
static int Info(VDFFile source)
159+
{
160+
Console.WriteLine(source.Datasets.Count);
161+
return 0;
162+
}
163+
164+
static int Json(List<Dataset> datasets, int indent)
165+
{
166+
foreach (var dataset in datasets)
167+
{
168+
Console.WriteLine(dataset.Data.ToJSON(indent: indent));
169+
}
170+
return 0;
171+
}
172+
173+
static int Query(List<Dataset> datasets, string[] queries)
174+
{
175+
foreach (var dataset in datasets)
176+
{
177+
foreach (var query in queries)
178+
{
179+
Console.WriteLine(String.Join("\n", dataset.Data.Search(query)));
180+
}
181+
}
182+
return 0;
183+
}
184+
static string? GetSteamPath()
185+
{
186+
187+
if (OperatingSystem.IsWindows())
188+
{
189+
return Registry.CurrentUser
190+
.OpenSubKey("SOFTWARE\\Valve\\Steam")
191+
?.GetValue("SteamPath") as string;
192+
}
193+
else if (OperatingSystem.IsLinux())
194+
{
195+
var home = Environment.GetFolderPath(
196+
Environment.SpecialFolder.UserProfile);
197+
var paths = new[] {
198+
".steam",
199+
".steam/steam",
200+
".steam/root",
201+
".local/share/Steam",
202+
};
203+
204+
foreach (var path in paths)
205+
{
206+
var steamPath = Path.Combine(home, path);
207+
var appCache = Path.Combine(steamPath, "appcache");
208+
if (Directory.Exists(appCache))
209+
return steamPath;
210+
}
211+
return null;
212+
}
213+
214+
throw new PlatformNotSupportedException();
215+
}
216+
}

VDFparse.Cli/Translations.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Resources;
2+
using System.Globalization;
3+
4+
namespace VDFParse.Cli;
5+
6+
internal static class Translations
7+
{
8+
private static bool useFallback;
9+
private static string currentLanguage = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
10+
private static ResourceManager Resources = new(GetResourcePath(currentLanguage), typeof(Program).Assembly);
11+
private static ResourceManager FallbackResources = new(GetResourcePath("en"), typeof(Program).Assembly);
12+
13+
private static string GetResourcePath(string languageCode) =>
14+
$"{typeof(Translations).Namespace}.resources.language-{languageCode}";
15+
16+
// The resource for en should always be embedded
17+
// and is assumed to have all translations
18+
#pragma warning disable CA1304
19+
public static string Get(string id, bool fallback = false)
20+
{
21+
if (fallback || useFallback)
22+
return FallbackResources.GetString(id) ?? "TRANSLATION ERROR";
23+
24+
try
25+
{
26+
return Resources.GetString(id) ?? Get(id, true);
27+
}
28+
catch (MissingManifestResourceException)
29+
{
30+
useFallback = true;
31+
return Get(id, true);
32+
}
33+
34+
}
35+
}

VDFparse.Cli/VDFparse.Cli.csproj

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<AssemblyName>VDFparse</AssemblyName>
5+
<OutputType>Exe</OutputType>
6+
<PublishSingleFile>true</PublishSingleFile>
7+
</PropertyGroup>
8+
9+
<PropertyGroup>
10+
<OutputPath>../bin/Cli</OutputPath>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<ProjectReference Include="../VDFparse.Core/VDFparse.Core.csproj"/>
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<EmbeddedResource Include="resources/*.resources" />
19+
</ItemGroup>
20+
21+
<Import Project="../VDFparse.csproj" Label="Shared" />
22+
23+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Translations file for VDFparse (English)
2+
ErrorCannotFindSteam = Cannot find Steam
3+
ErrorPlatformUnsupported = Platform unsupported for automated locating
4+
ErrorUnknownParameter = Unknown parameter "{0}"
5+
ErrorNotEnoughArguments = Not enough Arguments
6+
ErrorInvalidNumber = Invalid Number "{0}"
7+
ErrorNoId = Could not find dataset with ID {0}
8+
ErrorParsingFile = Error while trying to parse "{0}"
9+
ErrorUnknown = Unknown Error while executing query: {0}
10+
HelpMessage = {0} - Parses and displays info about Steam .vdf files\n\nUSAGE\n {0} <info|list|json|query> <path> [options]\n\nDESCRIPTION\n info Show number of entries parsed\n\n list Show all appids found\n\n json Show key value of an app as JSON\n options:\n appid The appid of the app to use\n\n\n query Query specified values for the specified keys\n options:\n appid The appid of the app to use\n query The name of the value to query for\n\n path A path to a vdf file. Use `appinfo` or `packageinfo` to\n automatically search for these files in the local Steam\n installation.\n\nEXAMPLES\n {0} info <path>\n Show the number of entries parsed in the vdf file specified by <path>\n\n {0} json <path> <appid>\n Show the key value data of <appid> in the vdf file specified by <path>\n\n {0} list <path>\n Show all appids found in the vdf file specified by <path>\n\n {0} query <path> <appid> <query> [query [...]]\n Query for a value of <appid> in the vdf file specified by <path>
1.89 KB
Binary file not shown.

VDFparse.Core/VDFFile.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System.Collections.ObjectModel;
2+
3+
namespace VDFparse;
4+
5+
public interface IVDFFileReader
6+
{
7+
public uint Magic { get; }
8+
public List<Dataset> Read(BinaryReader reader);
9+
}
10+
11+
public class VDFFile
12+
{
13+
private static List<IVDFFileReader> Readers = new List<IVDFFileReader>(){
14+
new PackageInfoReaderOld(),
15+
new PackageInfoReader(),
16+
new AppInfoReader(),
17+
};
18+
19+
public List<Dataset> Datasets { get; private set; } = new();
20+
21+
public EUniverse Universe { get; private set; }
22+
23+
public void Read(string filename)
24+
{
25+
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
26+
{
27+
Read(fs);
28+
}
29+
}
30+
31+
public void Read(Stream stream)
32+
{
33+
using (var reader = new BinaryReader(stream))
34+
{
35+
var magic = reader.ReadUInt32();
36+
Universe = (EUniverse)reader.ReadUInt32();
37+
foreach (var reader_sub in Readers)
38+
{
39+
if (magic == reader_sub.Magic)
40+
{
41+
Datasets = reader_sub.Read(reader);
42+
return;
43+
}
44+
}
45+
var hexHeader = Convert.ToHexString(BitConverter.GetBytes(magic));
46+
throw new InvalidDataException($"Unknown header: {hexHeader}");
47+
}
48+
}
49+
50+
public Dataset? FindByID(uint id)
51+
{
52+
foreach (var dataset in Datasets)
53+
{
54+
if (dataset.ID == id)
55+
{
56+
return dataset;
57+
}
58+
}
59+
return null;
60+
}
61+
}
62+
63+
public record Dataset(uint ID, ReadOnlyCollection<byte> Hash,
64+
ulong Token, uint ChangeNumber, KVObject Data);
65+
66+
public enum EUniverse
67+
{
68+
Invalid = 0,
69+
Public = 1,
70+
Beta = 2,
71+
Internal = 3,
72+
Dev = 4,
73+
Max = 5,
74+
}

0 commit comments

Comments
 (0)