Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SpeechControl v1.0.0
SpeechControl.dll
Decompiled 8 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Windows.Speech; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Omniscye")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SpeechControl")] [assembly: AssemblyTitle("SpeechControl")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Empress.VoiceCommands { [BepInPlugin("gg.empress.repo.voicecommands", "Empress Voice Commands", "1.0.1")] public class VoiceCommandActionsPlugin : BaseUnityPlugin { [HarmonyPatch] private static class InputManager_KeyPatches { [HarmonyPostfix] [HarmonyPatch(typeof(InputManager), "KeyHold")] private static void KeyHold_Postfix(InputKey key, ref bool __result) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if (Chainloader.PluginInfos.ContainsKey("gg.empress.repo.voicecommands") && (int)key == 10 && VoiceGrabHold) { __result = true; } } [HarmonyPostfix] [HarmonyPatch(typeof(InputManager), "KeyDown")] private static void KeyDown_Postfix(InputKey key, ref bool __result) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 if (Chainloader.PluginInfos.ContainsKey("gg.empress.repo.voicecommands") && !__result) { if ((int)key == 2 && InteractPulseFrames > 0) { __result = true; } else if ((int)key == 9 && ConfirmPulseFrames > 0) { __result = true; } } } } public const string PluginGuid = "gg.empress.repo.voicecommands"; public const string PluginName = "Empress Voice Commands"; public const string PluginVersion = "1.0.1"; private Harmony _harmony; private ConfigEntry<bool> _enabled; private ConfigEntry<string> _keywordsCsv; private ConfigEntry<float> _shootToggleHoldSeconds; private ConfigEntry<int> _pressFrames; private ConfigEntry<bool> _logDebug; internal static bool VoiceGrabHold; internal static int InteractPulseFrames; internal static int ConfirmPulseFrames; internal static float ShootToggleHoldTimer; internal static bool ShootToggleArmed; private KeywordRecognizer _recognizer; private Dictionary<string, Action> _handlers; private void Awake() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master enable for the plugin."); _keywordsCsv = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Keywords", "grab,drop,shoot,tranq,use,press", "Comma-separated keywords to listen for. Supported actions: grab, drop, shoot, tranq, use, press."); _shootToggleHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "ShootToggleHoldSeconds", 0.06f, "How long to keep ItemToggle set when faking a shot (seconds). Useful for weapons that read a toggle edge."); _pressFrames = ((BaseUnityPlugin)this).Config.Bind<int>("Timing", "KeyPressFrames", 2, "How many frames a voice-triggered key press should be reported as down (Interact/Confirm)."); _logDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDebug", false, "Verbose logging."); _harmony = new Harmony("gg.empress.repo.voicecommands"); _harmony.PatchAll(typeof(InputManager_KeyPatches)); TryInitSpeech(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Voice Commands 1.0.1 loaded."); } private void OnDestroy() { try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } try { KeywordRecognizer recognizer = _recognizer; if (recognizer != null) { ((PhraseRecognizer)recognizer).Stop(); } KeywordRecognizer recognizer2 = _recognizer; if (recognizer2 != null) { ((PhraseRecognizer)recognizer2).Dispose(); } } catch { } } private void Update() { if (!_enabled.Value) { return; } if (InteractPulseFrames > 0) { InteractPulseFrames--; } if (ConfirmPulseFrames > 0) { ConfirmPulseFrames--; } if (ShootToggleArmed) { ShootToggleHoldTimer -= Time.unscaledDeltaTime; if (ShootToggleHoldTimer <= 0f) { ShootToggleArmed = false; ToggleCurrentItem(state: false); } } } private void TryInitSpeech() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown if (!_enabled.Value) { return; } if ((int)Application.platform != 2 && (int)Application.platform != 7) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Windows speech only supported on Windows. Voice commands disabled."); return; } List<string> list = ParseKeywords(_keywordsCsv.Value); if (list.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No keywords configured; voice commands disabled."); return; } _handlers = new Dictionary<string, Action>(StringComparer.InvariantCultureIgnoreCase) { { "grab", OnGrab }, { "drop", OnDrop }, { "use", OnUse }, { "press", OnPress }, { "shoot", OnShoot }, { "tranq", OnShoot } }; List<string> list2 = new List<string>(); foreach (string item in list) { if (_handlers.ContainsKey(item)) { list2.Add(item); } } if (list2.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Configured keywords had no supported actions. Nothing to listen for."); return; } try { _recognizer = new KeywordRecognizer(list2.ToArray(), (ConfidenceLevel)2); ((PhraseRecognizer)_recognizer).OnPhraseRecognized += (PhraseRecognizedDelegate)delegate(PhraseRecognizedEventArgs evt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) string text = evt.text; if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Heard '{text}' (conf {evt.confidence})."); } if (_handlers.TryGetValue(text, out Action value)) { try { value?.Invoke(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } }; ((PhraseRecognizer)_recognizer).Start(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Voice listening started for: " + string.Join(", ", list2))); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to start KeywordRecognizer: {arg}"); } } private static List<string> ParseKeywords(string csv) { List<string> list = new List<string>(); if (string.IsNullOrWhiteSpace(csv)) { return list; } string[] array = csv.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (!string.IsNullOrEmpty(text2)) { list.Add(text2.ToLowerInvariant()); } } return list; } private void OnGrab() { VoiceGrabHold = true; if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] GRAB -> hold enabled"); } } private void OnDrop() { VoiceGrabHold = false; if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] DROP -> hold disabled"); } } private void OnUse() { InteractPulseFrames = Mathf.Max(1, _pressFrames.Value); if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VC] USE -> Interact pulse {InteractPulseFrames} frames"); } } private void OnPress() { ConfirmPulseFrames = Mathf.Max(1, _pressFrames.Value); if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[VC] PRESS -> Confirm pulse {ConfirmPulseFrames} frames"); } } private void OnShoot() { PhysGrabber instance = PhysGrabber.instance; if ((Object)(object)instance == (Object)null) { if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] SHOOT -> no PhysGrabber instance"); } return; } PhysGrabObject grabbedPhysGrabObject = instance.grabbedPhysGrabObject; if ((Object)(object)grabbedPhysGrabObject == (Object)null || !grabbedPhysGrabObject.grabbedLocal) { if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] SHOOT -> nothing grabbed locally"); } return; } ItemGun component = ((Component)grabbedPhysGrabObject).GetComponent<ItemGun>(); if ((Object)(object)component != (Object)null) { try { component.Shoot(); if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] SHOOT -> ItemGun.Shoot()"); } return; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"[VC] SHOOT -> ItemGun.Shoot() failed: {arg}"); return; } } if (ToggleCurrentItem(state: true)) { ShootToggleHoldTimer = Mathf.Max(0.01f, _shootToggleHoldSeconds.Value); ShootToggleArmed = true; if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] SHOOT -> ItemToggle pulse"); } } else if (_logDebug.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[VC] SHOOT -> no supported shooter on held object"); } } private static bool ToggleCurrentItem(bool state) { PhysGrabber instance = PhysGrabber.instance; if ((Object)(object)instance == (Object)null) { return false; } PhysGrabObject grabbedPhysGrabObject = instance.grabbedPhysGrabObject; if ((Object)(object)grabbedPhysGrabObject == (Object)null) { return false; } ItemToggle component = ((Component)grabbedPhysGrabObject).GetComponent<ItemToggle>(); if ((Object)(object)component == (Object)null) { return false; } try { component.ToggleItem(state, -1); } catch { return false; } return true; } } } namespace SpeechControl { [BepInPlugin("Omniscye.SpeechControl", "SpeechControl", "1.0")] public class SpeechControl : BaseUnityPlugin { internal static SpeechControl Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { } } }