StyleCop compliance, round 2 of 3 …

This commit is contained in:
alterNERDtive 2022-05-30 23:20:08 +02:00
parent 33a4fb8e3d
commit 64a096dae7
11 changed files with 1796 additions and 1485 deletions

View file

@ -1,72 +1,76 @@
#nullable enable // <copyright file="EliteAttack.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using System;
using alterNERDtive.util; using alterNERDtive.util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EliteAttack namespace EliteAttack
{ {
public class EliteAttack { /// <summary>
private static dynamic? VA { get; set; } /// VoiceAttack plugin for the EliteAttack profile.
/// </summary>
public class EliteAttack
{
private static readonly Version VERSION = new ("8.3");
private static VoiceAttackLog Log
=> log ??= new VoiceAttackLog(VA, "EliteAttack");
private static VoiceAttackLog? log; private static VoiceAttackLog? log;
private static VoiceAttackCommands Commands
=> commands ??= new VoiceAttackCommands(VA, Log);
private static VoiceAttackCommands? commands; private static VoiceAttackCommands? commands;
/*================\ private static dynamic? VA { get; set; }
| plugin contexts |
\================*/
private static void Context_Log(dynamic vaProxy) private static VoiceAttackLog Log => log ??= new (VA, "EliteAttack");
{
string message = vaProxy.GetText("~message");
string level = vaProxy.GetText("~level");
if (level == null) private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
{
Log.Log(message);
}
else
{
try
{
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
}
catch (ArgumentNullException) { throw; }
catch (ArgumentException)
{
Log.Error($"Invalid log level '{level}'.");
}
}
}
private static void Context_Startup(dynamic vaProxy)
{
Log.Notice("Starting up …");
VA = vaProxy;
Log.Notice("Finished startup.");
}
/*========================================\ /*========================================\
| required VoiceAttack plugin shenanigans | | required VoiceAttack plugin shenanigans |
\========================================*/ \========================================*/
static readonly Version VERSION = new Version("8.3"); /// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public static Guid VA_Id() public static Guid VA_Id()
=> new Guid("{5B46321D-2935-4550-BEEA-36C2145547B8}"); => new ("{5B46321D-2935-4550-BEEA-36C2145547B8}");
/// <summary>
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public static string VA_DisplayName() public static string VA_DisplayName()
=> $"EliteAttack {VERSION}"; => $"EliteAttack {VERSION}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public static string VA_DisplayInfo() public static string VA_DisplayInfo()
=> "EliteAttack: a plugin for doing Elite-y things."; => "EliteAttack: a plugin for doing Elite-y things.";
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Init1(dynamic vaProxy) public static void VA_Init1(dynamic vaProxy)
{ {
VA = vaProxy; VA = vaProxy;
@ -75,8 +79,15 @@ namespace EliteAttack
Log.Notice("Init successful."); Log.Notice("Init successful.");
} }
/// <summary>
/// The Invoke method, as required by the VoiceAttack plugin API.
/// Runs whenever a plugin context is invoked.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Invoke1(dynamic vaProxy) public static void VA_Invoke1(dynamic vaProxy)
{ {
VA = vaProxy;
string context = vaProxy.Context.ToLower(); string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …"); Log.Debug($"Running context '{context}' …");
try try
@ -84,14 +95,14 @@ namespace EliteAttack
switch (context) switch (context)
{ {
case "startup": case "startup":
Context_Startup(vaProxy); Context_Startup();
break; break;
// log
case "log.log": case "log.log":
Context_Log(vaProxy); // log
Context_Log();
break; break;
// invalid
default: default:
// invalid
Log.Error($"Invalid plugin context '{vaProxy.Context}'."); Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
break; break;
} }
@ -106,8 +117,59 @@ namespace EliteAttack
} }
} }
public static void VA_Exit1(dynamic vaProxy) { } /// <summary>
/// The Exit method, as required by the VoiceAttack plugin API.
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
public static void VA_Exit1(dynamic vaProxy)
{
}
public static void VA_StopCommand() { } /// <summary>
/// The StopCommand method, as required by the VoiceAttack plugin API.
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public static void VA_StopCommand()
{
}
/*================\
| plugin contexts |
\================*/
private static void Context_Log()
{
string message = VA!.GetText("~message");
string level = VA!.GetText("~level");
if (level == null)
{
Log.Log(message);
}
else
{
try
{
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
}
catch (ArgumentNullException)
{
throw;
}
catch (ArgumentException)
{
Log.Error($"Invalid log level '{level}'.");
}
}
}
private static void Context_Startup()
{
Log.Notice("Starting up …");
Log.Notice("Finished startup.");
}
} }
} }

View file

@ -1,43 +0,0 @@
#nullable enable
using System;
using System.IO;
using System.IO.Pipes;
using System.Text.RegularExpressions;
namespace RatAttack
{
class RatAttack_cli
{
static string stripIrcCodes(string message)
{
return Regex.Replace(message, @"[\x02\x11\x0F\x1D\x1E\x1F\x16]|\x03(\d\d?(,\d\d?)?)?", String.Empty);
}
static void Main(string[] args)
{
RatAttack.Ratsignal ratsignal = new RatAttack.Ratsignal(stripIrcCodes(args[0]), args.Length > 1 && args[1].ToLower() == "true");
using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "RatAttack", PipeDirection.Out))
{
try
{
// try connecting for up to 2minutes; then well assume VoiceAttack just isnt up and wont come up
pipeClient.Connect(120000);
using (StreamWriter writer = new StreamWriter(pipeClient))
{
writer.WriteLine(ratsignal);
}
}
catch (TimeoutException)
{
Console.Error.WriteLine("Connection to RatAttack pipe has timed out.");
}
catch (UnauthorizedAccessException)
{
Console.Error.WriteLine("Cannot connect to RatAttack pipe. Are you running VoiceAttack as Admin?");
}
}
}
}
}

View file

@ -48,8 +48,8 @@
<Reference Include="System.Xml.Serialization" /> <Reference Include="System.Xml.Serialization" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="RatAttack-cli.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RatAttack_cli.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\RatAttack\RatAttack.csproj"> <ProjectReference Include="..\RatAttack\RatAttack.csproj">

