Decompiled source of LethalHaptics v0.0.6

BepInEx/plugins/LethalVibrations.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Buttplug.Client;
using Buttplug.Client.Connectors.WebsocketConnector;
using Buttplug.Core;
using Costura;
using GameNetcodeStuff;
using HarmonyLib;
using LethalVibrations.Buttplug;
using LethalVibrations.Patches;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")]
[assembly: AssemblyCompany("LethalVibrations")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Lethal Company mod that makes your sex toys vibrate.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LethalVibrations")]
[assembly: AssemblyTitle("LethalVibrations")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
internal class <Module>
{
	static <Module>()
	{
		AssemblyLoader.Attach();
	}
}
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 LethalVibrations
{
	[BepInPlugin("LethalVibrations", "LethalVibrations", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static DeviceManager DeviceManager { get; private set; }

		internal static ManualLogSource Mls { get; private set; }

		private void Awake()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			Mls = ((BaseUnityPlugin)this).Logger;
			DeviceManager = new DeviceManager("LethalVibrations");
			DeviceManager.ConnectDevices();
			Harmony val = new Harmony("LethalVibrations");
			val.PatchAll(typeof(PlayerControllerBPatches));
			val.PatchAll(typeof(ItemChargerPatches));
			val.PatchAll(typeof(EnemyAIPatches));
			val.PatchAll(typeof(HUDManagerPatches));
			val.PatchAll(typeof(GrabbableObjectPatches));
			val.PatchAll(typeof(RoundManagerPatches));
			val.PatchAll(typeof(NoisemakerPropPatches));
			val.PatchAll(typeof(ShipAlarmCordPatches));
			val.PatchAll(typeof(StunGrenadeItemPatches));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalVibrations (1.0.0) is loaded!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "LethalVibrations";

		public const string PLUGIN_NAME = "LethalVibrations";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace LethalVibrations.Patches
{
	internal class EnemyAIPatches
	{
		[HarmonyPatch(typeof(EnemyAI), "HitEnemy")]
		[HarmonyPostfix]
		private static void HitEnemyPatch(int force, PlayerControllerB playerWhoHit)
		{
			if (playerWhoHit.playerClientId == GameNetworkManager.Instance.localPlayerController.playerClientId)
			{
				Plugin.Mls.LogDebug((object)"HitEnemy got called");
				if (Plugin.DeviceManager.IsConnected() && Config.VibrateDamageDealtEnabled.Value)
				{
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.VibrateDamageDealtStrength.Value, Config.VibrateDamageDealtDuration.Value);
				}
			}
		}
	}
	internal class GrabbableObjectPatches
	{
		[HarmonyPatch(typeof(GrabbableObject), "GrabItemOnClient")]
		[HarmonyPostfix]
		private static void GrabItemOnClientPatch(GrabbableObject __instance)
		{
			if (__instance.itemProperties.isScrap && !__instance.isInShipRoom)
			{
				Plugin.Mls.LogDebug((object)"GrabItemOnClient called");
				if (Plugin.DeviceManager.IsConnected() && Config.Rewarding.Value)
				{
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.VibrateKilledStrength.Value, Config.VibrateKilledDuration.Value);
				}
			}
		}
	}
	internal class HUDManagerPatches
	{
		[HarmonyPatch(typeof(HUDManager), "ShakeCamera")]
		[HarmonyPostfix]
		private static void ShakeCameraPatch(ScreenShakeType shakeType)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected I4, but got Unknown
			Plugin.Mls.LogDebug((object)$"ShakeCamera {shakeType} got called");
			if (Plugin.DeviceManager.IsConnected() && Config.VibrateScreenShakeEnabled.Value)
			{
				switch ((int)shakeType)
				{
				case 0:
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(0.3f + Config.VibrateScreenShakeAmplifier.Value, Config.VibrateScreenShakeDuration.Value);
					break;
				case 1:
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(0.6f + Config.VibrateScreenShakeAmplifier.Value, Config.VibrateScreenShakeDuration.Value);
					break;
				case 2:
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(0.5f + Config.VibrateScreenShakeAmplifier.Value, Config.VibrateScreenShakeDuration.Value + 0.6f);
					break;
				case 3:
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(0.9f + Config.VibrateScreenShakeAmplifier.Value, Config.VibrateScreenShakeDuration.Value + 0.3f);
					break;
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "DisplayNewDeadline")]
		[HarmonyPostfix]
		private static void DisplayNewDeadlinePatch()
		{
			Plugin.Mls.LogDebug((object)"DisplayNewDeadline got called");
			if (Plugin.DeviceManager.IsConnected() && Config.QuotaReachedEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.QuotaReachedStrength.Value, Config.QuotaReachedDuration.Value);
			}
		}

		[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
		[HarmonyPostfix]
		private static void PingScan_performedPatch()
		{
			Plugin.Mls.LogDebug((object)"PingScan_performed got called");
			if (Plugin.DeviceManager.IsConnected() && Config.PingScanEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.PingScanStrength.Value, Config.PingScanDuration.Value);
			}
		}
	}
	internal class ItemChargerPatches
	{
		[HarmonyPatch(typeof(ItemCharger), "ChargeItem")]
		[HarmonyPostfix]
		private static void ChargeItemPatch()
		{
			Plugin.Mls.LogDebug((object)"ChargeItem got called");
			if (Plugin.DeviceManager.IsConnected() && Config.VibrateItemChargerChargeEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.VibrateItemChargerChargeStrength.Value, Config.VibrateItemChargerChargeDuration.Value);
			}
		}
	}
	internal class NoisemakerPropPatches
	{
		[HarmonyPatch(typeof(NoisemakerProp), "ItemActivate")]
		[HarmonyPostfix]
		private static void ItemActivatePatch(NoisemakerProp __instance)
		{
			Plugin.Mls.LogDebug((object)("NoisemakerProp.ItemActivate got called: " + ((GrabbableObject)__instance).itemProperties.itemName));
			if (!(((GrabbableObject)__instance).itemProperties.itemName != "Airhorn") && Plugin.DeviceManager.IsConnected() && Config.AirhornEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.AirhornStrength.Value, Config.AirhornDuration.Value);
			}
		}
	}
	internal class PlayerControllerBPatches
	{
		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
		[HarmonyPostfix]
		private static void DamagePlayerPatch(PlayerControllerB __instance, int damageNumber)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				float num = damageNumber;
				Plugin.Mls.LogDebug((object)$"DamagePlayer got called: {num} ({num / 100f})");
				if (Plugin.DeviceManager.IsConnected() && Config.VibrateDamageReceivedEnabled.Value)
				{
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(num / 100f + Config.VibrateDamageReceivedAmplifier.Value, Config.VibrateDamageReceivedDuration.Value);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPostfix]
		private static void KillPlayerPatch(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				Plugin.Mls.LogDebug((object)"KillPlayer got called");
				if (Plugin.DeviceManager.IsConnected() && Config.VibrateKilledEnabled.Value)
				{
					Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.VibrateKilledStrength.Value, Config.VibrateKilledDuration.Value);
				}
			}
		}
	}
	public class RoundManagerPatches
	{
		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPostfix]
		private static void GrabItemOnClientPatch(RoundManager __instance)
		{
			Plugin.Mls.LogDebug((object)"DespawnPropsAtEndOfRound called");
			if (Plugin.DeviceManager.IsConnected() && Config.RoundSurvivalEnabled.Value && !GameNetworkManager.Instance.localPlayerController.isPlayerDead)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.RoundSurvivalStrength.Value, Config.RoundSurvivalDuration.Value);
			}
		}
	}
	public class ShipAlarmCordPatches
	{
		[HarmonyPatch(typeof(ShipAlarmCord), "PullCordClientRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PullCordClientRpcTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = list.FindLastIndex((CodeInstruction i) => i.opcode == OpCodes.Nop) + 1;
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ShipAlarmCordPatches), "StartVibrating", (Type[])null, (Type[])null))
			});
			foreach (CodeInstruction item in list)
			{
				yield return item;
			}
		}

		[HarmonyPatch(typeof(ShipAlarmCord), "StopPullingCordClientRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> StopPullingCordClientRpcTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			int index = list.FindLastIndex((CodeInstruction i) => i.opcode == OpCodes.Nop) + 1;
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ShipAlarmCordPatches), "StopVibrating", (Type[])null, (Type[])null))
			});
			foreach (CodeInstruction item in list)
			{
				yield return item;
			}
		}

		[HarmonyPatch(typeof(ShipAlarmCord), "HoldCordDown")]
		[HarmonyPostfix]
		private static void HoldCordDownPatch()
		{
			Plugin.Mls.LogDebug((object)"ShipAlarmCord.HoldCordDown got called");
			StartVibrating();
		}

		[HarmonyPatch(typeof(ShipAlarmCord), "StopHorn")]
		[HarmonyPostfix]
		private static void StopHornPatch()
		{
			Plugin.Mls.LogDebug((object)"ShipAlarmCord.StopHorn got called");
			StopVibrating();
		}

		private static void StartVibrating()
		{
			if (Plugin.DeviceManager.IsConnected() && Config.ShipHornEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevices(Config.ShipHornStrength.Value);
			}
		}

		private static void StopVibrating()
		{
			if (Plugin.DeviceManager.IsConnected() && Config.ShipHornEnabled.Value)
			{
				Plugin.DeviceManager.StopConnectedDevices();
			}
		}
	}
	public class StunGrenadeItemPatches
	{
		[HarmonyPatch(typeof(StunGrenadeItem), "StunExplosion")]
		[HarmonyPostfix]
		private static void StunExplosionPatch(StunGrenadeItem __instance)
		{
			Plugin.Mls.LogDebug((object)"StunExplosion got called");
			if (Plugin.DeviceManager.IsConnected() && Config.FlashbangEnabled.Value)
			{
				Plugin.DeviceManager.VibrateConnectedDevicesWithDuration(Config.FlashbangStrength.Value, 0.3f);
			}
		}
	}
}
namespace LethalVibrations.Buttplug
{
	internal class Config
	{
		private static ConfigFile ConfigFile { get; set; }

		internal static ConfigEntry<string> ServerUri { get; set; }

		internal static ConfigEntry<float> VibrateAmplifier { get; set; }

		internal static ConfigEntry<bool> Rewarding { get; set; }

		internal static ConfigEntry<bool> VibrateDamageReceivedEnabled { get; set; }

		internal static ConfigEntry<float> VibrateDamageReceivedDuration { get; set; }

		internal static ConfigEntry<float> VibrateDamageReceivedAmplifier { get; set; }

		internal static ConfigEntry<bool> VibrateDamageDealtEnabled { get; set; }

		internal static ConfigEntry<float> VibrateDamageDealtDuration { get; set; }

		internal static ConfigEntry<float> VibrateDamageDealtStrength { get; set; }

		internal static ConfigEntry<bool> VibrateKilledEnabled { get; set; }

		internal static ConfigEntry<float> VibrateKilledDuration { get; set; }

		internal static ConfigEntry<float> VibrateKilledStrength { get; set; }

		internal static ConfigEntry<bool> VibrateItemChargerChargeEnabled { get; set; }

		internal static ConfigEntry<float> VibrateItemChargerChargeDuration { get; set; }

		internal static ConfigEntry<float> VibrateItemChargerChargeStrength { get; set; }

		internal static ConfigEntry<bool> VibrateScreenShakeEnabled { get; set; }

