From 5d05ccb3298475ebd6274cfa38f0a60586f232ad Mon Sep 17 00:00:00 2001 From: glax Date: Mon, 15 Jan 2024 19:30:22 +0100 Subject: [PATCH] GSI Config-File Installer --- CS2GSI.csproj | 15 ++++++ Class1.cs | 5 -- GSIConfigInstaller.cs | 57 ++++++++++++++++++++ Resources.Designer.cs | 93 ++++++++++++++++++++++++++++++++ Resources.resx | 24 +++++++++ gamestate_integration_cs2gsi.cfg | 23 ++++++++ 6 files changed, 212 insertions(+), 5 deletions(-) delete mode 100644 Class1.cs create mode 100644 GSIConfigInstaller.cs create mode 100644 Resources.Designer.cs create mode 100644 Resources.resx create mode 100644 gamestate_integration_cs2gsi.cfg diff --git a/CS2GSI.csproj b/CS2GSI.csproj index 6836c68..c0c3371 100644 --- a/CS2GSI.csproj +++ b/CS2GSI.csproj @@ -6,4 +6,19 @@ enable + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + True + True + Resources.resx + + + diff --git a/Class1.cs b/Class1.cs deleted file mode 100644 index 0c2c78e..0000000 --- a/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace CS2GSI; - -public class Class1 -{ -} \ No newline at end of file diff --git a/GSIConfigInstaller.cs b/GSIConfigInstaller.cs new file mode 100644 index 0000000..51d62ab --- /dev/null +++ b/GSIConfigInstaller.cs @@ -0,0 +1,57 @@ +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Microsoft.Win32; + +namespace CS2GSI; + +public class GsiConfigInstaller +{ + internal static void InstallGsi() + { + string installLocation = Path.Combine(GetInstallDirectory(), "game\\csgo\\cfg\\gamestate_integration_cs2gsi.cfg"); + File.WriteAllText(installLocation, Resources.GSI_CFG_Content); + } + + private static string GetInstallDirectory(int appId = 730) + { + string libraryFolderFilepath = GetLibraryFoldersFilePath(); + string? libraryPath = null; + string? appManifestFolderPath = null; + foreach (string line in File.ReadAllLines(libraryFolderFilepath)) + if (line.Contains("path")) + libraryPath = line.Split("\"").Last(split => split.Length > 0); + else if (line.Contains($"\"{appId}\"")) + appManifestFolderPath = Path.Combine(libraryPath!, $"steamapps\\appmanifest_{appId}.acf"); + + string installationPath = ""; + if (appManifestFolderPath is null) + throw new DirectoryNotFoundException($"No {appId} Installation found."); + foreach(string line in File.ReadAllLines(appManifestFolderPath)) + if (line.Contains("installdir")) + installationPath = Path.Combine(libraryPath!, "steamapps\\common", line.Split("\"").Last(split => split.Length > 0)); + + return installationPath; + } + + private static string GetLibraryFoldersFilePath() + { + string? path = null; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + path = GetLibraryFoldersFilePathWindows(); + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + path = "~/.local/share/Steam/steamapps/libraryfolders.vdf"; + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + path = "~/Library/Application Support/Steam/steamapps/libraryfolders.vdf"; + else throw new Exception("Could not get Installation FolderPath"); + return path ?? throw new FileNotFoundException("No libraryfolders.vdf found"); + } + + [SupportedOSPlatform("windows")] + private static string GetLibraryFoldersFilePathWindows() + { + string steamInstallation = + (string)(Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Valve\Steam", "SteamPath", null) ?? + throw new DirectoryNotFoundException("No Steam Installation found.")); + return Path.Combine(steamInstallation, "steamapps\\libraryfolders.vdf"); + } +} \ No newline at end of file diff --git a/Resources.Designer.cs b/Resources.Designer.cs new file mode 100644 index 0000000..d80d7af --- /dev/null +++ b/Resources.Designer.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CS2GSI { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CS2GSI.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to "CS2GSI" + ///{ + /// "uri" "http://127.0.0.1:3000" + /// "timeout" "2.0" + /// "buffer" "0.0" + /// "throttle" "0.1" + /// "heartbeat" "60.0" + /// "output" + /// { + /// "precision_time" "3" + /// "precision_position" "1" + /// "precision_vector" "3" + /// } + /// "data" + /// { + /// "provider" "1" + /// "map" "1" + /// "round" "1" + /// "player_id" "1" + /// "player_state" "1" + /// "player_match_stats" "1" + /// } + ///}. + /// + internal static string GSI_CFG_Content { + get { + return ResourceManager.GetString("GSI_CFG_Content", resourceCulture); + } + } + } +} diff --git a/Resources.resx b/Resources.resx new file mode 100644 index 0000000..6c843e9 --- /dev/null +++ b/Resources.resx @@ -0,0 +1,24 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + gamestate_integration_cs2gsi.cfg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral + + \ No newline at end of file diff --git a/gamestate_integration_cs2gsi.cfg b/gamestate_integration_cs2gsi.cfg new file mode 100644 index 0000000..10424a1 --- /dev/null +++ b/gamestate_integration_cs2gsi.cfg @@ -0,0 +1,23 @@ +"CS2GSI" +{ + "uri" "http://127.0.0.1:3000" + "timeout" "2.0" + "buffer" "0.0" + "throttle" "0.1" + "heartbeat" "60.0" + "output" + { + "precision_time" "3" + "precision_position" "1" + "precision_vector" "3" + } + "data" + { + "provider" "1" + "map" "1" + "round" "1" + "player_id" "1" + "player_state" "1" + "player_match_stats" "1" + } +} \ No newline at end of file