View file

@ -0,0 +1,68 @@
// <copyright file="RatAttack_cli.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using System;
using System.IO;
using System.IO.Pipes;
using System.Text.RegularExpressions;
namespace RatAttack
{
/// <summary>
/// CLI helper tool for the RatAttack VoiceAttack plugin. Accepts RATSIGNALs
/// e.g. from an IRC client and passes them to the plugin via named pipe.
/// </summary>
public class RatAttack_cli
{
/// <summary>
/// Main entry point.
/// </summary>
/// <param name="args">The command line arguments.</param>
public static void Main(string[] args)
{
RatAttack.Ratsignal ratsignal = new (StripIrcCodes(args[0]), args.Length > 1 && args[1].ToLower() == "true");
using (NamedPipeClientStream pipeClient = new (".", "RatAttack", PipeDirection.Out))
{
try
{
// try connecting for up to 2minutes; then well assume VoiceAttack just isnt up and wont come up
pipeClient.Connect(120000);
using StreamWriter writer = new (pipeClient);
writer.WriteLine(ratsignal);
}
catch (TimeoutException)
{
Console.Error.WriteLine("Connection to RatAttack pipe has timed out.");
}
catch (UnauthorizedAccessException)
{
Console.Error.WriteLine("Cannot connect to RatAttack pipe. Are you running VoiceAttack as Admin?");
}
}
}
private static string StripIrcCodes(string message)
{
return Regex.Replace(message, @"[\x02\x11\x0F\x1D\x1E\x1F\x16]|\x03(\d\d?(,\d\d?)?)?", string.Empty);
}
}
}

View file