		internal static ConfigEntry<float> VibrateScreenShakeDuration { get; set; }

		internal static ConfigEntry<float> VibrateScreenShakeAmplifier { get; set; }

		internal static ConfigEntry<bool> PingScanEnabled { get; set; }

		internal static ConfigEntry<float> PingScanDuration { get; set; }

		internal static ConfigEntry<float> PingScanStrength { get; set; }

		internal static ConfigEntry<bool> QuotaReachedEnabled { get; set; }

		internal static ConfigEntry<float> QuotaReachedDuration { get; set; }

		internal static ConfigEntry<float> QuotaReachedStrength { get; set; }

		internal static ConfigEntry<bool> RoundSurvivalEnabled { get; set; }

		internal static ConfigEntry<float> RoundSurvivalDuration { get; set; }

		internal static ConfigEntry<float> RoundSurvivalStrength { get; set; }

		internal static ConfigEntry<bool> AirhornEnabled { get; set; }

		internal static ConfigEntry<float> AirhornDuration { get; set; }

		internal static ConfigEntry<float> AirhornStrength { get; set; }

		internal static ConfigEntry<bool> ShipHornEnabled { get; set; }

		internal static ConfigEntry<float> ShipHornStrength { get; set; }

		internal static ConfigEntry<bool> FlashbangEnabled { get; set; }

		internal static ConfigEntry<float> FlashbangStrength { get; set; }

