From 41a433bf3f125d5db756300c736f7a02e1a9c048 Mon Sep 17 00:00:00 2001 From: glax Date: Thu, 18 Jan 2024 00:06:39 +0100 Subject: [PATCH] Version 3: CS2GSI and CShocker libraries More extensive options for Events Setup on first start --- OpenCS2hock.sln.DotSettings | 2 + OpenCS2hock.sln.DotSettings.user | 1 + OpenCS2hock/Configuration.cs | 44 ++++++ OpenCS2hock/ConfiguredInteger.cs | 17 --- OpenCS2hock/Installer.cs | 27 ---- OpenCS2hock/OpenCS2hock.cs | 111 +++++++++----- OpenCS2hock/OpenCS2hock.csproj | 4 +- OpenCS2hock/OpenShock.cs | 45 ------ OpenCS2hock/Program.cs | 2 +- OpenCS2hock/Settings.cs | 70 --------- OpenCS2hock/Setup.cs | 242 +++++++++++++++++++++++++++++++ OpenCS2hock/Shocker.cs | 41 ------ OpenCS2hock/ShockerAction.cs | 29 ++++ README.md | 64 +++++--- 14 files changed, 436 insertions(+), 263 deletions(-) create mode 100644 OpenCS2hock/Configuration.cs delete mode 100644 OpenCS2hock/ConfiguredInteger.cs delete mode 100644 OpenCS2hock/Installer.cs delete mode 100644 OpenCS2hock/OpenShock.cs delete mode 100644 OpenCS2hock/Settings.cs create mode 100644 OpenCS2hock/Setup.cs delete mode 100644 OpenCS2hock/Shocker.cs create mode 100644 OpenCS2hock/ShockerAction.cs diff --git a/OpenCS2hock.sln.DotSettings b/OpenCS2hock.sln.DotSettings index 15ea657..78d8485 100644 --- a/OpenCS2hock.sln.DotSettings +++ b/OpenCS2hock.sln.DotSettings @@ -4,5 +4,7 @@ True True True + True + True True True \ No newline at end of file diff --git a/OpenCS2hock.sln.DotSettings.user b/OpenCS2hock.sln.DotSettings.user index 2aaabe6..87e528f 100644 --- a/OpenCS2hock.sln.DotSettings.user +++ b/OpenCS2hock.sln.DotSettings.user @@ -1,3 +1,4 @@  + True True \ No newline at end of file diff --git a/OpenCS2hock/Configuration.cs b/OpenCS2hock/Configuration.cs new file mode 100644 index 0000000..34f0560 --- /dev/null +++ b/OpenCS2hock/Configuration.cs @@ -0,0 +1,44 @@ +using CShocker.Shockers.Abstract; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; + +namespace OpenCS2hock; + +public struct Configuration +{ + public LogLevel LogLevel = LogLevel.Information; + + public List Shockers = new(); + + public List ShockerActions = new (); + + public Configuration() + { + + } + + public override string ToString() + { + return $"Loglevel: {Enum.GetName(typeof(LogLevel), LogLevel)}\n" + + $"Shockers: {string.Join("\n---", Shockers)}\n" + + $"Actions: {string.Join("\n---", ShockerActions)}"; + } + + internal static Configuration GetConfigurationFromFile(string? path = null, ILogger? logger = null) + { + string settingsFilePath = path ?? "config.json"; + if (!File.Exists(settingsFilePath)) + Setup.Run().SaveConfiguration(); + + Configuration c = JsonConvert.DeserializeObject(File.ReadAllText(settingsFilePath), new CShocker.Shockers.ShockerJsonConverter()); + foreach (Shocker cShocker in c.Shockers) + cShocker.SetLogger(logger); + return c; + } + + internal void SaveConfiguration(string? path = null) + { + string settingsFilePath = path ?? "config.json"; + File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(this, Formatting.Indented)); + } +} \ No newline at end of file diff --git a/OpenCS2hock/ConfiguredInteger.cs b/OpenCS2hock/ConfiguredInteger.cs deleted file mode 100644 index 53bc2d8..0000000 --- a/OpenCS2hock/ConfiguredInteger.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace OpenCS2hock; - -internal class ConfiguredInteger -{ - private readonly int _min, _max; - - internal ConfiguredInteger(int min = 0, int max = 50) - { - this._min = min; - this._max = max; - } - - internal int GetValue() - { - return Random.Shared.Next(_min, _max); - } -} \ No newline at end of file diff --git a/OpenCS2hock/Installer.cs b/OpenCS2hock/Installer.cs deleted file mode 100644 index c272ee4..0000000 --- a/OpenCS2hock/Installer.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Win32; -using Newtonsoft.Json; - -namespace OpenCS2hock; - -public static class Installer -{ - internal static Settings GetSettings(string? path = null) - { - string settingsFilePath = path ?? "config.json"; - if (!File.Exists(settingsFilePath)) - File.WriteAllText(settingsFilePath, JsonConvert.SerializeObject(new Settings(), Formatting.Indented)); - - return JsonConvert.DeserializeObject(File.ReadAllText(settingsFilePath)); - } - - internal static List GetShockers(Settings settings, Logger? logger = null) - { - List shockers = new(); - shockers.Add(new OpenShock(settings.OpenShockSettings.Endpoint, settings.OpenShockSettings.ApiKey, - settings.OpenShockSettings.Shockers, - new ConfiguredInteger(settings.IntensityRange.Min, settings.IntensityRange.Max), - new ConfiguredInteger(settings.DurationRange.Min, settings.DurationRange.Max), - logger)); - return shockers; - } -} \ No newline at end of file diff --git a/OpenCS2hock/OpenCS2hock.cs b/OpenCS2hock/OpenCS2hock.cs index e9082d7..7d8a871 100644 --- a/OpenCS2hock/OpenCS2hock.cs +++ b/OpenCS2hock/OpenCS2hock.cs @@ -1,25 +1,29 @@ using Microsoft.Extensions.Logging; +using CS2GSI; +using CShocker.Ranges; +using CShocker.Shockers.Abstract; +using CS2Event = CS2GSI.CS2GSI.CS2Event; namespace OpenCS2hock; +// ReSharper disable once InconsistentNaming public class OpenCS2hock { private readonly CS2GSI.CS2GSI _cs2GSI; - private readonly List _shockers; - private readonly Settings _settings; + private readonly Configuration _configuration; private readonly Logger? _logger; - public OpenCS2hock(string? settingsPath = null, Logger? logger = null) + public OpenCS2hock(string? configPath = null, bool editConfig = false, Logger? logger = null) { this._logger = logger; this._logger?.Log(LogLevel.Information, "Starting OpenCS2hock..."); - this._logger?.Log(LogLevel.Information, "Loading Settings..."); - _settings = Installer.GetSettings(settingsPath); - this._logger?.Log(LogLevel.Information, $"Loglevel set to {_settings.LogLevel}"); - this._logger?.UpdateLogLevel(_settings.LogLevel); - this._logger?.Log(LogLevel.Information, _settings.ToString()); - this._logger?.Log(LogLevel.Information, "Setting up Shockers..."); - this._shockers = Installer.GetShockers(_settings, logger); + this._logger?.Log(LogLevel.Information, "Loading Configuration..."); + this._configuration = Configuration.GetConfigurationFromFile(configPath, this._logger); + if(editConfig) + Setup.EditConfig(ref this._configuration); + this._logger?.Log(LogLevel.Information, $"Loglevel set to {_configuration.LogLevel}"); + this._logger?.UpdateLogLevel(_configuration.LogLevel); + this._logger?.Log(LogLevel.Information, _configuration.ToString()); this._cs2GSI = new CS2GSI.CS2GSI(_logger); this.SetupEventHandlers(); while(this._cs2GSI.IsRunning) @@ -29,41 +33,74 @@ public class OpenCS2hock private void SetupEventHandlers() { this._logger?.Log(LogLevel.Information, "Setting up EventHandlers..."); - foreach (Shocker shocker in this._shockers) + foreach (ShockerAction shockerAction in this._configuration.ShockerActions) { - foreach (KeyValuePair kv in _settings.Actions) + foreach (string shockerId in shockerAction.ShockerIds) { - switch (kv.Key) + Shocker shocker = this._configuration.Shockers.First(s => s.ShockerIds.Contains(shockerId)); + switch (shockerAction.TriggerEvent) { - case "OnKill": - this._cs2GSI.OnKill += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnDeath": - this._cs2GSI.OnDeath += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnRoundStart": - this._cs2GSI.OnRoundStart += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnRoundEnd": - this._cs2GSI.OnRoundOver += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnRoundLoss": - this._cs2GSI.OnRoundLoss += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnRoundWin": - this._cs2GSI.OnRoundWin += (cs2EventArgs) => shocker.Control(Settings.StringToAction(kv.Value)); - break; - case "OnDamageTaken": - this._cs2GSI.OnDamageTaken += (cs2EventArgs) => - shocker.Control(Settings.StringToAction(kv.Value), - intensity: MapInt(cs2EventArgs.ValueAsOrDefault(), 0, 100, - _settings.IntensityRange.Min, _settings.IntensityRange.Max)); - break; + case CS2Event.OnKill: this._cs2GSI.OnKill += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnHeadshot: this._cs2GSI.OnHeadshot += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnDeath: this._cs2GSI.OnDeath += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnFlashed: this._cs2GSI.OnFlashed += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnBurning: this._cs2GSI.OnBurning += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnSmoked: this._cs2GSI.OnSmoked += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnRoundStart: this._cs2GSI.OnRoundStart += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnRoundOver: this._cs2GSI.OnRoundOver += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnRoundWin: this._cs2GSI.OnRoundWin += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnRoundLoss: this._cs2GSI.OnRoundLoss += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnDamageTaken: this._cs2GSI.OnDamageTaken += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnMatchStart: this._cs2GSI.OnMatchStart += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnMatchOver: this._cs2GSI.OnMatchOver += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnMoneyChange: this._cs2GSI.OnMoneyChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnHealthChange: this._cs2GSI.OnHealthChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnArmorChange: this._cs2GSI.OnArmorChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnHelmetChange: this._cs2GSI.OnHelmetChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnEquipmentValueChange: this._cs2GSI.OnEquipmentValueChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnTeamChange: this._cs2GSI.OnTeamChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnPlayerChange: this._cs2GSI.OnPlayerChange += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnHalfTime: this._cs2GSI.OnHalfTime += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnFreezeTime: this._cs2GSI.OnFreezeTime += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnBombPlanted: this._cs2GSI.OnBombPlanted += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnBombDefused: this._cs2GSI.OnBombDefused += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.OnBombExploded: this._cs2GSI.OnBombExploded += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.AnyEvent: this._cs2GSI.AnyEvent += args => EventHandler(args, shockerId, shocker, shockerAction); break; + case CS2Event.AnyMessage: this._cs2GSI.AnyMessage += args => EventHandler(args, shockerId, shocker, shockerAction); break; + default: this._logger?.Log(LogLevel.Debug, $"CS2Event {nameof(shockerAction.TriggerEvent)} unknown."); break; } } } } + private void EventHandler(CS2EventArgs cs2EventArgs, string shockerId, Shocker shocker, ShockerAction shockerAction) + { + this._logger?.Log(LogLevel.Information, $"Shocker: {shocker}\nID: {shockerId}\nAction: {shockerAction}\nEventArgs: {cs2EventArgs}"); + shocker.Control(shockerAction.Action, shockerId, + GetIntensity(shockerAction.ValueFromInput, shockerAction.TriggerEvent, cs2EventArgs, shockerId)); + } + + private int GetIntensity(bool valueFromInput, CS2Event cs2Event, CS2EventArgs eventArgs, string shockerId) + { + return valueFromInput + ? IntensityFromCS2Event(cs2Event, eventArgs, shockerId) + : this._configuration.Shockers.First(shocker => shocker.ShockerIds.Contains(shockerId)) + .IntensityRange.GetRandomRangeValue(); + } + + private int IntensityFromCS2Event(CS2Event cs2Event, CS2EventArgs eventArgs, string shockerId) + { + IntensityRange configuredRangeForShocker = this._configuration.Shockers + .First(shocker => shocker.ShockerIds.Contains(shockerId)) + .IntensityRange; + return cs2Event switch + { + CS2Event.OnDamageTaken => MapInt(eventArgs.ValueAsOrDefault(), 0, 100, configuredRangeForShocker.Min, configuredRangeForShocker.Max), + CS2Event.OnArmorChange => MapInt(eventArgs.ValueAsOrDefault(), 0, 100, configuredRangeForShocker.Min, configuredRangeForShocker.Max), + _ => configuredRangeForShocker.GetRandomRangeValue() + }; + } + private int MapInt(int input, int fromLow, int fromHigh, int toLow, int toHigh) { int mappedValue = (input - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + toLow; diff --git a/OpenCS2hock/OpenCS2hock.csproj b/OpenCS2hock/OpenCS2hock.csproj index 3301029..e762ad9 100644 --- a/OpenCS2hock/OpenCS2hock.csproj +++ b/OpenCS2hock/OpenCS2hock.csproj @@ -6,10 +6,12 @@ enable enable OpenCS2Hock + false - + + diff --git a/OpenCS2hock/OpenShock.cs b/OpenCS2hock/OpenShock.cs deleted file mode 100644 index 7ef0945..0000000 --- a/OpenCS2hock/OpenShock.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Net.Http.Headers; -using System.Text; -using Microsoft.Extensions.Logging; - -namespace OpenCS2hock; - -internal class OpenShock : Shocker -{ - protected override void ControlInternal(ControlAction action, string shockerId, int intensity, int duration) - { - HttpRequestMessage request = new (HttpMethod.Post, $"{Endpoint}/1/shockers/control") - { - Headers = - { - UserAgent = { new ProductInfoHeaderValue("OpenCS2hock", "1") }, - Accept = { new MediaTypeWithQualityHeaderValue("application/json") } - }, - Content = new StringContent(@"[ { "+ - $"\"id\": \"{shockerId}\"," + - $"\"type\": {ControlActionToByte(action)},"+ - $"\"intensity\": {intensity},"+ - $"\"duration\": {duration}"+ - "}]", Encoding.UTF8, new MediaTypeHeaderValue("application/json")) - }; - request.Headers.Add("OpenShockToken", ApiKey); - HttpResponseMessage response = this.HttpClient.Send(request); - this.Logger?.Log(LogLevel.Debug, $"{request.RequestUri} response: {response.StatusCode}"); - } - - private byte ControlActionToByte(ControlAction action) - { - return action switch - { - ControlAction.Beep => 3, - ControlAction.Vibrate => 2, - ControlAction.Shock => 1, - _ => 0 - }; - } - - internal OpenShock(string endpoint, string apiKey, string[] shockerIds, ConfiguredInteger intensity, ConfiguredInteger duration, Logger? logger = null) : base(endpoint, apiKey, shockerIds, intensity, duration, logger) - { - - } -} \ No newline at end of file diff --git a/OpenCS2hock/Program.cs b/OpenCS2hock/Program.cs index 0bbee14..aa27900 100644 --- a/OpenCS2hock/Program.cs +++ b/OpenCS2hock/Program.cs @@ -6,6 +6,6 @@ public class Program { public static void Main(string[] args) { - OpenCS2hock openCS2Hock = new OpenCS2hock(logger: new Logger(LogLevel.Information)); + OpenCS2hock openCS2Hock = new OpenCS2hock(editConfig: true, logger: new Logger(LogLevel.Information)); } } \ No newline at end of file diff --git a/OpenCS2hock/Settings.cs b/OpenCS2hock/Settings.cs deleted file mode 100644 index e0cae3d..0000000 --- a/OpenCS2hock/Settings.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; - -namespace OpenCS2hock; - -public struct Settings -{ - public LogLevel LogLevel = LogLevel.Information; - public OpenShockSettings OpenShockSettings = new() - { - Endpoint = "https://api.shocklink.net", - ApiKey = "", - Shockers = Array.Empty() - }; - - public Range IntensityRange = new () - { - Min = 20, - Max = 60 - }; - - public Range DurationRange = new() - { - Min = 1000, - Max = 1000 - }; - - public Dictionary Actions = new() - { - {"OnKill", "Nothing"}, - {"OnDeath", "Shock"}, - {"OnRoundStart", "Vibrate"}, - {"OnRoundEnd", "Nothing"}, - {"OnRoundWin", "Beep"}, - {"OnRoundLoss", "Nothing"}, - {"OnDamageTaken", "Vibrate"} - }; - - public Settings() - { - - } - - public override string ToString() - { - return JsonConvert.SerializeObject(this, Formatting.Indented); - } - - internal static Shocker.ControlAction StringToAction(string str) - { - return str.ToLower() switch - { - "shock" => Shocker.ControlAction.Shock, - "vibrate" => Shocker.ControlAction.Vibrate, - "beep" => Shocker.ControlAction.Beep, - _ => Shocker.ControlAction.Nothing - }; - } -} - -public struct OpenShockSettings -{ - public string Endpoint, ApiKey; - public string[] Shockers; -} - -public struct Range -{ - public short Min, Max; -} \ No newline at end of file diff --git a/OpenCS2hock/Setup.cs b/OpenCS2hock/Setup.cs new file mode 100644 index 0000000..89f81ad --- /dev/null +++ b/OpenCS2hock/Setup.cs @@ -0,0 +1,242 @@ +using System.Text.RegularExpressions; +using CShocker.Ranges; +using CShocker.Shockers; +using CShocker.Shockers.Abstract; +using CShocker.Shockers.APIS; +using Microsoft.Extensions.Logging; +using CS2Event = CS2GSI.CS2GSI.CS2Event; + +namespace OpenCS2hock; + +public static class Setup +{ + + internal static Configuration Run() + { + Console.Clear(); + Console.WriteLine("Running first-time setup."); + Configuration c = new(); + + Console.WriteLine("First adding APIs:"); + Console.WriteLine("Press Enter."); + while (Console.ReadKey().Key != ConsoleKey.Enter) + {//NYAA + } + + bool addShocker = true; + while (c.Shockers.Count < 1 || addShocker) + { + Console.Clear(); + AddShockerApi(ref c); + Console.WriteLine("Add another Shocker-API (Y/N):"); + addShocker = Console.ReadKey().Key == ConsoleKey.Y; + } + + Console.Clear(); + Console.WriteLine("Now adding Actions:"); + Console.WriteLine("Press Enter."); + while (Console.ReadKey().Key != ConsoleKey.Enter) + {//NYAA + } + bool addAction = true; + while (c.ShockerActions.Count < 1 || addAction) + { + Console.Clear(); + AddAction(ref c); + Console.WriteLine("Add another Action (Y/N):"); + addAction = Console.ReadKey().Key == ConsoleKey.Y; + } + return c; + } + + internal static void EditConfig(ref Configuration c) + { + ConsoleKey? pressedKey = null; + while (pressedKey is not ConsoleKey.X && pressedKey is not ConsoleKey.Q) + { + Console.Clear(); + Console.WriteLine("Config Edit Mode."); + Console.WriteLine("What do you want to edit?"); + Console.WriteLine("1) LogLevel"); + Console.WriteLine("2) Shocker-APIs"); + Console.WriteLine("3) Event Actions"); + Console.WriteLine("\nq) Quit Edit Mode"); + pressedKey = Console.ReadKey().Key; + switch (pressedKey) + { + case ConsoleKey.D1: + Console.WriteLine("New LogLevel:"); + string[] levels = Enum.GetNames(); + for(int i = 0; i < levels.Length; i++) + Console.WriteLine($"{i}) {levels[i]}"); + int selected; + while (!int.TryParse(Console.ReadKey().KeyChar.ToString(), out selected) || selected < 0 || + selected >= levels.Length) + {//NYAA + } + c.LogLevel = Enum.Parse(levels[selected]); + break; + case ConsoleKey.D2: + bool addShocker = true; + while (c.Shockers.Count < 1 || addShocker) + { + Console.Clear(); + AddShockerApi(ref c); + Console.WriteLine("Add another Shocker-API (Y/N):"); + addShocker = Console.ReadKey().Key == ConsoleKey.Y; + } + break; + case ConsoleKey.D3: + bool addAction = true; + while (c.ShockerActions.Count < 1 || addAction) + { + Console.Clear(); + AddAction(ref c); + Console.WriteLine("Add another Action (Y/N):"); + addAction = Console.ReadKey().Key == ConsoleKey.Y; + } + break; + } + } + c.SaveConfiguration(); + } + + private static void AddShockerApi(ref Configuration c) + { + Console.WriteLine("Select API:"); + Console.WriteLine("1) OpenShock (HTTP)"); + Console.WriteLine("2) OpenShock (Serial)"); + Console.WriteLine("3) PiShock (HTTP)"); + Console.WriteLine("4) PiShock (Serial)"); + string? selectedChar = Console.ReadLine(); + int selected; + while (!int.TryParse(selectedChar, out selected) || selected < 1 || selected > 1) + selectedChar = Console.ReadLine(); + + Shocker newShocker; + switch (selected) + { + case 1: //OpenShock (HTTP) + string apiUri = QueryString("OpenShock API-Endpoint (https://api.shocklink.net):", + "https://api.shocklink.net"); + string apiKey = QueryString("OpenShock API-Key:",""); + Console.WriteLine("Shocker IDs associated with this API:"); + List shockerIds = GetShockerIds(c.Shockers); + IntensityRange intensityRange = GetIntensityRange(); + DurationRange durationRange = GetDurationRange(); + + newShocker = new OpenShockHttp(shockerIds, intensityRange, durationRange, apiUri, apiKey); + break; + // ReSharper disable thrice RedundantCaseLabel + case 2: //OpenShock (Serial) + case 3: //PiShock (HTTP) + case 4: //PiShock (Serial) + default: + throw new NotImplementedException(); + } + c.Shockers.Add(newShocker); + } + + private static void AddAction(ref Configuration c) + { + CS2Event triggerEvent = GetTrigger(); + Console.WriteLine("Shocker IDs to trigger when Event occurs:"); + List shockerIds = GetShockerIds(c.Shockers); + ControlAction action = GetControlAction(); + bool useEventArgsValue = QueryBool("Try using EventArgs to control Intensity (within set limits)?", "false"); + + c.ShockerActions.Add(new ShockerAction(triggerEvent, shockerIds, action, useEventArgsValue)); + } + + private static bool QueryBool(string queryString, string defaultResult) + { + string value = QueryString(queryString, defaultResult); + bool ret; + while (bool.TryParse(value, out ret)) + value = QueryString(queryString, defaultResult); + return ret; + } + + private static string QueryString(string queryString, string defaultResult) + { + Console.WriteLine(queryString); + string? userInput = Console.ReadLine(); + return userInput?.Length > 0 ? userInput : defaultResult; + } + + private static IntensityRange GetIntensityRange() + { + Regex intensityRangeRex = new (@"([0-9]{1,3})\-(1?[0-9]{1,2})"); + string intensityRangeStr = ""; + while(!intensityRangeRex.IsMatch(intensityRangeStr)) + intensityRangeStr = QueryString("Intensity Range (0-100) in %:", "0-100"); + short min = short.Parse(intensityRangeRex.Match(intensityRangeStr).Groups[1].Value); + short max = short.Parse(intensityRangeRex.Match(intensityRangeStr).Groups[2].Value); + return new IntensityRange(min, max); + } + + private static DurationRange GetDurationRange() + { + Regex intensityRangeRex = new (@"([0-9]{1,4})\-([0-9]{1,5})"); + string intensityRangeStr = ""; + while(!intensityRangeRex.IsMatch(intensityRangeStr)) + intensityRangeStr = QueryString("Duration Range (500-30000) in ms:", "500-30000"); + short min = short.Parse(intensityRangeRex.Match(intensityRangeStr).Groups[1].Value); + short max = short.Parse(intensityRangeRex.Match(intensityRangeStr).Groups[2].Value); + return new DurationRange(min, max); + } + + private static List GetShockerIds(List shockers) + { + List allShockerIds = new(); + foreach(Shocker shocker in shockers) + allShockerIds.AddRange(shocker.ShockerIds); + + List ids = new(); + bool addAnother = true; + while (ids.Count < 1 || addAnother) + { + + for (int i = 0; i < allShockerIds.Count; i++) + Console.WriteLine($"{i}) {allShockerIds[i]}"); + + int selectedIndex; + while (!int.TryParse(Console.ReadLine(), out selectedIndex) || selectedIndex < 0 || selectedIndex >= allShockerIds.Count) + Console.WriteLine("Select ID:"); + + ids.Add(allShockerIds[selectedIndex]); + + Console.WriteLine("Add another ID? (Y/N):"); + addAnother = Console.ReadKey().Key == ConsoleKey.Y; + } + return ids; + } + + private static CS2Event GetTrigger() + { + string[] names = Enum.GetNames(typeof(CS2Event)); + Console.WriteLine("Select CS2 Trigger-Event:"); + for (int i = 0; i < names.Length; i++) + Console.WriteLine($"{i}) {names[i]}"); + + int selectedIndex; + while (!int.TryParse(Console.ReadLine(), out selectedIndex)) + Console.WriteLine("Select CS2 Trigger-Event:"); + + return Enum.Parse(names[selectedIndex]); + } + + private static ControlAction GetControlAction() + { + string[] names = Enum.GetNames(typeof(ControlAction)); + Console.WriteLine("Select Action:"); + for (int i = 0; i < names.Length; i++) + Console.WriteLine($"{i}) {names[i]}"); + + int selectedIndex; + while (!int.TryParse(Console.ReadLine(), out selectedIndex)) + Console.WriteLine("Select Action:"); + + return Enum.Parse(names[selectedIndex]); + } +} \ No newline at end of file diff --git a/OpenCS2hock/Shocker.cs b/OpenCS2hock/Shocker.cs deleted file mode 100644 index 3fd3a35..0000000 --- a/OpenCS2hock/Shocker.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace OpenCS2hock; - -internal abstract class Shocker -{ - protected readonly HttpClient HttpClient; - protected readonly string ApiKey,Endpoint; - private readonly string[] _shockerIds; - private readonly ConfiguredInteger _intensity, _duration; - protected readonly Logger? Logger; - - internal enum ControlAction { Beep, Vibrate, Shock, Nothing } - - internal void Control(ControlAction action, string? shockerId = null, int? intensity = null, int? duration = null) - { - int i = intensity ?? _intensity.GetValue(); - int d = duration ?? _duration.GetValue(); - this.Logger?.Log(LogLevel.Information, $"{action} {(intensity is not null ? "Overwrite " : "")}{i} {(duration is not null ? "Overwrite " : "")}{d}"); - if (action is ControlAction.Nothing) - return; - if(shockerId is null) - foreach (string shocker in _shockerIds) - ControlInternal(action, shocker, i, d); - else - ControlInternal(action, shockerId, i, d); - } - - protected abstract void ControlInternal(ControlAction action, string shockerId, int intensity, int duration); - - protected Shocker(string endpoint, string apiKey, string[] shockerIds, ConfiguredInteger intensity, ConfiguredInteger duration, Logger? logger = null) - { - this.Endpoint = endpoint; - this.ApiKey = apiKey; - this.HttpClient = new HttpClient(); - this._shockerIds = shockerIds; - this._intensity = intensity; - this._duration = duration; - this.Logger = logger; - } -} \ No newline at end of file diff --git a/OpenCS2hock/ShockerAction.cs b/OpenCS2hock/ShockerAction.cs new file mode 100644 index 0000000..d68eddb --- /dev/null +++ b/OpenCS2hock/ShockerAction.cs @@ -0,0 +1,29 @@ +using CShocker.Shockers; +using CS2Event = CS2GSI.CS2GSI.CS2Event; + +namespace OpenCS2hock; + +public struct ShockerAction +{ + public CS2Event TriggerEvent; + // ReSharper disable thrice FieldCanBeMadeReadOnly.Global JsonDeserializer will throw a fit + public List ShockerIds; + public ControlAction Action; + public bool ValueFromInput; + + public ShockerAction(CS2Event trigger, List shockerIds, ControlAction action, bool valueFromInput = false) + { + this.TriggerEvent = trigger; + this.ShockerIds = shockerIds; + this.Action = action; + this.ValueFromInput = valueFromInput; + } + + public override string ToString() + { + return $"Trigger Event: {Enum.GetName(typeof(CS2Event), this.TriggerEvent)}\n" + + $"ShockerIds: {string.Join(", ", ShockerIds)}\n" + + $"Action: {Enum.GetName(typeof(ControlAction), this.Action)}\n" + + $"ValueFromInput: {ValueFromInput}"; + } +} \ No newline at end of file diff --git a/README.md b/README.md index 00cdc6a..7f3b33b 100644 --- a/README.md +++ b/README.md @@ -12,35 +12,41 @@ Example `config.json`. Place next to executable. Will also be generated on first ```json { "LogLevel": 2, - "OpenShockSettings": { - "Endpoint": "https://api.shocklink.net", - "ApiKey": "", - "Shockers": [ " comma seperated" ] - }, - "IntensityRange": { - "Min": 30, - "Max": 60 - }, - "DurationRange": { - "Min": 1000, - "Max": 1000 - }, - "Actions": { - "OnKill": "Nothing", - "OnDeath": "Shock", - "OnRoundStart": "Nothing", - "OnRoundEnd": "Vibrate", - "OnRoundWin": "Nothing", - "OnRoundLoss": "Shock", - "OnDamageTaken": "Vibrate" - } + "Shockers": [ + { + "ShockerIds": [ + "ID HERE" + ], + "IntensityRange": { + "Min": 30, + "Max": 50 + }, + "DurationRange": { + "Min": 1000, + "Max": 1000 + }, + "ApiType": 0, + "Endpoint": "https://api.shocklink.net", + "ApiKey": "API KEY HERE" + } + ], + "ShockerActions": [ + { + "TriggerEvent": 2, + "ShockerIds": [ + "SAME ID HERE" + ], + "Action": 2, + "ValueFromInput": false + } + ] } ``` ### ApiKey For OpenShock get token [here](https://shocklink.net/#/dashboard/tokens) -### Shockers +### ShockerIds List of Shocker-Ids, comma seperated. Get Id [here](https://shocklink.net/#/dashboard/shockers/own). Press the three dots -> Edit Example `[ "ID-1", "ID-2" ]` @@ -56,5 +62,15 @@ in ms - Beep - Shock - Vibrate +- Nothing -# Using [CS2GSI](https://github.com/C9Glax/CS2GSI) \ No newline at end of file +# Using +### CS2GSI +[![GitHub License](https://img.shields.io/github/license/c9glax/CS2GSI)](/LICENSE) +[![NuGet Version](https://img.shields.io/nuget/v/CS2GSI)](https://www.nuget.org/packages/CS2GSI/) +[![Github](https://img.shields.io/badge/Github-8A2BE2)](https://github.com/C9Glax/CS2GSI) +[![GitHub Release](https://img.shields.io/github/v/release/c9glax/CS2GSI)](https://github.com/C9Glax/CS2GSI/releases/latest) +### CShocker +[![GitHub License](https://img.shields.io/github/license/c9glax/cshocker)](https://github.com/C9Glax/CShocker) +[![Github](https://img.shields.io/badge/Github-8A2BE2)](https://github.com/C9Glax/cshocker) +[![NuGet Version](https://img.shields.io/nuget/v/CShocker)](https://shields.io/badges/nu-get-version) \ No newline at end of file