@ -1,93 +1,184 @@
#nullable enable // <copyright file="RatAttack.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using alterNERDtive.util; using alterNERDtive.util;
namespace RatAttack namespace RatAttack
{ {
/// <summary>
/// VoiceAttack plugin for the RatAttack profile.
/// </summary>
public class RatAttack public class RatAttack
{ {
private static Dictionary<int,RatCase> CaseList { get; } = new Dictionary<int, RatCase>(); private static readonly Version VERSION = new ("6.3.1");
private static dynamic? VA { get; set; }
private static alterNERDtive.util.PipeServer<Ratsignal> RatsignalPipe
=> ratsignalPipe ??= new alterNERDtive.util.PipeServer<Ratsignal>(Log, "RatAttack",
new alterNERDtive.util.PipeServer<Ratsignal>.SignalHandler(On_Ratsignal));
private static alterNERDtive.util.PipeServer<Ratsignal>? ratsignalPipe;
private static readonly Regex RatsignalRegex = new Regex( private static readonly Regex RatsignalRegex = new (
@"^RATSIGNAL Case #(?<number>\d+) (?<platform>(PC|Xbox|Playstation))(?<oxygen> \(Code Red\))?(?<odyssey> \(Odyssey\))? CMDR (?<cmdr>.+) System: (None|u\u200bnknown system|""(?<system>.+)"" \((?<systemInfo>([a-zA-Z0-9\s\(\)\-/]*(~?[0-9,\.]+ LY (""[a-zA-Z\-]+"" of|from) [a-zA-Z0-9\s\*\-]+)?( \([a-zA-Z\s]+\))?|Not found in galaxy database|Invalid system name))\)(?<permit> \(((?<permitName>.*) )?Permit Required\))?) Language: (?<language>[a-zA-z0-9\x7f-\xff\-\(\)&,\s\.]+)( Nick: (?<nick>[a-zA-Z0-9_\[\]\-]+))? \((PC|XB|PS)_SIGNAL\)\v*$" @"^RATSIGNAL Case #(?<number>\d+) (?<platform>(PC|Xbox|Playstation))(?<oxygen> \(Code Red\))?(?<odyssey> \(Odyssey\))? CMDR (?<cmdr>.+) System: (None|u\u200bnknown system|""(?<system>.+)"" \((?<systemInfo>([a-zA-Z0-9\s\(\)\-/]*(~?[0-9,\.]+ LY (""[a-zA-Z\-]+"" of|from) [a-zA-Z0-9\s\*\-]+)?( \([a-zA-Z\s]+\))?|Not found in galaxy database|Invalid system name))\)(?<permit> \(((?<permitName>.*) )?Permit Required\))?) Language: (?<language>[a-zA-z0-9\x7f-\xff\-\(\)&,\s\.]+)( Nick: (?<nick>[a-zA-Z0-9_\[\]\-]+))? \((PC|XB|PS)_SIGNAL\)\v*$");
);
private static VoiceAttackLog Log private static PipeServer<Ratsignal>? ratsignalPipe;
=> log ??= new VoiceAttackLog(VA, "RatAttack");
private static VoiceAttackLog? log; private static VoiceAttackLog? log;
private static VoiceAttackCommands Commands
=> commands ??= new VoiceAttackCommands(VA, Log);
private static VoiceAttackCommands? commands; private static VoiceAttackCommands? commands;
private class RatCase private static Dictionary<int, RatCase> CaseList { get; } = new ();
{
public string Cmdr;
public string? Language;
public string? System;
public string? SystemInfo;
public bool PermitLocked;
public string? PermitName;
public string Platform;
public bool Odyssey;
public bool CodeRed;
public int Number;
public RatCase(string cmdr, string? language, string? system, string? systemInfo, bool permitLocked, string? permitName, string platform, bool odyssey, bool codeRed, int number) private static dynamic? VA { get; set; }
=> (Cmdr, Language, System, SystemInfo, PermitLocked, PermitName, Platform, Odyssey, CodeRed, Number) = (cmdr, language, system, systemInfo, permitLocked, permitName, platform, odyssey, codeRed, number);
public string ShortInfo private static PipeServer<Ratsignal> RatsignalPipe
=> ratsignalPipe ??= new (
Log,
"RatAttack",
new PipeServer<Ratsignal>.SignalHandler(On_Ratsignal));
private static VoiceAttackLog Log => log ??= new (VA, "RatAttack");
private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
/*========================================\
| required VoiceAttack plugin shenanigans |
\========================================*/
/// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public static Guid VA_Id()
=> new ("{F2ADF0AE-4837-4E4A-9C87-8A7E2FA63E5F}");
/// <summary>
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public static string VA_DisplayName()
=> $"RatAttack {VERSION}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public static string VA_DisplayInfo()
=> "RatAttack: a plugin to handle FuelRats cases.";
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Init1(dynamic vaProxy)
{ {
get => $"#{Number}, {Platform}{(Odyssey ? " (Odyssey)" : "")}{(CodeRed ? ", code red" : "")}, {System ?? "None"}{(SystemInfo != null ? $" ({SystemInfo}{(PermitLocked ? ", permit required" : "")})" : "")}"; VA = vaProxy;
Log.Notice("Initializing …");
VA.SetText("RatAttack.version", VERSION.ToString());
vaProxy.ProfileChanged += new Action<Guid?, Guid?, string, string>(On_ProfileChanged);
Log.Notice("Init successful.");
} }
public override string ToString() /// <summary>
=> ShortInfo; /// The Invoke method, as required by the VoiceAttack plugin API.
} /// Runs whenever a plugin context is invoked.
/// </summary>
public class Ratsignal : IPipable /// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Invoke1(dynamic vaProxy)
{ {
public string Signal { get; set; } VA = vaProxy;
public bool Announce { get; set; }
private readonly char separator = '\x1F';
public Ratsignal() string context = vaProxy.Context.ToLower();
=> (Signal, Announce) = ("", false); Log.Debug($"Running context '{context}' …");
public Ratsignal(string signal, bool announce)
=> (Signal, Announce) = (signal, announce);
public void ParseString(string serialization)
{
try try
{ {
string[] parts = serialization.Split(separator); switch (context)
Signal = parts[0]; {
Announce = Boolean.Parse(parts[1]); case "getcasedata":
// plugin methods
Context_GetCaseData();
break;
case "parseratsignal":
Context_ParseRatsignal();
break;
case "startup":
Context_Startup();
break;
case "edsm.getnearestcmdr":
// EDSM
Context_EDSM_GetNearestCMDR();
break;
case "log.log":
// log
Context_Log();
break;
default:
// invalid
Log.Error($"Invalid plugin context '{VA!.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
} }
catch (Exception e) catch (Exception e)
{ {
throw new ArgumentException($"Invalid serialized RATSIGNAL: '{serialization}'", e); Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
} }
} }
public override string ToString() /// <summary>
=> $"{Signal}{separator}{Announce}"; /// The Exit method, as required by the VoiceAttack plugin API.
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
public static void VA_Exit1(dynamic vaProxy)
{
Log.Debug("Starting teardown …");
Log.Debug("Closing RATSIGNAL pipe …");
RatsignalPipe.Stop();
Log.Debug("Teardown finished.");
} }
/// <summary>
/// The StopCommand method, as required by the VoiceAttack plugin API.
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public static void VA_StopCommand()
{
}
/// <summary>
/// Parses a RATSIGNAL and extracts case data for storage.
/// </summary>
/// <param name="ratsignal">The incoming RATSIGNAL.</param>
/// <returns>The case number.</returns>
/// <exception cref="ArgumentException">Thrown on invalid RATSIGNAL.</exception>
private static int ParseRatsignal(string ratsignal) private static int ParseRatsignal(string ratsignal)
{ {
if (!RatsignalRegex.IsMatch(ratsignal)) if (!RatsignalRegex.IsMatch(ratsignal))
{
throw new ArgumentException($"Invalid RATSIGNAL format: '{ratsignal}'.", "ratsignal"); throw new ArgumentException($"Invalid RATSIGNAL format: '{ratsignal}'.", "ratsignal");
}
Match match = RatsignalRegex.Match(ratsignal); Match match = RatsignalRegex.Match(ratsignal);
@ -103,12 +194,12 @@ namespace RatAttack
int number = int.Parse(match.Groups["number"].Value); int number = int.Parse(match.Groups["number"].Value);
if (String.IsNullOrEmpty(system)) if (string.IsNullOrEmpty(system))
{ {
system = "None"; system = "None";
} }
Log.Debug($"New rat case: CMDR “{cmdr}” in “{system}”{(systemInfo != null ? $" ({systemInfo})" : "")} on {platform}{(odyssey ? " (Odyssey)" : "")}, permit locked: {permitLocked}{(permitLocked && permitName != null ? $" (permit name: {permitName})" : "")}, code red: {codeRed} (#{number})."); Log.Debug($"New rat case: CMDR “{cmdr}” in “{system}”{(systemInfo != null ? $" ({systemInfo})" : string.Empty)} on {platform}{(odyssey ? " (Odyssey)" : string.Empty)}, permit locked: {permitLocked}{(permitLocked && permitName != null ? $" (permit name: {permitName})" : string.Empty)}, code red: {codeRed} (#{number}).");
CaseList[number] = new RatCase(cmdr, language, system, systemInfo, permitLocked, permitName, platform, odyssey, codeRed, number); CaseList[number] = new RatCase(cmdr, language, system, systemInfo, permitLocked, permitName, platform, odyssey, codeRed, number);
@ -141,18 +232,19 @@ namespace RatAttack
| plugin contexts | | plugin contexts |
\================*/ \================*/
private static void Context_EDSM_GetNearestCMDR(dynamic vaProxy) private static void Context_EDSM_GetNearestCMDR()
{ {
int caseNo = vaProxy.GetInt("~caseNo") ?? throw new ArgumentNullException("~caseNo"); int caseNo = VA!.GetInt("~caseNo") ?? throw new ArgumentNullException("~caseNo");
string cmdrList = vaProxy.GetText("~cmdrs") ?? throw new ArgumentNullException("~cmdrs"); string cmdrList = VA!.GetText("~cmdrs") ?? throw new ArgumentNullException("~cmdrs");
string[] cmdrs = cmdrList.Split(';'); string[] cmdrs = cmdrList.Split(';');
if (cmdrs.Length == 0) if (cmdrs.Length == 0)
{ {
throw new ArgumentNullException("~cmdrs"); throw new ArgumentNullException("~cmdrs");
} }
string system = CaseList[caseNo]?.System ?? throw new ArgumentException($"Case #{caseNo} has no system information", "~caseNo"); string system = CaseList[caseNo]?.System ?? throw new ArgumentException($"Case #{caseNo} has no system information", "~caseNo");
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\edsm-getnearest.exe"; string path = $@"{VA!.SessionState["VA_SOUNDS"]}\Scripts\edsm-getnearest.exe";
string arguments = $@"--short --text --system ""{system}"" ""{string.Join(@""" """, cmdrs)}"""; string arguments = $@"--short --text --system ""{system}"" ""{string.Join(@""" """, cmdrs)}""";
Process p = PythonProxy.SetupPythonScript(path, arguments); Process p = PythonProxy.SetupPythonScript(path, arguments);
@ -164,7 +256,7 @@ namespace RatAttack
string message = stdout; string message = stdout;
string? errorMessage = null; string? errorMessage = null;
bool error = true; bool error;
switch (p.ExitCode) switch (p.ExitCode)
{ {
@ -185,32 +277,31 @@ namespace RatAttack
Log.Error(stderr); Log.Error(stderr);
errorMessage = "Unrecoverable error in plugin."; errorMessage = "Unrecoverable error in plugin.";
break; break;
} }
vaProxy.SetText("~message", message); VA!.SetText("~message", message);
vaProxy.SetBoolean("~error", error); VA!.SetBoolean("~error", error);
vaProxy.SetText("~errorMessage", errorMessage); VA!.SetText("~errorMessage", errorMessage);
vaProxy.SetInt("~exitCode", p.ExitCode); VA!.SetInt("~exitCode", p.ExitCode);
} }
private static void Context_GetCaseData(dynamic vaProxy) private static void Context_GetCaseData()
{ {
int cn = vaProxy.GetInt("~caseNumber"); int cn = VA!.GetInt("~caseNumber");
if (CaseList.ContainsKey(cn)) if (CaseList.ContainsKey(cn))
{ {
RatCase rc = CaseList[cn]; RatCase rc = CaseList[cn];
vaProxy.SetInt("~~caseNumber", rc.Number); VA!.SetInt("~~caseNumber", rc.Number);
vaProxy.SetText("~~cmdr", rc.Cmdr); VA!.SetText("~~cmdr", rc.Cmdr);
vaProxy.SetText("~~system", rc?.System?.ToLower()); VA!.SetText("~~system", rc?.System?.ToLower());
vaProxy.SetText("~~systemInfo", rc?.SystemInfo); VA!.SetText("~~systemInfo", rc?.SystemInfo);
vaProxy.SetBoolean("~~permitLocked", rc?.PermitLocked); VA!.SetBoolean("~~permitLocked", rc?.PermitLocked);
vaProxy.SetText("~~permitName", rc?.PermitName); VA!.SetText("~~permitName", rc?.PermitName);
vaProxy.SetText("~~platform", rc?.Platform); VA!.SetText("~~platform", rc?.Platform);
vaProxy.SetBoolean("~~odyssey", rc?.Odyssey); VA!.SetBoolean("~~odyssey", rc?.Odyssey);
vaProxy.SetBoolean("~~codeRed", rc?.CodeRed); VA!.SetBoolean("~~codeRed", rc?.CodeRed);
} }
else else
{ {
@ -218,10 +309,10 @@ namespace RatAttack
} }
} }
private static void Context_Log(dynamic vaProxy) private static void Context_Log()
{ {
string message = vaProxy.GetText("~message"); string message = VA!.GetText("~message");
string level = vaProxy.GetText("~level"); string level = VA!.GetText("~level");
if (level == null) if (level == null)
{ {
@ -233,7 +324,10 @@ namespace RatAttack
{ {
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper())); Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
} }
catch (ArgumentNullException) { throw; } catch (ArgumentNullException)
{
throw;
}
catch (ArgumentException) catch (ArgumentException)
{ {
Log.Error($"Invalid log level '{level}'."); Log.Error($"Invalid log level '{level}'.");
@ -241,92 +335,111 @@ namespace RatAttack
} }
} }
private static void Context_Startup(dynamic vaProxy) private static void Context_Startup()
{ {
Log.Notice("Starting up …"); Log.Notice("Starting up …");
VA = vaProxy;
_ = RatsignalPipe.Run(); _ = RatsignalPipe.Run();
Log.Notice("Finished startup."); Log.Notice("Finished startup.");
} }
private static void Context_ParseRatsignal(dynamic vaProxy) private static void Context_ParseRatsignal()
{ {
Log.Warn("Passing a RATSIGNAL from VoiceAttack (through the clipboard or a file) is DEPRECATED and will no longer be supported in the future."); Log.Warn("Passing a RATSIGNAL to VoiceAttack through the clipboard or a file is DEPRECATED and will no longer be supported in the future.");
On_Ratsignal(new Ratsignal(vaProxy.GetText("~ratsignal"), vaProxy.GetBoolean("~announceRatsignal"))); On_Ratsignal(new Ratsignal(VA!.GetText("~ratsignal"), VA!.GetBoolean("~announceRatsignal")));
} }
/*========================================\ /// <summary>
| required VoiceAttack plugin shenanigans | /// Encapsulates a RATSIGNAL for sending between the CLI helper tool and
\========================================*/ /// the plugin via named pipe.
/// </summary>
static readonly Version VERSION = new Version("6.3.1"); public class Ratsignal : IPipable
public static Guid VA_Id()
=> new Guid("{F2ADF0AE-4837-4E4A-9C87-8A7E2FA63E5F}");
public static string VA_DisplayName()
=> $"RatAttack {VERSION}";
public static string VA_DisplayInfo()
=> "RatAttack: a plugin to handle FuelRats cases.";
public static void VA_Init1(dynamic vaProxy)
{ {
VA = vaProxy; private readonly char separator = '\x1F';
Log.Notice("Initializing …");
VA.SetText("RatAttack.version", VERSION.ToString());
vaProxy.ProfileChanged += new Action<Guid?, Guid?, String, String>(On_ProfileChanged);
Log.Notice("Init successful.");
}
public static void VA_Invoke1(dynamic vaProxy) /// <summary>
/// Initializes a new instance of the <see cref="Ratsignal"/> class.
/// </summary>
public Ratsignal()
=> (this.Signal, this.Announce) = (string.Empty, false);
/// <summary>
/// Initializes a new instance of the <see cref="Ratsignal"/> class.
/// </summary>
/// <param name="signal">The RATSIGNAL.</param>
/// <param name="announce">Whether or not to announce the new case.</param>
public Ratsignal(string signal, bool announce)
=> (this.Signal, this.Announce) = (signal, announce);
/// <summary>
/// Gets or sets the RATSIGNAL.
/// </summary>
public string Signal { get; set; }
/// <summary>
/// Gets or Sets a value indicating whether to announce the incoming
/// case.
/// </summary>
public bool Announce { get; set; }
/// <summary>
/// Initializes the <see cref="Ratsignal"/> instance from a
/// serialized representation.
/// FIXXME: should probably make this a static factory method.
/// </summary>
/// <param name="serialization">The serialized <see cref="Ratsignal"/>.</param>
/// <exception cref="ArgumentException">Thrown on receiving an invalid signal.</exception>
public void ParseString(string serialization)
{ {
string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …");
try try
{ {
switch (context) string[] parts = serialization.Split(this.separator);
{ this.Signal = parts[0];
// plugin methods this.Announce = bool.Parse(parts[1]);
case "getcasedata":
Context_GetCaseData(vaProxy);
break;
case "parseratsignal":
Context_ParseRatsignal(vaProxy);
break;
case "startup":
Context_Startup(vaProxy);
break;
// EDSM
case "edsm.getnearestcmdr":
Context_EDSM_GetNearestCMDR(vaProxy);
break;
// log
case "log.log":
Context_Log(vaProxy);
break;
// invalid
default:
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
} }
catch (Exception e) catch (Exception e)
{ {
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})"); throw new ArgumentException($"Invalid serialized RATSIGNAL: '{serialization}'", e);
} }
} }
public static void VA_Exit1(dynamic vaProxy) /// <inheritdoc/>
public override string ToString()
=> $"{this.Signal}{this.separator}{this.Announce}";
}
private class RatCase
{ {
Log.Debug("Starting teardown …"); public RatCase(string cmdr, string? language, string? system, string? systemInfo, bool permitLocked, string? permitName, string platform, bool odyssey, bool codeRed, int number)
Log.Debug("Closing RATSIGNAL pipe …"); => (this.Cmdr, this.Language, this.System, this.SystemInfo, this.PermitLocked, this.PermitName, this.Platform, this.Odyssey, this.CodeRed, this.Number)
RatsignalPipe.Stop(); = (cmdr, language, system, systemInfo, permitLocked, permitName, platform, odyssey, codeRed, number);
Log.Debug("Teardown finished.");
public string Cmdr { get; }
public string? Language { get; }
public string? System { get; }
public string? SystemInfo { get; }
public bool PermitLocked { get; }
public string? PermitName { get; }
public string Platform { get; }
public bool Odyssey { get; }
public bool CodeRed { get; }
public int Number { get; }
public string ShortInfo
{
get => $"#{this.Number}, {this.Platform}{(this.Odyssey ? " (Odyssey)" : string.Empty)}{(this.CodeRed ? ", code red" : string.Empty)}, {this.System ?? "None"}{(this.SystemInfo != null ? $" ({this.SystemInfo}{(this.PermitLocked ? ", permit required" : string.Empty)})" : string.Empty)}";
} }
public static void VA_StopCommand() { } public override string ToString()
=> this.ShortInfo;
}
} }
} }

View file

@ -1,32 +1,162 @@
#nullable enable // <copyright file="SpanshAttack.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using alterNERDtive.util;
using alterNERDtive.edts;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using alterNERDtive.edts;
using alterNERDtive.util;
namespace SpanshAttack namespace SpanshAttack
{ {
/// <summary>
/// VoiceAttack plugin for the SpanshAttack profile.
/// </summary>
public class SpanshAttack public class SpanshAttack
{ {
private static readonly Version VERSION = new ("7.2.2");
private static VoiceAttackLog? log;
private static VoiceAttackCommands? commands;
private static dynamic? VA { get; set; } private static dynamic? VA { get; set; }
private static VoiceAttackLog Log private static VoiceAttackLog Log => log ??= new (VA, "SpanshAttack");
=> log ??= new VoiceAttackLog(VA, "SpanshAttack");
private static VoiceAttackLog? log;
private static VoiceAttackCommands Commands private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
=> commands ??= new VoiceAttackCommands(VA, Log);
private static VoiceAttackCommands? commands; /*========================================\
| required VoiceAttack plugin shenanigans |
\========================================*/
/// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public static Guid VA_Id()
=> new ("{e722b29d-898e-47dd-a843-a409c87e0bd8}");
/// <summary>
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public static string VA_DisplayName()
=> $"SpanshAttack {VERSION}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public static string VA_DisplayInfo()
=> "SpanshAttack: a plugin for doing routing with spansh.co.uk for Elite: Dangerous.";
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Init1(dynamic vaProxy)
{
VA = vaProxy;
Log.Notice("Initializing …");
VA.SetText("SpanshAttack.version", VERSION.ToString());
Log.Notice("Init successful.");
}
/// <summary>
/// The Invoke method, as required by the VoiceAttack plugin API.
/// Runs whenever a plugin context is invoked.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Invoke1(dynamic vaProxy)
{
VA = vaProxy;
string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …");
try
{
switch (context)
{
case "startup":
Context_Startup();
break;
case "edts.getcoordinates":
// EDTS
Context_EDTS_GetCoordinates();
break;
case "log.log":
// log
Context_Log();
break;
case "spansh.systemexists":
// Spansh
Context_Spansh_SytemExists();
break;
case "spansh.nearestsystem":
Context_Spansh_Nearestsystem();
break;
default:
// invalid
Log.Error($"Invalid plugin context '{VA!.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
}
}
/// <summary>
/// The Exit method, as required by the VoiceAttack plugin API.
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
public static void VA_Exit1(dynamic vaProxy)
{
}
/// <summary>
/// The StopCommand method, as required by the VoiceAttack plugin API.
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public static void VA_StopCommand()
{
}
/*================\ /*================\
| plugin contexts | | plugin contexts |
\================*/ \================*/
private static void Context_EDTS_GetCoordinates(dynamic vaProxy) private static void Context_EDTS_GetCoordinates()
{ {
string name = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system"); string name = VA!.GetText("~system") ?? throw new ArgumentNullException("~system");
bool success = false; bool success = false;
string? errorType = null; string? errorType = null;
@ -45,35 +175,37 @@ namespace SpanshAttack
Log.Warn($@"Coordinates with low precision for ""{name}"": ({system.Coords.X}, {system.Coords.Y}, {system.Coords.Z}), precision: {system.Coords.Precision}ly"); Log.Warn($@"Coordinates with low precision for ""{name}"": ({system.Coords.X}, {system.Coords.Y}, {system.Coords.Z}), precision: {system.Coords.Precision}ly");
} }
vaProxy.SetInt("~x", system.Coords.X); VA!.SetInt("~x", system.Coords.X);
vaProxy.SetInt("~y", system.Coords.Y); VA!.SetInt("~y", system.Coords.Y);
vaProxy.SetInt("~z", system.Coords.Z); VA!.SetInt("~z", system.Coords.Z);
vaProxy.SetInt("~precision", system.Coords.Precision); VA!.SetInt("~precision", system.Coords.Precision);
success = true; success = true;
} catch (ArgumentException e) }
catch (ArgumentException e)
{ {
errorType = "invalid name"; errorType = "invalid name";
errorMessage = e.Message; errorMessage = e.Message;
} catch (Exception e) }
catch (Exception e)
{ {
errorType = "connection error"; errorType = "connection error";
errorMessage = e.Message; errorMessage = e.Message;
} }
vaProxy.SetBoolean("~success", success); VA!.SetBoolean("~success", success);
if (!string.IsNullOrWhiteSpace(errorType)) if (!string.IsNullOrWhiteSpace(errorType))
{ {
Log.Error(errorMessage!); Log.Error(errorMessage!);
vaProxy.SetText("~errorType", errorType); VA!.SetText("~errorType", errorType);
vaProxy.SetText("~errorMessage", errorMessage); VA!.SetText("~errorMessage", errorMessage);
} }
} }
private static void Context_Log(dynamic vaProxy) private static void Context_Log()
{ {
string message = vaProxy.GetText("~message"); string message = VA!.GetText("~message");
string level = vaProxy.GetText("~level"); string level = VA!.GetText("~level");
if (level == null) if (level == null)
{ {
@ -85,7 +217,10 @@ namespace SpanshAttack
{ {
Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper())); Log.Log(message, (LogLevel)Enum.Parse(typeof(LogLevel), level.ToUpper()));
} }
catch (ArgumentNullException) { throw; } catch (ArgumentNullException)
{
throw;
}
catch (ArgumentException) catch (ArgumentException)
{ {
Log.Error($"Invalid log level '{level}'."); Log.Error($"Invalid log level '{level}'.");
@ -93,22 +228,22 @@ namespace SpanshAttack
} }
} }
private static void Context_Spansh_Nearestsystem(dynamic vaProxy) private static void Context_Spansh_Nearestsystem()
{ {
int x = vaProxy.GetInt("~x") ?? throw new ArgumentNullException("~x"); int x = VA!.GetInt("~x") ?? throw new ArgumentNullException("~x");
int y = vaProxy.GetInt("~y") ?? throw new ArgumentNullException("~y"); int y = VA!.GetInt("~y") ?? throw new ArgumentNullException("~y");
int z = vaProxy.GetInt("~z") ?? throw new ArgumentNullException("~z"); int z = VA!.GetInt("~z") ?? throw new ArgumentNullException("~z");
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe"; string path = $@"{VA!.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe";
string arguments = $@"nearestsystem --parsable {x} {y} {z}"; string arguments = $@"nearestsystem --parsable {x} {y} {z}";
Process p = PythonProxy.SetupPythonScript(path, arguments); Process p = PythonProxy.SetupPythonScript(path, arguments);
Dictionary<char, decimal> coords = new Dictionary<char, decimal> { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } }; Dictionary<char, decimal> coords = new () { { 'x', 0 }, { 'y', 0 }, { 'z', 0 } };
string system = ""; string system = string.Empty;
decimal distance = 0; decimal distance = 0;
bool error = false; bool error = false;
string errorMessage = ""; string errorMessage = string.Empty;
p.Start(); p.Start();
string stdout = p.StandardOutput.ReadToEnd(); string stdout = p.StandardOutput.ReadToEnd();
@ -138,28 +273,28 @@ namespace SpanshAttack
break; break;
} }
vaProxy.SetText("~system", system); VA!.SetText("~system", system);
vaProxy.SetDecimal("~x", coords['x']); VA!.SetDecimal("~x", coords['x']);
vaProxy.SetDecimal("~y", coords['y']); VA!.SetDecimal("~y", coords['y']);
vaProxy.SetDecimal("~z", coords['z']); VA!.SetDecimal("~z", coords['z']);
vaProxy.SetDecimal("~distance", distance); VA!.SetDecimal("~distance", distance);
vaProxy.SetBoolean("~error", error); VA!.SetBoolean("~error", error);
vaProxy.SetText("~errorMessage", errorMessage); VA!.SetText("~errorMessage", errorMessage);
vaProxy.SetInt("~exitCode", p.ExitCode); VA!.SetInt("~exitCode", p.ExitCode);
} }
private static void Context_Spansh_SytemExists(dynamic vaProxy) private static void Context_Spansh_SytemExists()
{ {
string system = vaProxy.GetText("~system") ?? throw new ArgumentNullException("~system"); string system = VA!.GetText("~system") ?? throw new ArgumentNullException("~system");
string path = $@"{vaProxy.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe"; string path = $@"{VA!.SessionState["VA_SOUNDS"]}\Scripts\spansh.exe";
string arguments = $@"systemexists ""{system}"""; string arguments = $@"systemexists ""{system}""";
Process p = PythonProxy.SetupPythonScript(path, arguments); Process p = PythonProxy.SetupPythonScript(path, arguments);
bool exists = true; bool exists = true;
bool error = false; bool error = false;
string errorMessage = ""; string errorMessage = string.Empty;
p.Start(); p.Start();
string stdout = p.StandardOutput.ReadToEnd(); string stdout = p.StandardOutput.ReadToEnd();
@ -186,84 +321,16 @@ namespace SpanshAttack
break; break;
} }
vaProxy.SetBoolean("~systemExists", exists); VA!.SetBoolean("~systemExists", exists);
vaProxy.SetBoolean("~error", error); VA!.SetBoolean("~error", error);
vaProxy.SetText("~errorMessage", errorMessage); VA!.SetText("~errorMessage", errorMessage);
vaProxy.SetInt("~exitCode", p.ExitCode); VA!.SetInt("~exitCode", p.ExitCode);
} }
private static void Context_Startup(dynamic vaProxy) private static void Context_Startup()
{ {
Log.Notice("Starting up …"); Log.Notice("Starting up …");
VA = vaProxy;
Log.Notice("Finished startup."); Log.Notice("Finished startup.");
} }
/*========================================\
| required VoiceAttack plugin shenanigans |
\========================================*/
static readonly Version VERSION = new Version("7.2.2");
public static Guid VA_Id()
=> new Guid("{e722b29d-898e-47dd-a843-a409c87e0bd8}");
public static string VA_DisplayName()
=> $"SpanshAttack {VERSION}";
public static string VA_DisplayInfo()
=> "SpanshAttack: a plugin for doing routing with spansh.co.uk for Elite: Dangerous.";
public static void VA_Init1(dynamic vaProxy)
{
VA = vaProxy;
Log.Notice("Initializing …");
VA.SetText("SpanshAttack.version", VERSION.ToString());
Log.Notice("Init successful.");
}
public static void VA_Invoke1(dynamic vaProxy)
{
string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …");
try
{
switch (context)
{
case "startup":
Context_Startup(vaProxy);
break;
// EDTS
case "edts.getcoordinates":
Context_EDTS_GetCoordinates(vaProxy);
break;
// log
case "log.log":
Context_Log(vaProxy);
break;
// Spansh
case "spansh.systemexists":
Context_Spansh_SytemExists(vaProxy);
break;
case "spansh.nearestsystem":
Context_Spansh_Nearestsystem(vaProxy);
break;
// invalid
default:
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
}
}
public static void VA_Exit1(dynamic vaProxy) { }
public static void VA_StopCommand() { }
} }
} }

View file

@ -5,4 +5,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "<Pending>", Scope = "namespace", Target = "~N:alterNERDtive")] [assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive")]
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive.edts")]
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "just cause", Scope = "namespace", Target = "~N:alterNERDtive.util")]

View file

@ -56,7 +56,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="base.cs" /> <Compile Include="base.cs" />
<Compile Include="edts.cs" /> <Compile Include="edts.cs">
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="GlobalSuppressions.cs" /> <Compile Include="GlobalSuppressions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SettingsDialog.xaml.cs"> <Compile Include="SettingsDialog.xaml.cs">

View file

@ -39,7 +39,9 @@ namespace alterNERDtive
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "F off :)")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "F off :)")]
public class BasePlugin public class BasePlugin
{ {
private static readonly Dictionary<Guid, string> Profiles = new Dictionary<Guid, string> private static readonly Version VERSION = new ("4.3.1");
private static readonly Dictionary<Guid, string> Profiles = new ()
{ {
{ new Guid("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}"), "alterNERDtive-base" }, { new Guid("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}"), "alterNERDtive-base" },
{ new Guid("{f31b575b-6ce4-44eb-91fc-7459e55013cf}"), "EliteAttack" }, { new Guid("{f31b575b-6ce4-44eb-91fc-7459e55013cf}"), "EliteAttack" },
@ -57,14 +59,154 @@ namespace alterNERDtive
private static Configuration? config; private static Configuration? config;
private static VoiceAttackLog? log; private static VoiceAttackLog? log;
private static VoiceAttackCommands Commands => commands ??= new VoiceAttackCommands(VA, Log); private static VoiceAttackCommands Commands => commands ??= new (VA, Log);
private static Configuration Config => config ??= new Configuration(VA, Log, Commands, "alterNERDtive-base"); private static Configuration Config => config ??= new (VA, Log, Commands, "alterNERDtive-base");
private static VoiceAttackLog Log => log ??= new VoiceAttackLog(VA, "alterNERDtive-base"); private static VoiceAttackLog Log => log ??= new (VA, "alterNERDtive-base");
private static dynamic? VA { get; set; } private static dynamic? VA { get; set; }
/*========================================\
| required VoiceAttack plugin shenanigans |
\========================================*/
/// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public static Guid VA_Id()
=> new ("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}");
/// <summary>
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public static string VA_DisplayName()
=> $"alterNERDtive-base {VERSION}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public static string VA_DisplayInfo()
=> "The alterNERDtive plugin to manage all the alterNERDtive profiles!";
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Init1(dynamic vaProxy)
{
VA = vaProxy;
Log.Notice("Initializing …");
VA.SetText("alterNERDtive-base.version", VERSION.ToString());
vaProxy.BooleanVariableChanged += new Action<string, bool?, bool?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.DateVariableChanged += new Action<string, DateTime?, DateTime?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.DecimalVariableChanged += new Action<string, decimal?, decimal?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.IntegerVariableChanged += new Action<string, int?, int?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.TextVariableChanged += new Action<string, string, string, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
VA.SetBoolean("alterNERDtive-base.initialized", true);
Commands.TriggerEvent("alterNERDtive-base.initialized", wait: false, logMissing: false);
Log.Notice("Init successful.");
}
/// <summary>
/// The Invoke method, as required by the VoiceAttack plugin API.
/// Runs whenever a plugin context is invoked.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Invoke1(dynamic vaProxy)
{
VA = vaProxy;
string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …");
try
{
switch (context)
{
case "startup":
Context_Startup();
break;
case "config.dialog":
// config
Context_Config_Dialog();
break;
case "config.dump":
Context_Config_Dump();
break;
case "config.getvariables":
Context_Config_SetVariables();
break;
case "config.list":
Context_Config_List();
break;
case "config.setup":
Context_Config_Setup();
break;
case "config.versionmigration":
Context_Config_VersionMigration();
break;
case "edsm.bodycount":
// EDSM
Context_EDSM_BodyCount();
break;
case "edsm.distancebetween":
Context_EDSM_DistanceBetween();
break;
case "eddi.event":
// EDDI
Context_Eddi_Event();
break;
case "spansh.outdatedstations":
// Spansh
Context_Spansh_OutdatedStations();
break;
case "log.log":
// log
Context_Log();
break;
case "update.check":
// update
Context_Update_Check();
break;
default:
// invalid
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
}
}
/// <summary>
/// The Exit method, as required by the VoiceAttack plugin API.
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
public static void VA_Exit1(dynamic vaProxy)
{
}
/// <summary>
/// The StopCommand method, as required by the VoiceAttack plugin API.
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public static void VA_StopCommand()
{
}
/// <summary> /// <summary>
/// Returns whether a given profile is currently active. /// Returns whether a given profile is currently active.
/// </summary> /// </summary>
@ -544,148 +686,5 @@ namespace alterNERDtive
{ {
UpdateCheck(); UpdateCheck();
} }
/*========================================\
| required VoiceAttack plugin shenanigans |
\========================================*/
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "nicer grouping")]
private static readonly Version VERSION = new ("4.3.1");
/// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public static Guid VA_Id()
=> new ("{F7F59CFD-1AE2-4A7E-8F62-C62372418BAC}");
/// <summary>
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public static string VA_DisplayName()
=> $"alterNERDtive-base {VERSION}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public static string VA_DisplayInfo()
=> "The alterNERDtive plugin to manage all the alterNERDtive profiles!";
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Init1(dynamic vaProxy)
{
VA = vaProxy;
Log.Notice("Initializing …");
VA.SetText("alterNERDtive-base.version", VERSION.ToString());
vaProxy.BooleanVariableChanged += new Action<string, bool?, bool?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.DateVariableChanged += new Action<string, DateTime?, DateTime?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.DecimalVariableChanged += new Action<string, decimal?, decimal?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.IntegerVariableChanged += new Action<string, int?, int?, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
vaProxy.TextVariableChanged += new Action<string, string, string, Guid?>((name, from, to, id) => { ConfigurationChanged(name, from, to, id); });
VA.SetBoolean("alterNERDtive-base.initialized", true);
Commands.TriggerEvent("alterNERDtive-base.initialized", wait: false, logMissing: false);
Log.Notice("Init successful.");
}
/// <summary>
/// The Invoke method, as required by the VoiceAttack plugin API.
/// Runs whenever a plugin context is invoked.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public static void VA_Invoke1(dynamic vaProxy)
{
VA = vaProxy;
string context = vaProxy.Context.ToLower();
Log.Debug($"Running context '{context}' …");
try
{
switch (context)
{
case "startup":
Context_Startup();
break;
case "config.dialog":
// config
Context_Config_Dialog();
break;
case "config.dump":
Context_Config_Dump();
break;
case "config.getvariables":
Context_Config_SetVariables();
break;
case "config.list":
Context_Config_List();
break;
case "config.setup":
Context_Config_Setup();
break;
case "config.versionmigration":
Context_Config_VersionMigration();
break;
case "edsm.bodycount":
// EDSM
Context_EDSM_BodyCount();
break;
case "edsm.distancebetween":
Context_EDSM_DistanceBetween();
break;
case "eddi.event":
// EDDI
Context_Eddi_Event();
break;
case "spansh.outdatedstations":
// Spansh
Context_Spansh_OutdatedStations();
break;
case "log.log":
// log
Context_Log();
break;
case "update.check":
// update
Context_Update_Check();
break;
default:
// invalid
Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
break;
}
}
catch (ArgumentNullException e)
{
Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
}
}
/// <summary>
/// The Exit method, as required by the VoiceAttack plugin API.
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "required by VoiceAttack plugin API")]
public static void VA_Exit1(dynamic vaProxy)
{
}
/// <summary>
/// The StopCommand method, as required by the VoiceAttack plugin API.
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public static void VA_StopCommand()
{
}
} }
} }

View file

@ -1,10 +1,31 @@
#nullable enable // <auto-generated/>
// Not really, but this file will not bow to StyleCop tyranny.
// Why? Because it will be obsolete mid term anyway ;)
// <copyright file="edts.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using System; using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
namespace alterNERDtive.edts namespace alterNERDtive.edts
{ {

View file

@ -1,4 +1,23 @@
#nullable enable // <copyright file="util.cs" company="alterNERDtive">
// Copyright 20192022 alterNERDtive.
//
// This file is part of alterNERDtive VoiceAttack profiles for Elite Dangerous.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// alterNERDtive VoiceAttack profiles for Elite Dangerous is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with alterNERDtive VoiceAttack profiles for Elite Dangerous. If not, see &lt;https://www.gnu.org/licenses/&gt;.
// </copyright>
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -9,6 +28,7 @@ using System.Linq;
namespace alterNERDtive.util namespace alterNERDtive.util
{ {
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "file contains collection of utility classes")]
public class Configuration public class Configuration
{ {
private readonly dynamic VA; private readonly dynamic VA;