		static Config()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			ConfigFile = new ConfigFile(Paths.ConfigPath + "\\LethalVibrations.cfg", true);
			ServerUri = ConfigFile.Bind<string>("Devices", "Server Uri", "ws://localhost:12345", "URI of the Intiface server.");
			VibrateAmplifier = ConfigFile.Bind<float>("Vibrations", "Amplifier", 0f, "Change the amplification of vibration");
			Rewarding = ConfigFile.Bind<bool>("Vibrations", "Rewarding", true, "Enable rewarding");
			VibrateDamageDealtEnabled = ConfigFile.Bind<bool>("Vibrations.DamageDealt", "Enabled", true, "Vibrate when you deal damage");
			VibrateDamageDealtDuration = ConfigFile.Bind<float>("Vibrations.DamageDealt", "Duration", 1f, "Length of time to vibrate for");
			VibrateDamageDealtStrength = ConfigFile.Bind<float>("Vibrations.DamageDealt", "Strength", 0.5f, "Change the strength of vibration");
			QuotaReachedEnabled = ConfigFile.Bind<bool>("Vibrations.QuotaReached", "Enabled", true, "Vibrate when you reach the quota");
			QuotaReachedDuration = ConfigFile.Bind<float>("Vibrations.QuotaReached", "Duration", 1f, "Length of time to vibrate for");
			QuotaReachedStrength = ConfigFile.Bind<float>("Vibrations.QuotaReached", "Strength", 0.5f, "Change the strength of vibration");
			RoundSurvivalEnabled = ConfigFile.Bind<bool>("Vibrations.RoundSurvival", "Enabled", true, "Vibrate when you survive the round");
			RoundSurvivalDuration = ConfigFile.Bind<float>("Vibrations.RoundSurvival", "Duration", 1f, "Length of time to vibrate for");
			RoundSurvivalStrength = ConfigFile.Bind<float>("Vibrations.RoundSurvival", "Strength", 0.3f, "Change the strength of vibration");
			VibrateDamageReceivedEnabled = ConfigFile.Bind<bool>("Vibrations.DamageReceived", "Enabled", true, "Vibrate when you receive damage");
			VibrateDamageReceivedDuration = ConfigFile.Bind<float>("Vibrations.DamageReceived", "Duration", 1f, "Length of time to vibrate for");
			VibrateDamageReceivedAmplifier = ConfigFile.Bind<float>("Vibrations.DamageReceived", "Amplifier", 0f, "Change the amplification of vibration");
			VibrateKilledEnabled = ConfigFile.Bind<bool>("Vibrations.PlayerKilled", "Enabled", false, "Vibrate when you die");
			VibrateKilledDuration = ConfigFile.Bind<float>("Vibrations.PlayerKilled", "Duration", 1f, "Length of time to vibrate for");
			VibrateKilledStrength = ConfigFile.Bind<float>("Vibrations.PlayerKilled", "Strength", 1f, "Change the strength of vibration");
			PingScanEnabled = ConfigFile.Bind<bool>("Vibrations.PingScan", "Enabled", false, "Vibrate when you press right click");
			PingScanDuration = ConfigFile.Bind<float>("Vibrations.PingScan", "Duration", 0.3f, "Length of time to vibrate for");
			PingScanStrength = ConfigFile.Bind<float>("Vibrations.PingScan", "Strength", 0.3f, "Change the strength of vibration");
			VibrateItemChargerChargeEnabled = ConfigFile.Bind<bool>("Vibrations.ItemCharge", "Enabled", true, "Vibrate when you charge an item");
			VibrateItemChargerChargeDuration = ConfigFile.Bind<float>("Vibrations.ItemCharge", "Duration", 1f, "Length of time to vibrate for");
			VibrateItemChargerChargeStrength = ConfigFile.Bind<float>("Vibrations.ItemCharge", "Strength", 0.4f, "Change the strength of vibration");
			VibrateScreenShakeEnabled = ConfigFile.Bind<bool>("Vibrations.ShakeScreen", "Enabled", true, "Vibrate when your screen shakes");
			VibrateScreenShakeDuration = ConfigFile.Bind<float>("Vibrations.ShakeScreen", "Duration", 1f, "Length of time to vibrate for");
			VibrateScreenShakeAmplifier = ConfigFile.Bind<float>("Vibrations.ShakeScreen", "Amplifier", 0f, "Change the amplification of vibration");
			AirhornEnabled = ConfigFile.Bind<bool>("Vibrations.Airhorn", "Enabled", false, "Vibrate when someone uses the airhorn");
			AirhornDuration = ConfigFile.Bind<float>("Vibrations.Airhorn", "Duration", 1f, "Length of time to vibrate for");
			AirhornStrength = ConfigFile.Bind<float>("Vibrations.Airhorn", "Strength", 0.1f, "Change the intensity of vibration");
			ShipHornEnabled = ConfigFile.Bind<bool>("Vibrations.ShipHorn", "Enabled", true, "Vibrate when someone airs the ships horn");
			ShipHornStrength = ConfigFile.Bind<float>("Vibrations.ShipHorn", "Strength", 0.5f, "Change the intensity of vibration");
			FlashbangEnabled = ConfigFile.Bind<bool>("Vibrations.Flashbang", "Enabled", true, "Vibrate when a flashbang goes off");
			FlashbangStrength = ConfigFile.Bind<float>("Vibrations.Flashbang", "Strength", 0.5f, "Change the intensity of vibration");
		}
	}
	public class DeviceManager
	{
		private List<ButtplugClientDevice> ConnectedDevices { get; set; }

		private ButtplugClient ButtplugClient { get; set; }

		public DeviceManager(string clientName)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			ConnectedDevices = new List<ButtplugClientDevice>();
			ButtplugClient = new ButtplugClient(clientName);
			Plugin.Mls.LogInfo((object)("BP client created for " + clientName));
			ButtplugClient.DeviceAdded += HandleDeviceAdded;
			ButtplugClient.DeviceRemoved += HandleDeviceRemoved;
		}

		public bool IsConnected()
		{
			return ButtplugClient.Connected;
		}

		public async void ConnectDevices()
		{
			if (ButtplugClient.Connected)
			{
				return;
			}
			try
			{
				Plugin.Mls.LogInfo((object)("Attempting to connect to Intiface server at " + Config.ServerUri.Value));
				await ButtplugClient.ConnectAsync((IButtplugClientConnector)new ButtplugWebsocketConnector(new Uri(Config.ServerUri.Value)), default(CancellationToken));
				Plugin.Mls.LogInfo((object)"Connection successful. Beginning scan for devices");
				await ButtplugClient.StartScanningAsync(default(CancellationToken));
			}
			catch (ButtplugException val)
			{
				ButtplugException arg = val;
				Plugin.Mls.LogError((object)"Attempt to connect to devices failed. Ensure Intiface is running and attempt to reconnect from the 'Devices' section in the mod's in-game settings.");
				Plugin.Mls.LogDebug((object)$"ButtplugIO error occured while connecting devices: {arg}");
			}
		}

		public void VibrateConnectedDevicesWithDuration(double intensity, float time)
		{
			intensity += Config.VibrateAmplifier.Value;
			ConnectedDevices.ForEach(Action);
			async void Action(ButtplugClientDevice device)
			{
				await device.VibrateAsync((double)Mathf.Clamp((float)intensity, 0f, 1f));
				await Task.Delay((int)(time * 1000f));
				await device.VibrateAsync(0.0);
			}
		}

		public void VibrateConnectedDevices(double intensity)
		{
			intensity += Config.VibrateAmplifier.Value;
			ConnectedDevices.ForEach(Action);
			async void Action(ButtplugClientDevice device)
			{
				await device.VibrateAsync((double)Mathf.Clamp((float)intensity, 0f, 1f));
			}
		}

		public void StopConnectedDevices()
		{
			ConnectedDevices.ForEach(async delegate(ButtplugClientDevice device)
			{
				await device.Stop();
			});
		}

		internal void CleanUp()
		{
			StopConnectedDevices();
		}

		private void HandleDeviceAdded(object sender, DeviceAddedEventArgs args)
		{
			if (!IsVibratableDevice(args.Device))
			{
				Plugin.Mls.LogInfo((object)(args.Device.Name + " was detected but ignored due to it not being vibratable."));
				return;
			}
			Plugin.Mls.LogInfo((object)(args.Device.Name + " connected to client " + ButtplugClient.Name));
			ConnectedDevices.Add(args.Device);
		}

		private void HandleDeviceRemoved(object sender, DeviceRemovedEventArgs args)
		{
			if (IsVibratableDevice(args.Device))
			{
				Plugin.Mls.LogInfo((object)(args.Device.Name + " disconnected from client " + ButtplugClient.Name));
				ConnectedDevices.Remove(args.Device);
			}
		}

		private bool IsVibratableDevice(ButtplugClientDevice device)
		{
			return device.VibrateAttributes.Count > 0;
		}
	}
}
namespace Costura
{
	[CompilerGenerated]
	internal static class AssemblyLoader
	{
		private static object nullCacheLock = new object();

