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 LethalShock v1.2.0
LethalShock/LethalShock.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Costura; using GameNetcodeStuff; using HarmonyLib; using LethalShock.Patches; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("LethalShock")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("PiShock integration")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1+f8c3f4bfa95eff76c57b83de7654e650ae2e55d7")] [assembly: AssemblyProduct("LethalShock")] [assembly: AssemblyTitle("LethalShock")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [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 LethalShock { public class PiShockApi { private string apiEndpoint = "https://do.pishock.com/api/apioperate/"; public string username { private get; set; } public string apiKey { private get; set; } public string code { private get; set; } public string senderName { private get; set; } public async Task Shock(int intensity, int duration) { HttpClient client = new HttpClient(); try { var requestData = new { Username = username, Name = senderName, Code = code, Intensity = intensity, Duration = duration, Apikey = apiKey, Op = 0 }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully."); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } public async Task Vibrate(int intensity, int duration) { HttpClient client = new HttpClient(); try { var requestData = new { Username = username, Name = senderName, Code = code, Intensity = intensity, Duration = duration, Apikey = apiKey, Op = 1 }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully."); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } public async Task Beep(int duration) { HttpClient client = new HttpClient(); try { var requestData = new { Username = username, Name = senderName, Code = code, Duration = duration, Apikey = apiKey, Op = 2 }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully."); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } } [BepInPlugin("LethalShock", "LethalShock", "1.1.1")] public class LethalShock : BaseUnityPlugin { internal enum ShockModes { FIRST, LAST, RANDOM, ROUND_ROBIN, RANDOM_ALL, ALL } private readonly Harmony harmony = new Harmony("LethalShock"); internal readonly string pishockLogId = "LethalShock (Lethal company)"; private readonly Random rnd = new Random(); internal static LethalShock instance; internal ManualLogSource mls; internal ConfigEntry<string> pishockUsername; internal ConfigEntry<string> pishockApiKey; internal ConfigEntry<string> pishockCodes; internal ConfigEntry<bool> shockOnDeath; internal ConfigEntry<bool> shockOnDamage; internal ConfigEntry<bool> vibrateOnly; internal ConfigEntry<bool> warningVibration; internal ConfigEntry<bool> shockBasedOnHealth; internal ConfigEntry<bool> shockOnFired; internal ConfigEntry<int> duration; internal ConfigEntry<int> maxIntensity; internal ConfigEntry<int> minIntensity; internal ConfigEntry<ShockModes> shockMode; internal ConfigEntry<int> durationDeath; internal ConfigEntry<int> intensityDeath; internal ConfigEntry<ShockModes> modeDeath; internal ConfigEntry<int> durationFired; internal ConfigEntry<int> intensityFired; internal ConfigEntry<ShockModes> modeFired; internal ConfigEntry<bool> enableInterval; internal ConfigEntry<int> interval; internal ConfigEntry<bool> xtoysEnabled; internal ConfigEntry<string> xtoysApiKey; internal DateTime lastShock; private bool DidDeath = false; private bool DidFired = false; private int roundRobin = 0; private void Awake() { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Expected O, but got Unknown mls = Logger.CreateLogSource("LethalShock"); mls.LogInfo((object)"LethalShock initiated"); pishockUsername = ((BaseUnityPlugin)this).Config.Bind<string>("LethalShock", "username", "", (ConfigDescription)null); pishockApiKey = ((BaseUnityPlugin)this).Config.Bind<string>("LethalShock", "apikey", "", (ConfigDescription)null); pishockCodes = ((BaseUnityPlugin)this).Config.Bind<string>("LethalShock", "codes", "code1,code2", (ConfigDescription)null); shockOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "shockOnDeath", true, "Enable to get shocked when you die"); shockOnDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "shockOnDamage", true, "Enable to get shocked when you take damage (Based on the damage value)"); vibrateOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "vibrateOnly", false, "Enable to only use vibrations"); warningVibration = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "warnning", true, "Enable to get a warning vibration before a shock"); shockBasedOnHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "shockByHealth", false, "Enable to calculate shock intensity based on your remaining health instead of the damage taken (shockOnDeath must be enabled)"); duration = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "duration", 1, "Duration of the shock/vibration"); maxIntensity = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "max", 80, new ConfigDescription("Maximum intensity of the shock/vibration", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); minIntensity = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "min", 1, new ConfigDescription("Minimum intensity of the shock/vibration", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); shockMode = ((BaseUnityPlugin)this).Config.Bind<ShockModes>("LethalShock", "mode", ShockModes.RANDOM, "What to do when you have multiple shockers?"); durationDeath = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "durationDeath", 5, "Duration of the shock/vibration when you die"); intensityDeath = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "intensityDeath", 100, "The intensity of the shock/vibration when you die"); modeDeath = ((BaseUnityPlugin)this).Config.Bind<ShockModes>("LethalShock", "modeDeath", ShockModes.ALL, "What to do when you have multiple shockers when you die"); durationFired = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "durationFired", 10, "Duration of the the shock/vibration when you get fired (gameover)"); intensityFired = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "intensityFired", 100, "Intensity of the shock/vibration when you get fired (gameover)"); modeFired = ((BaseUnityPlugin)this).Config.Bind<ShockModes>("LethalShock", "modeFired", ShockModes.ALL, "What to do when you have multiple shockers when you get fired (gameover)"); shockOnFired = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "shockOnFired", true, "Should you get shocked when fired?"); enableInterval = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "enableInterval", true, "Should there be a interval between damage shocks? (This makes bees and snear fleas bearable)"); interval = ((BaseUnityPlugin)this).Config.Bind<int>("LethalShock", "interval", 10, "Whats the interval between damage shocks?"); xtoysEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("LethalShock", "xtoysEnabled", false, "Use Xtoys instead of pishock? (Use XToys scripted located here: https://xtoys.app/scripts/lethalcompany"); xtoysApiKey = ((BaseUnityPlugin)this).Config.Bind<string>("LethalShock", "xtoysApiKey", "", "Apikey for Xtoys"); lastShock = DateTime.Now; harmony.PatchAll(typeof(LethalShock)); harmony.PatchAll(typeof(PlayerControllerBPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); if ((Object)(object)instance == (Object)null) { instance = this; } } internal void DoDamage(int dmg, int health) { TimeSpan timeSpan = DateTime.Now - lastShock; if (enableInterval.Value && timeSpan < TimeSpan.FromSeconds(interval.Value)) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Didn't shock due to interval. LastShock: " + lastShock.ToLongTimeString())); return; } int intensity = Mathf.Clamp(dmg, minIntensity.Value, maxIntensity.Value); int num = 100 - health; int intensity2 = Mathf.Clamp(num, minIntensity.Value, maxIntensity.Value); if (shockBasedOnHealth.Value) { mls.LogInfo((object)("Shocking based on health for " + intensity2)); DoOperation(intensity2, duration.Value, shockMode.Value); } else if (shockOnDamage.Value) { mls.LogInfo((object)("Shocking based on damage for " + intensity)); DoOperation(intensity, duration.Value, shockMode.Value); } lastShock = DateTime.Now; } internal void DoDeath() { if (!DidDeath && shockOnDeath.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Death shock"); DoOperation(intensityDeath.Value, durationDeath.Value, modeDeath.Value); DidDeath = true; Task.Run(async delegate { await Task.Delay(20000); DidDeath = false; }); } } internal void DoFired() { if (!DidFired) { mls.LogInfo((object)"Fired shock"); DoOperation(intensityFired.Value, durationFired.Value, modeFired.Value); DidFired = true; Task.Run(async delegate { await Task.Delay(durationFired.Value * 1000); DidFired = false; }); } } private async void DoOperation(int intensity, int duration, ShockModes mode) { string[] codes = pishockCodes.Value.Split(new char[1] { ',' }); bool[] picked = PickShockers(mode, codes.Length); if (!xtoysEnabled.Value) { for (int i = 0; i < codes.Length; i++) { mls.LogDebug((object)("Running DoOperation for shocker coded " + codes[i])); if (!picked[i]) { continue; } PiShockApi user = new PiShockApi { username = pishockUsername.Value, apiKey = pishockApiKey.Value, code = codes[i], senderName = pishockLogId }; if (vibrateOnly.Value || warningVibration.Value) { await user.Vibrate(intensity, duration); if (!vibrateOnly.Value) { mls.LogDebug((object)"Vibrating with delay"); await Task.Delay(duration + 1000); mls.LogDebug((object)"Shocking after delay"); await user.Shock(intensity, duration); } } else { await user.Shock(intensity, duration); } } return; } XToysApi xtoysApi = new XToysApi { apiKey = xtoysApiKey.Value }; if (vibrateOnly.Value || warningVibration.Value) { await xtoysApi.Vibrate(intensity, duration); if (!vibrateOnly.Value) { await Task.Delay(duration + 1000); await xtoysApi.Shock(intensity, duration); } } else { await xtoysApi.Shock(intensity, duration); } } public bool NextBoolean(Random random) { return random.Next() > 1073741823; } private bool[] PickShockers(ShockModes mode, int length) { bool[] array = new bool[length]; int num = rnd.Next(0, length); if (roundRobin >= length) { roundRobin = 0; } for (int i = 0; i < length; i++) { switch (mode) { case ShockModes.ALL: array[i] = true; break; case ShockModes.RANDOM_ALL: array[i] = NextBoolean(rnd); break; case ShockModes.RANDOM: array[i] = i == num; break; case ShockModes.FIRST: array[i] = i == 0; break; case ShockModes.LAST: array[i] = i == length - 1; break; case ShockModes.ROUND_ROBIN: array[i] = i == roundRobin; break; } } roundRobin++; if (mode == ShockModes.RANDOM_ALL) { bool flag = false; bool[] array2 = array; for (int j = 0; j < array2.Length; j++) { if (array2[j]) { flag = true; break; } } if (!flag) { array[num] = true; } } return array; } } public class XToysApi { private string apiEndpoint = "https://webhook.xtoys.app/"; public string apiKey { private get; set; } public async Task Shock(int intensity, int duration) { HttpClient client = new HttpClient(); try { var requestData = new { intensity = intensity, duration = duration, action = "shock" }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint + apiKey, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully. (XToys)"); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } public async Task Vibrate(int intensity, int duration) { HttpClient client = new HttpClient(); try { var requestData = new { intensity = intensity, duration = duration, action = "vibrate" }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint + apiKey, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully. (XToys)"); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } public async Task Beep(int duration, int intensity) { HttpClient client = new HttpClient(); try { var requestData = new { duration = duration, intensity = intensity, action = "beep" }; string jsonBody = JsonConvert.SerializeObject((object)requestData); HttpContent content = (HttpContent)new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { HttpResponseMessage response = await client.PostAsync(apiEndpoint + apiKey, content); if (response.IsSuccessStatusCode) { Console.WriteLine("Request sent successfully."); return; } Console.WriteLine($"Error: {response.StatusCode} - {response.ReasonPhrase}"); Console.WriteLine("Response Content: " + await response.Content.ReadAsStringAsync()); } finally { ((IDisposable)content)?.Dispose(); } } finally { ((IDisposable)client)?.Dispose(); } } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalShock"; public const string PLUGIN_NAME = "LethalShock"; public const string PLUGIN_VERSION = "1.1.1"; } } namespace LethalShock.Patches { internal class PlayerControllerBPatch { [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void DeathPatch(PlayerControllerB __instance) { if (((NetworkBehaviour)__instance).IsOwner) { LethalShock.instance.DoDeath(); } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void DamagePatch(int ___health, int damageNumber) { LethalShock.instance.DoDamage(damageNumber, ___health); } } internal class StartOfRoundPatch { [HarmonyPatch(typeof(StartOfRound), "FirePlayersAfterDeadlineClientRpc")] [HarmonyPostfix] private static void FirePlayersAfterDeadlinePatch() { LethalShock.instance.DoFired(); } } } 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("costura", "costura.costura.dll.compressed"); symbolNames.Add("costura", "costura.costura.pdb.compressed"); assemblyNames.Add("newtonsoft.json", "costura.newtonsoft.json.dll.compressed"); assemblyNames.Add("system.diagnostics.diagnosticsource", "costura.system.diagnostics.diagnosticsource.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 LethalShock_ProcessedByFody { internal const string FodyVersion = "6.8.0.0"; internal const string Costura = "5.7.0"; }