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