		private static Dictionary<string, bool> nullCache = new Dictionary<string, bool>();

		private static Dictionary<string, string> assemblyNames = new Dictionary<string, string>();

		private static Dictionary<string, string> symbolNames = new Dictionary<string, string>();

		private static int isAttached;

		private static string CultureToString(CultureInfo culture)
		{
			if (culture == null)
			{
				return "";
			}
			return culture.Name;
		}

		private static Assembly ReadExistingAssembly(AssemblyName name)
		{
			AppDomain currentDomain = AppDomain.CurrentDomain;
			Assembly[] assemblies = currentDomain.GetAssemblies();
			Assembly[] array = assemblies;
			foreach (Assembly assembly in array)
			{
				AssemblyName name2 = assembly.GetName();
				if (string.Equals(name2.Name, name.Name, StringComparison.InvariantCultureIgnoreCase) && string.Equals(CultureToString(name2.CultureInfo), CultureToString(name.CultureInfo), StringComparison.InvariantCultureIgnoreCase))
				{
					return assembly;
				}
			}
			return null;
		}

		private static void CopyTo(Stream source, Stream destination)
		{
			byte[] array = new byte[81920];
			int count;
			while ((count = source.Read(array, 0, array.Length)) != 0)
			{
				destination.Write(array, 0, count);
			}
		}

