Please disclose if your mod was created primarily 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 LethalVoice v1.1.0
com.github.zehsteam.LethalVoice.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; 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 LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using UnityEngine; using VoiceRecognitionAPI; using com.github.zehsteam.LethalVoice.Dependencies; using com.github.zehsteam.LethalVoice.Helpers; using com.github.zehsteam.MonsterHotkeys; using com.github.zehsteam.MonsterHotkeys.Helpers; using com.github.zehsteam.MonsterHotkeys.MonoBehaviours; [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: AssemblyCompany("com.github.zehsteam.LethalVoice")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Spawn Monsters and Monster Plushies when you say specific words/phrases using the MonsterHotkeys mod. Highly Configurable.")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+90cc74c9e70bc5a090e414d236b01915a35937b0")] [assembly: AssemblyProduct("LethalVoice")] [assembly: AssemblyTitle("com.github.zehsteam.LethalVoice")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace com.github.zehsteam.LethalVoice { internal class ConfigManager { public ConfigEntry<bool> General_DisableHotkeys; public ConfigEntry<bool> VoiceRecognition_Enabled; public ConfigEntry<float> VoiceRecognition_Confidence; public ConfigEntry<bool> Enemy_Enabled; public ConfigEntry<string> Enemy_WordsToSpawnRandomEnemies; public ConfigEntry<bool> Plushie_Enabled; public ConfigEntry<string> Plushie_WordsToSpawnRandomPlushies; public ConfigEntry<bool> Message_ShowRecognizedPlushiePhraseMessages; public string[] Enemy_WordsToSpawnRandomEnemiesArray { get { return Utils.StringToArray<string>(Enemy_WordsToSpawnRandomEnemies.Value); } set { Enemy_WordsToSpawnRandomEnemies.Value = Utils.ArrayToString(value); } } public string[] Plushie_WordsToSpawnRandomPlushiesArray { get { return Utils.StringToArray<string>(Plushie_WordsToSpawnRandomPlushies.Value); } set { Plushie_WordsToSpawnRandomPlushies.Value = Utils.ArrayToString(value); } } public ConfigManager() { BindConfigs(); MigrateOldConfigSettings(); ConfigHelper.ClearUnusedEntries(); } private void BindConfigs() { ConfigHelper.SkipAutoGen(); General_DisableHotkeys = ConfigHelper.Bind("General", "DisableHotkeys", defaultValue: true, "If enabled, the hotkeys from the MonsterHotkeys mod will be disabled."); General_DisableHotkeys.SettingChanged += Plugin.Instance.OnDisableHotkeysChanged; VoiceRecognition_Enabled = ConfigHelper.Bind("Voice Recognition", "Enabled", defaultValue: true, "If enabled, speech recognition will be active."); VoiceRecognition_Confidence = ConfigHelper.Bind("Voice Recognition", "Confidence", 0.7f, "How difficult it will be for the speech recognition to recognize your word/phrase.", requiresRestart: false, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)); Enemy_Enabled = ConfigHelper.Bind("Enemy", "Enabled", defaultValue: true, "If enabled, you will be able to spawn random monsters when specific words/phrases are said. (Requires VoiceRecognition to be enabled)"); Enemy_WordsToSpawnRandomEnemies = ConfigHelper.Bind("Enemy", "WordsToSpawnRandomEnemies", "alright, fuck, garbage, god, hell, kill, mate, nuts, piece, shit, wait, what, why", "The list of words/phrases you want to trigger a random monster spawn. Each word/phrase should be separated by a comma."); Enemy_WordsToSpawnRandomEnemies.SettingChanged += Plugin.Instance.OnSpawnRandomMonsterWordsChanged; Plushie_Enabled = ConfigHelper.Bind("Plushie", "Enabled", defaultValue: true, "If enabled, you will be able to spawn random plushies when specific words/phrases are said. (Requires VoiceRecognition to be enabled)"); Plushie_WordsToSpawnRandomPlushies = ConfigHelper.Bind("Plushie", "WordsToSpawnRandomPlushies", "ban, hate, like, messed, no, ok, rizz, stop, thank, this", "The list of words/phrases you want to trigger a random plushie spawn. Each word/phrase should be separated by a comma."); Plushie_WordsToSpawnRandomPlushies.SettingChanged += Plugin.Instance.OnSpawnRandomPlushieWordsChanged; Message_ShowRecognizedPlushiePhraseMessages = ConfigHelper.Bind("Message", "ShowRecognizedPlushiePhraseMessages", defaultValue: true, "If enabled, will show a message when a phrase is recognized for spawning plushies. See additional message setting in the MonsterHotkeys config file."); } private void MigrateOldConfigSettings() { foreach (KeyValuePair<ConfigDefinition, string> orphanedConfigEntry in ConfigHelper.GetOrphanedConfigEntries()) { MigrateOldConfigSetting(orphanedConfigEntry.Key.Section, orphanedConfigEntry.Key.Key, orphanedConfigEntry.Value); } } private void MigrateOldConfigSetting(string section, string key, string value) { StringComparison comparisonType = StringComparison.OrdinalIgnoreCase; if (section.Equals("General Settings", comparisonType)) { if (key.Equals("VoiceRecognitionEnabled", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(VoiceRecognition_Enabled, value); return; } if (key.Equals("VoiceConfidence", comparisonType)) { ConfigHelper.SetConfigEntryValue<float>(VoiceRecognition_Confidence, value); return; } if (key.Equals("DisableHotkeys", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(General_DisableHotkeys, value); return; } if (key.Equals("ShowRecognizedPlushiePhraseMessages", comparisonType)) { ConfigHelper.SetConfigEntryValue<bool>(Message_ShowRecognizedPlushiePhraseMessages, value); return; } } if (section.Equals("Monster Settings", comparisonType) && key.Equals("SpawnRandomMonsterWords", comparisonType)) { ConfigHelper.SetConfigEntryValue<string>(Enemy_WordsToSpawnRandomEnemies, value); } else if (section.Equals("Plushie Settings", comparisonType) && key.Equals("SpawnRandomPlushieWords", comparisonType)) { ConfigHelper.SetConfigEntryValue<string>(Plushie_WordsToSpawnRandomPlushies, value); } } } [BepInPlugin("com.github.zehsteam.LethalVoice", "LethalVoice", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class Plugin : BaseUnityPlugin { private string[] _activePhrases = Array.Empty<string>(); internal static Plugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static ConfigManager ConfigManager { get; private set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } Logger = Logger.CreateLogSource("com.github.zehsteam.LethalVoice"); Logger.LogInfo((object)"LethalVoice has awoken!"); ConfigManager = new ConfigManager(); RegisterVoiceListener(); UpdateDisableHotkeys(); } private void RegisterVoiceListener() { string[] enemy_WordsToSpawnRandomEnemiesArray = ConfigManager.Enemy_WordsToSpawnRandomEnemiesArray; string[] plushie_WordsToSpawnRandomPlushiesArray = ConfigManager.Plushie_WordsToSpawnRandomPlushiesArray; int num = 0; string[] array = new string[enemy_WordsToSpawnRandomEnemiesArray.Length + plushie_WordsToSpawnRandomPlushiesArray.Length]; ReadOnlySpan<string> readOnlySpan = new ReadOnlySpan<string>(enemy_WordsToSpawnRandomEnemiesArray); readOnlySpan.CopyTo(new Span<string>(array).Slice(num, readOnlySpan.Length)); num += readOnlySpan.Length; ReadOnlySpan<string> readOnlySpan2 = new ReadOnlySpan<string>(plushie_WordsToSpawnRandomPlushiesArray); readOnlySpan2.CopyTo(new Span<string>(array).Slice(num, readOnlySpan2.Length)); num += readOnlySpan2.Length; _activePhrases = array; Voice.RegisterPhrases(_activePhrases); Voice.RegisterCustomHandler((EventHandler<VoiceRecognitionEventArgs>)HandleVoiceRecognitionPhrase); } private void HandleVoiceRecognitionPhrase(object obj, VoiceRecognitionEventArgs recognized) { if (ConfigManager.VoiceRecognition_Enabled.Value && !(recognized.Confidence < ConfigManager.VoiceRecognition_Confidence.Value)) { string message = recognized.Message; if (ConfigManager.Enemy_Enabled.Value && Utils.ArrayContains(ConfigManager.Enemy_WordsToSpawnRandomEnemiesArray, message)) { Logger.LogInfo((object)$"Recognized phrase \"{message}\" with a confidence of {recognized.Confidence}"); SpawnRandomEnemy(message); } if (ConfigManager.Plushie_Enabled.Value && Utils.ArrayContains(ConfigManager.Plushie_WordsToSpawnRandomPlushiesArray, message)) { Logger.LogInfo((object)$"Recognized phrase \"{message}\" with a confidence of {recognized.Confidence}"); SpawnRandomPlushies(message); } } } private void SpawnRandomEnemy(string phrase) { try { EnemyHelper.SpawnRandomEnemy(phrase); } catch (Exception arg) { Logger.LogError((object)$"Failed to spawn random enemy. {arg}"); } } private void SpawnRandomPlushies(string phrase) { try { PlushieManager instance = PlushieManager.Instance; if (instance != null) { instance.SpawnRandomPlushies(); } ShowPlushiePhraseRecognizedMessage(phrase); } catch (Exception arg) { Logger.LogError((object)$"Failed to spawn random plushies. {arg}"); } } public void OnSpawnRandomMonsterWordsChanged(object sender, EventArgs e) { string[] array = ConfigManager.Enemy_WordsToSpawnRandomEnemiesArray.Where((string x) => !Utils.ArrayContains(_activePhrases, x)).ToArray(); if (array.Length != 0) { Voice.RegisterPhrases(array); } } public void OnSpawnRandomPlushieWordsChanged(object sender, EventArgs e) { string[] array = ConfigManager.Plushie_WordsToSpawnRandomPlushiesArray.Where((string x) => !Utils.ArrayContains(_activePhrases, x)).ToArray(); if (array.Length != 0) { Voice.RegisterPhrases(array); } } private void ShowPlushiePhraseRecognizedMessage(string phrase) { if (!ConfigManager.Message_ShowRecognizedPlushiePhraseMessages.Value) { return; } try { if (!((Object)(object)PlushieManager.Instance == (Object)null) && PlushieManager.Instance.CanSpawnPlushies()) { MessageCanvas instance = MessageCanvas.Instance; if (instance != null) { instance.ShowMessage_LocalClient("Recognized phrase \"" + phrase + "\""); } } } catch (Exception arg) { Logger.LogError((object)$"Failed to show plushie phrase recognized message on local client.\n\n{arg}"); } } private void UpdateDisableHotkeys() { bool value = ConfigManager.General_DisableHotkeys.Value; try { HotkeyListener.DisableHotkeys = value; Logger.LogInfo((object)((value ? "Disabled" : "Enabled") + " MonsterHotkeys hotkeys.")); } catch (Exception arg) { Logger.LogError((object)string.Format("Failed to {0} MonsterHotkeys hotkeys.\n\n{1}", value ? "disable" : "enable", arg)); } } public void OnDisableHotkeysChanged(object sender, EventArgs e) { UpdateDisableHotkeys(); } } internal static class Utils { public static T[] StringToArray<T>(string value) { if (string.IsNullOrEmpty(value)) { return Array.Empty<T>(); } try { return (from x in value.Split(',') select (T)Convert.ChangeType(x.Trim(), typeof(T))).ToArray(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Failed to convert string to array of type {typeof(T)}. \"{value}\". {arg}"); } return Array.Empty<T>(); } public static string ArrayToString<T>(T[] value) { if (value == null || value.Length == 0) { return string.Empty; } return string.Join(", ", value.Select((T x) => x.ToString())); } public static bool ArrayContains(string[] array, string value, bool matchCase = false) { if (value == null || value.Length == 0) { return false; } StringComparison comparisonType = ((!matchCase) ? StringComparison.OrdinalIgnoreCase : StringComparison.CurrentCulture); return array.Any((string x) => x.Equals(value, comparisonType)); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.github.zehsteam.LethalVoice"; public const string PLUGIN_NAME = "LethalVoice"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace com.github.zehsteam.LethalVoice.Helpers { internal static class ConfigHelper { public static void SkipAutoGen() { if (LethalConfigProxy.Enabled) { LethalConfigProxy.SkipAutoGen(); } } public static void AddButton(string section, string name, string buttonText, string description, Action callback) { if (LethalConfigProxy.Enabled) { LethalConfigProxy.AddButton(section, name, buttonText, description, callback); } } public static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, bool requiresRestart = false, AcceptableValueBase acceptableValues = null, Action<T> settingChanged = null, ConfigFile configFile = null) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown if (configFile == null) { configFile = ((BaseUnityPlugin)Plugin.Instance).Config; } ConfigEntry<T> configEntry = ((acceptableValues == null) ? configFile.Bind<T>(section, key, defaultValue, description) : configFile.Bind<T>(section, key, defaultValue, new ConfigDescription(description, acceptableValues, Array.Empty<object>()))); if (settingChanged != null) { configEntry.SettingChanged += delegate { settingChanged?.Invoke(configEntry.Value); }; } if (LethalConfigProxy.Enabled) { LethalConfigProxy.AddConfig<T>(configEntry, requiresRestart); } return configEntry; } public static Dictionary<ConfigDefinition, string> GetOrphanedConfigEntries(ConfigFile configFile = null) { if (configFile == null) { configFile = ((BaseUnityPlugin)Plugin.Instance).Config; } PropertyInfo property = ((object)configFile).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic); return (Dictionary<ConfigDefinition, string>)property.GetValue(configFile, null); } public static void SetConfigEntryValue<T>(ConfigEntry<T> configEntry, string value) { if (typeof(T) == typeof(int) && int.TryParse(value, out var result)) { configEntry.Value = (T)(object)result; return; } if (typeof(T) == typeof(float) && float.TryParse(value, out var result2)) { configEntry.Value = (T)(object)result2; return; } if (typeof(T) == typeof(double) && double.TryParse(value, out var result3)) { configEntry.Value = (T)(object)result3; return; } if (typeof(T) == typeof(bool) && bool.TryParse(value, out var result4)) { configEntry.Value = (T)(object)result4; return; } if (typeof(T) == typeof(string)) { configEntry.Value = (T)(object)value; return; } throw new InvalidOperationException($"Unsupported type: {typeof(T)}"); } public static void ClearUnusedEntries(ConfigFile configFile = null) { if (configFile == null) { configFile = ((BaseUnityPlugin)Plugin.Instance).Config; } Dictionary<ConfigDefinition, string> orphanedConfigEntries = GetOrphanedConfigEntries(configFile); if (orphanedConfigEntries != null) { orphanedConfigEntries.Clear(); configFile.Save(); } } } } namespace com.github.zehsteam.LethalVoice.Dependencies { internal static class LethalConfigProxy { public const string PLUGIN_GUID = "ainavt.lc.lethalconfig"; private static bool? _enabled; public static bool Enabled { get { bool valueOrDefault = _enabled.GetValueOrDefault(); if (!_enabled.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig"); _enabled = valueOrDefault; } return _enabled.Value; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void SkipAutoGen() { LethalConfigManager.SkipAutoGen(); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddConfig<T>(ConfigEntry<T> configEntry, bool requiresRestart = false) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown AcceptableValueBase acceptableValues = ((ConfigEntryBase)configEntry).Description.AcceptableValues; if (acceptableValues != null) { if (acceptableValues is AcceptableValueRange<float> || acceptableValues is AcceptableValueRange<int>) { AddConfigSlider<T>(configEntry, requiresRestart); return; } if (acceptableValues is AcceptableValueList<string>) { AddConfigDropdown<T>(configEntry, requiresRestart); return; } } if (!(configEntry is ConfigEntry<string> val)) { if (!(configEntry is ConfigEntry<bool> val2)) { if (!(configEntry is ConfigEntry<float> val3)) { if (!(configEntry is ConfigEntry<int> val4)) { throw new NotSupportedException($"Unsupported type: {typeof(T)}"); } LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(val4, requiresRestart)); } else { LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(val3, requiresRestart)); } } else { LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(val2, requiresRestart)); } } else { LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(val, requiresRestart)); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddConfigSlider<T>(ConfigEntry<T> configEntry, bool requiresRestart = false) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (!(configEntry is ConfigEntry<float> val)) { if (!(configEntry is ConfigEntry<int> val2)) { throw new NotSupportedException($"Slider not supported for type: {typeof(T)}"); } LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(val2, requiresRestart)); } else { LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(val, requiresRestart)); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddConfigDropdown<T>(ConfigEntry<T> configEntry, bool requiresRestart = false) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (configEntry is ConfigEntry<string> val) { LethalConfigManager.AddConfigItem((BaseConfigItem)new TextDropDownConfigItem(val, requiresRestart)); return; } throw new NotSupportedException($"Dropdown not supported for type: {typeof(T)}"); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void AddButton(string section, string name, string buttonText, string description, Action callback) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem(section, name, description, buttonText, (GenericButtonHandler)delegate { callback?.Invoke(); })); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }