Version 3:

CS2GSI and CShocker libraries
More extensive options for Events
Setup on first start
This commit is contained in:
glax 2024-01-18 00:06:39 +01:00
parent fa6a8d4e15
commit 41a433bf3f
14 changed files with 436 additions and 263 deletions

View File

@ -4,5 +4,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=appmanifest/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=freezetime/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=libraryfolders/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NYAA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=OpenCS2hock/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=steamapps/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=steamid/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,3 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/AddReferences/RecentPaths/=C_003A_005CUsers_005CGlax_005CRiderProjects_005CCShocker_005CCShocker_005Cbin_005CDebug_005Cnet7_002E0_005CCShocker_002Edll/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -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<Shocker> Shockers = new();
public List<ShockerAction> 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<Configuration>(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));
}
}

View File

@ -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);
}
}

View File

@ -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<Settings>(File.ReadAllText(settingsFilePath));
}
internal static List<Shocker> GetShockers(Settings settings, Logger? logger = null)
{
List<Shocker> 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;
}
}

View File

@ -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<Shocker> _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<string, string> 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<int>(), 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<int>(), 0, 100, configuredRangeForShocker.Min, configuredRangeForShocker.Max),
CS2Event.OnArmorChange => MapInt(eventArgs.ValueAsOrDefault<int>(), 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;

View File

@ -6,10 +6,12 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>OpenCS2Hock</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CS2GSI" Version="1.0.4" />
<PackageReference Include="CS2GSI" Version="1.0.6" />
<PackageReference Include="CShocker" Version="1.1.11" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

View File

@ -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)
{
}
}

View File

@ -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));
}
}

View File

@ -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<string>()
};
public Range IntensityRange = new ()
{
Min = 20,
Max = 60
};
public Range DurationRange = new()
{
Min = 1000,
Max = 1000
};
public Dictionary<string, string> 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;
}

242
OpenCS2hock/Setup.cs Normal file
View File

@ -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<LogLevel>();
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<LogLevel>(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<string> 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<string> 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<string> GetShockerIds(List<Shocker> shockers)
{
List<string> allShockerIds = new();
foreach(Shocker shocker in shockers)
allShockerIds.AddRange(shocker.ShockerIds);
List<string> 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<CS2Event>(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<ControlAction>(names[selectedIndex]);
}
}

View File

@ -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;
}
}

View File

@ -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<string> ShockerIds;
public ControlAction Action;
public bool ValueFromInput;
public ShockerAction(CS2Event trigger, List<string> 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}";
}
}

View File

@ -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": "<Your Shocklink API Key>",
"Shockers": [ "<Shocker Id> 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)
# 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)