		private static Stream LoadStream(string fullName)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			if (fullName.EndsWith(".compressed"))
			{
				using (Stream stream = executingAssembly.GetManifestResourceStream(fullName))
				{
					using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress);
					MemoryStream memoryStream = new MemoryStream();
					CopyTo(source, memoryStream);
					memoryStream.Position = 0L;
					return memoryStream;
				}
			}
			return executingAssembly.GetManifestResourceStream(fullName);
		}

		private static Stream LoadStream(Dictionary<string, string> resourceNames, string name)
		{
			if (resourceNames.TryGetValue(name, out var value))
			{
				return LoadStream(value);
			}
			return null;
		}

		private static byte[] ReadStream(Stream stream)
		{
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			return array;
		}

		private static Assembly ReadFromEmbeddedResources(Dictionary<string, string> assemblyNames, Dictionary<string, string> symbolNames, AssemblyName requestedAssemblyName)
		{
			string text = requestedAssemblyName.Name.ToLowerInvariant();
			if (requestedAssemblyName.CultureInfo != null && !string.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name))
			{
				text = requestedAssemblyName.CultureInfo.Name + "." + text;
			}
			byte[] rawAssembly;
			using (Stream stream = LoadStream(assemblyNames, text))
			{
				if (stream == null)
				{
					return null;
				}
				rawAssembly = ReadStream(stream);
			}
			using (Stream stream2 = LoadStream(symbolNames, text))
			{
				if (stream2 != null)
				{
					byte[] rawSymbolStore = ReadStream(stream2);
					return Assembly.Load(rawAssembly, rawSymbolStore);
				}
			}
			return Assembly.Load(rawAssembly);
		}

		public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)
		{
			lock (nullCacheLock)
			{
				if (nullCache.ContainsKey(e.Name))
				{
					return null;
				}
			}
			AssemblyName assemblyName = new AssemblyName(e.Name);
			Assembly assembly = ReadExistingAssembly(assemblyName);
			if ((object)assembly != null)
			{
				return assembly;
			}
			assembly = ReadFromEmbeddedResources(assemblyNames, symbolNames, assemblyName);
			if ((object)assembly == null)
			{
				lock (nullCacheLock)
				{
					nullCache[e.Name] = true;
				}
				if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0)
				{
					assembly = Assembly.Load(assemblyName);
				}
			}
			return assembly;
		}

		static AssemblyLoader()
		{
			assemblyNames.Add("buttplug.client.connectors.websocketconnector", "costura.buttplug.client.connectors.websocketconnector.dll.compressed");
			assemblyNames.Add("buttplug", "costura.buttplug.dll.compressed");
			assemblyNames.Add("deniszykov.websocketlistener", "costura.deniszykov.websocketlistener.dll.compressed");
			assemblyNames.Add("system.appcontext", "costura.system.appcontext.dll.compressed");
			assemblyNames.Add("system.collections.concurrent", "costura.system.collections.concurrent.dll.compressed");
			assemblyNames.Add("system.collections", "costura.system.collections.dll.compressed");
			assemblyNames.Add("system.collections.nongeneric", "costura.system.collections.nongeneric.dll.compressed");
			assemblyNames.Add("system.collections.specialized", "costura.system.collections.specialized.dll.compressed");
			assemblyNames.Add("system.componentmodel.annotations", "costura.system.componentmodel.annotations.dll.compressed");
			assemblyNames.Add("system.componentmodel.composition", "costura.system.componentmodel.composition.dll.compressed");
			assemblyNames.Add("system.componentmodel", "costura.system.componentmodel.dll.compressed");
			assemblyNames.Add("system.componentmodel.eventbasedasync", "costura.system.componentmodel.eventbasedasync.dll.compressed");
			assemblyNames.Add("system.componentmodel.primitives", "costura.system.componentmodel.primitives.dll.compressed");
			assemblyNames.Add("system.componentmodel.typeconverter", "costura.system.componentmodel.typeconverter.dll.compressed");
			assemblyNames.Add("system.console", "costura.system.console.dll.compressed");
			assemblyNames.Add("system.core", "costura.system.core.dll.compressed");
			assemblyNames.Add("system.data.common", "costura.system.data.common.dll.compressed");
			assemblyNames.Add("system.data", "costura.system.data.dll.compressed");
			assemblyNames.Add("system.diagnostics.contracts", "costura.system.diagnostics.contracts.dll.compressed");
			assemblyNames.Add("system.diagnostics.debug", "costura.system.diagnostics.debug.dll.compressed");
			assemblyNames.Add("system.diagnostics.diagnosticsource", "costura.system.diagnostics.diagnosticsource.dll.compressed");
			assemblyNames.Add("system.diagnostics.fileversioninfo", "costura.system.diagnostics.fileversioninfo.dll.compressed");
			assemblyNames.Add("system.diagnostics.process", "costura.system.diagnostics.process.dll.compressed");
			assemblyNames.Add("system.diagnostics.stacktrace", "costura.system.diagnostics.stacktrace.dll.compressed");
			assemblyNames.Add("system.diagnostics.textwritertracelistener", "costura.system.diagnostics.textwritertracelistener.dll.compressed");
			assemblyNames.Add("system.diagnostics.tools", "costura.system.diagnostics.tools.dll.compressed");
			assemblyNames.Add("system.diagnostics.tracesource", "costura.system.diagnostics.tracesource.dll.compressed");
			assemblyNames.Add("system.diagnostics.tracing", "costura.system.diagnostics.tracing.dll.compressed");
			assemblyNames.Add("system.drawing", "costura.system.drawing.dll.compressed");
			assemblyNames.Add("system.drawing.primitives", "costura.system.drawing.primitives.dll.compressed");
			assemblyNames.Add("system.dynamic.runtime", "costura.system.dynamic.runtime.dll.compressed");
			assemblyNames.Add("system.globalization.calendars", "costura.system.globalization.calendars.dll.compressed");
			assemblyNames.Add("system.globalization", "costura.system.globalization.dll.compressed");
			assemblyNames.Add("system.globalization.extensions", "costura.system.globalization.extensions.dll.compressed");
			assemblyNames.Add("system.io.compression", "costura.system.io.compression.dll.compressed");
			assemblyNames.Add("system.io.compression.filesystem", "costura.system.io.compression.filesystem.dll.compressed");
			assemblyNames.Add("system.io.compression.zipfile", "costura.system.io.compression.zipfile.dll.compressed");
			assemblyNames.Add("system.io", "costura.system.io.dll.compressed");
			assemblyNames.Add("system.io.filesystem", "costura.system.io.filesystem.dll.compressed");
			assemblyNames.Add("system.io.filesystem.driveinfo", "costura.system.io.filesystem.driveinfo.dll.compressed");
			assemblyNames.Add("system.io.filesystem.primitives", "costura.system.io.filesystem.primitives.dll.compressed");
			assemblyNames.Add("system.io.filesystem.watcher", "costura.system.io.filesystem.watcher.dll.compressed");
			assemblyNames.Add("system.io.isolatedstorage", "costura.system.io.isolatedstorage.dll.compressed");
			assemblyNames.Add("system.io.memorymappedfiles", "costura.system.io.memorymappedfiles.dll.compressed");
			assemblyNames.Add("system.io.pipes", "costura.system.io.pipes.dll.compressed");
			assemblyNames.Add("system.io.unmanagedmemorystream", "costura.system.io.unmanagedmemorystream.dll.compressed");
			assemblyNames.Add("system.linq", "costura.system.linq.dll.compressed");
			assemblyNames.Add("system.linq.expressions", "costura.system.linq.expressions.dll.compressed");
			assemblyNames.Add("system.linq.parallel", "costura.system.linq.parallel.dll.compressed");
			assemblyNames.Add("system.linq.queryable", "costura.system.linq.queryable.dll.compressed");
			assemblyNames.Add("system.net.http", "costura.system.net.http.dll.compressed");
			assemblyNames.Add("system.net.nameresolution", "costura.system.net.nameresolution.dll.compressed");
			assemblyNames.Add("system.net.networkinformation", "costura.system.net.networkinformation.dll.compressed");
			assemblyNames.Add("system.net.ping", "costura.system.net.ping.dll.compressed");
			assemblyNames.Add("system.net.primitives", "costura.system.net.primitives.dll.compressed");
			assemblyNames.Add("system.net.requests", "costura.system.net.requests.dll.compressed");
			assemblyNames.Add("system.net.security", "costura.system.net.security.dll.compressed");
			assemblyNames.Add("system.net.sockets", "costura.system.net.sockets.dll.compressed");
			assemblyNames.Add("system.net.webheadercollection", "costura.system.net.webheadercollection.dll.compressed");
			assemblyNames.Add("system.net.websockets.client", "costura.system.net.websockets.client.dll.compressed");
			assemblyNames.Add("system.net.websockets", "costura.system.net.websockets.dll.compressed");
			assemblyNames.Add("system.numerics", "costura.system.numerics.dll.compressed");
			assemblyNames.Add("system.objectmodel", "costura.system.objectmodel.dll.compressed");
			assemblyNames.Add("system.reflection", "costura.system.reflection.dll.compressed");
			assemblyNames.Add("system.reflection.emit", "costura.system.reflection.emit.dll.compressed");
			assemblyNames.Add("system.reflection.emit.ilgeneration", "costura.system.reflection.emit.ilgeneration.dll.compressed");
			assemblyNames.Add("system.reflection.emit.lightweight", "costura.system.reflection.emit.lightweight.dll.compressed");
			assemblyNames.Add("system.reflection.extensions", "costura.system.reflection.extensions.dll.compressed");
			assemblyNames.Add("system.reflection.primitives", "costura.system.reflection.primitives.dll.compressed");
			assemblyNames.Add("system.resources.reader", "costura.system.resources.reader.dll.compressed");
			assemblyNames.Add("system.resources.resourcemanager", "costura.system.resources.resourcemanager.dll.compressed");
			assemblyNames.Add("system.resources.writer", "costura.system.resources.writer.dll.compressed");
			assemblyNames.Add("system.runtime.compilerservices.unsafe", "costura.system.runtime.compilerservices.unsafe.dll.compressed");
			assemblyNames.Add("system.runtime.compilerservices.visualc", "costura.system.runtime.compilerservices.visualc.dll.compressed");
			assemblyNames.Add("system.runtime", "costura.system.runtime.dll.compressed");
			assemblyNames.Add("system.runtime.extensions", "costura.system.runtime.extensions.dll.compressed");
			assemblyNames.Add("system.runtime.handles", "costura.system.runtime.handles.dll.compressed");
			assemblyNames.Add("system.runtime.interopservices", "costura.system.runtime.interopservices.dll.compressed");
			assemblyNames.Add("system.runtime.interopservices.runtimeinformation", "costura.system.runtime.interopservices.runtimeinformation.dll.compressed");
			assemblyNames.Add("system.runtime.interopservices.windowsruntime", "costura.system.runtime.interopservices.windowsruntime.dll.compressed");
			assemblyNames.Add("system.runtime.numerics", "costura.system.runtime.numerics.dll.compressed");
			assemblyNames.Add("system.runtime.serialization", "costura.system.runtime.serialization.dll.compressed");
			assemblyNames.Add("system.runtime.serialization.formatters", "costura.system.runtime.serialization.formatters.dll.compressed");
			assemblyNames.Add("system.runtime.serialization.json", "costura.system.runtime.serialization.json.dll.compressed");
			assemblyNames.Add("system.runtime.serialization.primitives", "costura.system.runtime.serialization.primitives.dll.compressed");
			assemblyNames.Add("system.runtime.serialization.xml", "costura.system.runtime.serialization.xml.dll.compressed");
			assemblyNames.Add("system.security.claims", "costura.system.security.claims.dll.compressed");
			assemblyNames.Add("system.security.cryptography.algorithms", "costura.system.security.cryptography.algorithms.dll.compressed");
			assemblyNames.Add("system.security.cryptography.csp", "costura.system.security.cryptography.csp.dll.compressed");
			assemblyNames.Add("system.security.cryptography.encoding", "costura.system.security.cryptography.encoding.dll.compressed");
			assemblyNames.Add("system.security.cryptography.primitives", "costura.system.security.cryptography.primitives.dll.compressed");
			assemblyNames.Add("system.security.cryptography.x509certificates", "costura.system.security.cryptography.x509certificates.dll.compressed");
			assemblyNames.Add("system.security.principal", "costura.system.security.principal.dll.compressed");
			assemblyNames.Add("system.security.securestring", "costura.system.security.securestring.dll.compressed");
			assemblyNames.Add("system.servicemodel.duplex", "costura.system.servicemodel.duplex.dll.compressed");
			assemblyNames.Add("system.servicemodel.http", "costura.system.servicemodel.http.dll.compressed");
			assemblyNames.Add("system.servicemodel.nettcp", "costura.system.servicemodel.nettcp.dll.compressed");
			assemblyNames.Add("system.servicemodel.primitives", "costura.system.servicemodel.primitives.dll.compressed");
			assemblyNames.Add("system.servicemodel.security", "costura.system.servicemodel.security.dll.compressed");
			assemblyNames.Add("system.text.encoding", "costura.system.text.encoding.dll.compressed");
			assemblyNames.Add("system.text.encoding.extensions", "costura.system.text.encoding.extensions.dll.compressed");
			assemblyNames.Add("system.text.regularexpressions", "costura.system.text.regularexpressions.dll.compressed");
			assemblyNames.Add("system.threading.channels", "costura.system.threading.channels.dll.compressed");
			assemblyNames.Add("system.threading", "costura.system.threading.dll.compressed");
			assemblyNames.Add("system.threading.overlapped", "costura.system.threading.overlapped.dll.compressed");
			assemblyNames.Add("system.threading.tasks", "costura.system.threading.tasks.dll.compressed");
			assemblyNames.Add("system.threading.tasks.extensions", "costura.system.threading.tasks.extensions.dll.compressed");
			assemblyNames.Add("system.threading.tasks.parallel", "costura.system.threading.tasks.parallel.dll.compressed");
			assemblyNames.Add("system.threading.thread", "costura.system.threading.thread.dll.compressed");
			assemblyNames.Add("system.threading.threadpool", "costura.system.threading.threadpool.dll.compressed");
			assemblyNames.Add("system.threading.timer", "costura.system.threading.timer.dll.compressed");
			assemblyNames.Add("system.valuetuple", "costura.system.valuetuple.dll.compressed");
			assemblyNames.Add("system.xml", "costura.system.xml.dll.compressed");
			assemblyNames.Add("system.xml.linq", "costura.system.xml.linq.dll.compressed");
			assemblyNames.Add("system.xml.readerwriter", "costura.system.xml.readerwriter.dll.compressed");
			assemblyNames.Add("system.xml.xdocument", "costura.system.xml.xdocument.dll.compressed");
			assemblyNames.Add("system.xml.xmldocument", "costura.system.xml.xmldocument.dll.compressed");
			assemblyNames.Add("system.xml.xmlserializer", "costura.system.xml.xmlserializer.dll.compressed");
			assemblyNames.Add("system.xml.xpath", "costura.system.xml.xpath.dll.compressed");
			assemblyNames.Add("system.xml.xpath.xdocument", "costura.system.xml.xpath.xdocument.dll.compressed");
		}

		public static void Attach()
		{
			if (Interlocked.Exchange(ref isAttached, 1) == 1)
			{
				return;
			}
			AppDomain currentDomain = AppDomain.CurrentDomain;
			currentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
			{
				lock (nullCacheLock)
				{
					if (nullCache.ContainsKey(e.Name))
					{
						return null;
					}
				}
				AssemblyName assemblyName = new AssemblyName(e.Name);
				Assembly assembly = ReadExistingAssembly(assemblyName);
				if ((object)assembly != null)
				{
					return assembly;
				}
				assembly = ReadFromEmbeddedResources(assemblyNames, symbolNames, assemblyName);
				if ((object)assembly == null)
				{
					lock (nullCacheLock)
					{
						nullCache[e.Name] = true;
					}
					if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0)
					{
						assembly = Assembly.Load(assemblyName);
					}
				}
				return assembly;
			};
		}
	}
}
internal class LethalVibrations_ProcessedByFody
{
	internal const string FodyVersion = "6.8.0.0";

	internal const string Costura = "5.7.0";
}