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 LaserControl v0.1.7
LaserControl.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Anubis.LC.LaserControlPlugin.Components; using Anubis.LC.LaserControlPlugin.Extensions; using Anubis.LC.LaserControlPlugin.Helpers; using Anubis.LC.LaserControlPlugin.ModNetwork; using Anubis.LC.LaserControlPlugin.Store; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalLib.Modules; using Microsoft.CodeAnalysis; using RuntimeNetcodeRPCValidator; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [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("Anubis")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.7.0")] [assembly: AssemblyInformationalVersion("0.1.7+5236b6321e8bc1314ca93755b29db981cbbb5f0c")] [assembly: AssemblyProduct("LaserControl")] [assembly: AssemblyTitle("LaserControl")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.7.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 Anubis.LC.LaserControlPlugin { [BepInPlugin("Anubis.LaserControl", "LaserControl", "0.1.7")] [BepInDependency("NicholaScott.BepInEx.RuntimeNetcodeRPCValidator", "0.2.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LaserControlPlugin : BaseUnityPlugin { private Harmony HarmonyInstance = new Harmony("Anubis.LaserControl"); public static LaserControlPlugin? Instance; private NetcodeValidator netcodeValidator; private void Awake() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { Instance = this; } netcodeValidator = new NetcodeValidator("Anubis.LaserControl"); netcodeValidator.PatchAll(); netcodeValidator.BindToPreExistingObjectByBehaviour<Networking, Terminal>(); LethalConfigHelper.SetLehalConfig(((BaseUnityPlugin)this).Config); LaserLogger.LogInfo("Anubis.LaserControl is loading...", overrideDebugConfiguration: true); LaserLogger.LogInfo("Installing patches", overrideDebugConfiguration: true); HarmonyInstance.PatchAll(typeof(LaserControlPlugin).Assembly); Object.DontDestroyOnLoad((Object)(object)this); LaserLogger.LogInfo("Plugin Anubis.LaserControl is loaded!", overrideDebugConfiguration: true); } } public static class PluginInfo { public const string PLUGIN_GUID = "LaserControl"; public const string PLUGIN_NAME = "LaserControl"; public const string PLUGIN_VERSION = "0.1.7"; } } namespace Anubis.LC.LaserControlPlugin.Store { public static class BuyableLaserPointer { private static readonly int Price = 50; private static readonly string Name = "Pointer"; private static readonly string Description = "To point laser to some direction"; public static Item LaserPointerItemInstance { get; private set; } public static void RegisterShopItem(GameObject spawnPrefab, int price = 50) { Item[] array = Resources.FindObjectsOfTypeAll<Item>(); Item[] array2 = Object.FindObjectsByType<Item>((FindObjectsInactive)1, (FindObjectsSortMode)1); List<Item> list = new List<Item>(array.Length + array2.Length); Item[] array3 = array; foreach (Item item2 in array3) { list.Add(item2); } Item[] array4 = array2; foreach (Item item2 in array4) { list.Add(item2); } List<Item> source = list; Item val = ((IEnumerable<Item>)source).FirstOrDefault((Func<Item, bool>)((Item item) => ((Object)item).name == "FlashLaserPointer")); if ((Object)(object)val != (Object)null && !Object.op_Implicit((Object)(object)LaserPointerItemInstance)) { Items.RegisterShopItem(CreateBuyableItem(val, spawnPrefab, price), (TerminalNode)null, (TerminalNode)null, CreateInfoNode(Name, Description), price); } } private static Item CreateBuyableItem(Item original, GameObject spawnPrefab, int price = 50) { Item val = Object.Instantiate<Item>(original); ((Object)val).name = "Buyable" + ((Object)original).name; val.isScrap = false; val.itemName = Name; val.creditsWorth = price; val.spawnPrefab = spawnPrefab; LaserPointerItemInstance = val; return val; } private static TerminalNode CreateInfoNode(string name, string description) { TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); val.clearPreviousText = true; ((Object)val).name = name + "InfoNode"; val.displayText = description + "\n\n"; return val; } } } namespace Anubis.LC.LaserControlPlugin.Patches { [HarmonyPatch(typeof(FlashlightItem))] public class FlashlightItemPatch { private static string LASER_PROP_NAME = "LaserPointer"; private static Turret? PrevUsedTurret; private static float counterOfUsage = 0f; private static float maxSeconds = 15f; private static InputAction leftAltAction; private static InputAction leftClickAction; private static InputAction rightClickAction; private static bool IsClickToShoot = false; private static bool IsRightBusy = false; private static bool IsLeftBusy = false; [HarmonyPatch("Start")] [HarmonyPostfix] private static void Start(FlashlightItem __instance) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown FlashlightItem __instance2 = __instance; if (!((Object)__instance2).name.Contains(LASER_PROP_NAME)) { return; } if (ModStaticHelper.IsThisModInstalled("FlipMods.ReservedFlashlightSlot")) { leftAltAction = new InputAction((string)null, (InputActionType)0, "<Keyboard>/leftAlt", (string)null, (string)null, (string)null); leftAltAction.canceled += delegate { OnAltKeyReleased(__instance2); }; leftAltAction.Enable(); } rightClickAction = new InputAction((string)null, (InputActionType)0, "<Mouse>/rightButton", (string)null, (string)null, (string)null); rightClickAction.canceled += delegate { OnRightClickReleased(__instance2); }; rightClickAction.Enable(); } [HarmonyPatch("ItemActivate")] [HarmonyPrefix] private static void ItemActivate(FlashlightItem __instance, bool used, bool buttonDown = true) { if (((Object)__instance).name.Contains(LASER_PROP_NAME)) { CreateAndSyncBeam(__instance); } } [HarmonyBefore(new string[] { "AdvancedCompany" })] [HarmonyPatch("SwitchFlashlight")] [HarmonyPostfix] private static void SwitchFlashlight(FlashlightItem __instance, bool on) { if (((Object)__instance).name.Contains(LASER_PROP_NAME) && ModStaticHelper.IsThisModInstalled("com.potatoepet.AdvancedCompany")) { CreateAndSyncBeam(__instance); } } [HarmonyPatch("Update")] [HarmonyPostfix] private static void Update(FlashlightItem __instance) { //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Invalid comparison between Unknown and I4 //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Invalid comparison between Unknown and I4 if (!((Object)__instance).name.Contains(LASER_PROP_NAME) || !Networking.Instance.GetConfigItemValueOfPlayer<bool>("IsPointerCanControlTurrets")) { return; } LaserPointerRaycast component = ((Component)__instance).GetComponent<LaserPointerRaycast>(); if (!Object.op_Implicit((Object)(object)component)) { return; } if (component.state) { LaserLogger.LogInfo("Pointer is working"); Turret nearestTurret = Networking.Instance.GetNearestTurret(); if ((Object)(object)nearestTurret == (Object)null) { return; } __instance.UseLaserPointerItemBatteries(nearestTurret); LaserLogger.LogInfo("Pointer is working and turret found"); if (Object.op_Implicit((Object)(object)PrevUsedTurret)) { Turret? prevUsedTurret = PrevUsedTurret; if (((prevUsedTurret != null) ? new ulong?(((NetworkBehaviour)prevUsedTurret).NetworkObjectId) : null) != ((NetworkBehaviour)nearestTurret).NetworkObjectId) { Turret? prevUsedTurret2 = PrevUsedTurret; if (prevUsedTurret2 == null || (int)prevUsedTurret2.turretMode > 0) { LaserLogger.LogInfo("Previous turret no longer in player control, stop firing (ON)"); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)PrevUsedTurret).NetworkObjectId, (TurretMode)0); } } } counterOfUsage += Time.deltaTime; if (counterOfUsage < maxSeconds) { if (!IsClickToShoot) { LaserLogger.LogInfo("Charging..."); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)nearestTurret).NetworkObjectId, (TurretMode)0); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)nearestTurret).NetworkObjectId, (TurretMode)1); } else { LaserLogger.LogInfo("Firing..."); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)nearestTurret).NetworkObjectId, (TurretMode)2); } Networking.Instance.TurnTowardsLaserBeamIfHasLOSServerRpc(((NetworkBehaviour)nearestTurret).NetworkObjectId, ((object)component).GetHashCode()); IsRightBusy = false; } else { __instance.SwitchFlashlight(false); nearestTurret.TurnOffAndOnTurret(); counterOfUsage = 0f; } PrevUsedTurret = nearestTurret; __instance.DestroyIfBatteryIsEmpty(nearestTurret); } else { LaserLogger.LogInfo("Laser pointer destroyed"); Object.Destroy((Object)(object)component); } if (!component.state && (Object)(object)PrevUsedTurret != (Object)null) { if ((int)PrevUsedTurret.turretMode > 0) { LaserLogger.LogInfo("Previous turret no longer in player control, stop firing (OFF)"); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)PrevUsedTurret).NetworkObjectId, (TurretMode)0); } __instance.DestroyIfBatteryIsEmpty(PrevUsedTurret); PrevUsedTurret = null; } } private static void OnRightClickReleased(FlashlightItem __instance) { if (Object.op_Implicit((Object)(object)__instance) && !IsRightBusy) { LaserPointerRaycast component = ((Component)__instance).GetComponent<LaserPointerRaycast>(); if (Object.op_Implicit((Object)(object)component) && component.state) { IsRightBusy = true; IsClickToShoot = !IsClickToShoot; } } } private static void OnLeftClickReleased(FlashlightItem __instance) { if (!IsLeftBusy) { IsLeftBusy = true; CreateAndSyncBeam(__instance); } } private static void OnAltKeyReleased(FlashlightItem __instance) { __instance.SwitchFlashlight(false); } private static void CreateAndSyncBeam(FlashlightItem __instance) { FlashlightItemExtensions.LaserPointerRaycastCurrentInstance = ((Component)__instance).GetComponent<LaserPointerRaycast>(); if ((Object)(object)FlashlightItemExtensions.LaserPointerRaycastCurrentInstance == (Object)null) { LaserLogger.LogInfo("Added LaserPointerRaycast to laser pointer"); ((Component)__instance).gameObject.AddComponent<LaserPointerRaycast>(); } if (Object.op_Implicit((Object)(object)FlashlightItemExtensions.LaserPointerRaycastCurrentInstance) && !FlashlightItemExtensions.LaserPointerRaycastCurrentInstance.state) { LaserLogger.LogInfo("Laser pointer destroyed"); Object.Destroy((Object)(object)FlashlightItemExtensions.LaserPointerRaycastCurrentInstance); IsClickToShoot = false; } Networking.Instance.SyncAllTurretsAndRaycastsServerRpc(); IsLeftBusy = false; } } [HarmonyPatch(typeof(HUDManager))] internal class HUDManagerPatch { [HarmonyPatch("ChangeControlTipMultiple")] [HarmonyPostfix] public static void ChangeControlTipMultiple(HUDManager __instance, string[] allLines, bool holdingItem = false, Item itemProperties = null) { if (__instance.controlTipLines == null || __instance.controlTipLines.Length == 0) { return; } for (int i = 0; i < __instance.controlTipLines.Length; i++) { LaserLogger.LogInfo(((TMP_Text)__instance.controlTipLines[i]).text ?? ""); if (((TMP_Text)__instance.controlTipLines[i]).text.Contains("Toggle turret shooting : [LMB]", StringComparison.OrdinalIgnoreCase)) { ((TMP_Text)__instance.controlTipLines[i]).text = "Toggle turret shooting : [RMB]"; } } } } [HarmonyPatch(typeof(Landmine))] public static class LandminePatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start(Landmine __instance) { LaserLogger.LogInfo("Added LaserPointerTargetLandmine to the landmine"); ((Component)__instance).gameObject.AddComponent<LaserPointerTargetLandmine>(); } } [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] public static void Awake(StartOfRound __instance) { Item val = StartOfRound.Instance.allItemsList?.itemsList?.FirstOrDefault((Func<Item, bool>)((Item itm) => Object.op_Implicit((Object)(object)itm.spawnPrefab) && ((Object)itm.spawnPrefab).name == "LaserPointer")); if ((Object)(object)val != (Object)null) { LaserLogger.LogInfo("Added LaserPointerRaycastTarget to bind turrets and/or landmines and laser pointer"); val.spawnPrefab.AddComponent<LaserPointerRaycastTarget>(); FlashlightItem component = val.spawnPrefab.gameObject.GetComponent<FlashlightItem>(); List<string> list = ((GrabbableObject)component).itemProperties.toolTips.ToList(); list.Add("Toggle turret shooting : [RMB]"); ((GrabbableObject)component).itemProperties.toolTips = list.ToArray(); LaserLogger.LogInfo("Added laser pointer to the ship's store"); try { BuyableLaserPointer.RegisterShopItem(val.spawnPrefab, Networking.Instance.GetConfigItemValueOfPlayer<int>("PointerLaserPrice")); } catch { BuyableLaserPointer.RegisterShopItem(val.spawnPrefab, LethalConfigHelper.PointerLaserPrice.Value); } } } } [HarmonyPatch(typeof(Turret))] public static class TurretPatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void Start(Turret __instance) { LaserLogger.LogInfo("Added LaserPointerTargetTurret to the turret"); ((Component)__instance).gameObject.AddComponent<LaserPointerTargetTurret>(); } } } namespace Anubis.LC.LaserControlPlugin.ModNetwork { internal class Networking : NetworkBehaviour { public static Networking Instance; private Turret[] currentTurrets = (Turret[])(object)new Turret[0]; private Dictionary<ulong, Turret> currentTurretsAsDict = new Dictionary<ulong, Turret>(); private LaserPointerRaycast[] currentLaserPointerRaycast = new LaserPointerRaycast[0]; private Dictionary<int, LaserPointerRaycast> currentLaserPointerRaycastAsDict = new Dictionary<int, LaserPointerRaycast>(); private readonly float maxDistance = 35f; private readonly float minDistance = 25f; private Dictionary<string, object> HostConfigurationForPlayers = new Dictionary<string, object>(); public T GetConfigItemValueOfPlayer<T>(string key) { if (!((NetworkBehaviour)this).IsHost && HostConfigurationForPlayers.TryGetValue(key, out object value)) { return (T)value; } if (((NetworkBehaviour)this).IsHost && LethalConfigHelper.HostConfigurationForPlayers.TryGetValue(key, out object value2)) { return (T)value2; } return default(T); } public Dictionary<int, LaserPointerRaycast> GetAllLaserPointerRaycastsAsDict() { return currentLaserPointerRaycastAsDict; } public Turret[] GetAllTurrets() { return currentTurrets; } public Dictionary<ulong, Turret> GetAllTurretsAsDict() { return currentTurretsAsDict; } private LaserPointerRaycast[] FindAllLaserPointerRaycasts() { LaserPointerRaycast[] array = Object.FindObjectsOfType<LaserPointerRaycast>(); if (array.Count() == 0) { return new LaserPointerRaycast[0]; } return array; } private Turret[] FindAllTurrets() { Turret[] array = Object.FindObjectsOfType<Turret>(); if (array.Count() == 0) { return (Turret[])(object)new Turret[0]; } return array; } public Turret GetNearestTurret() { Transform localPlayerTransform = ((Component)StartOfRound.Instance.localPlayerController).transform; Turret[] allTurrets = GetAllTurrets(); return (from turret in allTurrets where Vector3.Distance(((Component)turret).transform.position, localPlayerTransform.position) <= minDistance orderby Vector3.Distance(((Component)turret).transform.position, localPlayerTransform.position) select turret).FirstOrDefault(); } public Turret[] GetXNearestTurret(int x) { if (x <= 1) { return (Turret[])(object)new Turret[1] { GetNearestTurret() }; } Transform localPlayerTransform = ((Component)StartOfRound.Instance.localPlayerController).transform; Turret[] allTurrets = GetAllTurrets(); return (from turret in allTurrets where Vector3.Distance(((Component)turret).transform.position, localPlayerTransform.position) <= minDistance orderby Vector3.Distance(((Component)turret).transform.position, localPlayerTransform.position) select turret).Take(x).ToArray(); } [ServerRpc(RequireOwnership = false)] public void StopTurretFireVisualServerRpc(ulong networkObjectId) { StopTurretFireVisualClientRpc(networkObjectId); } [ClientRpc] public void StopTurretFireVisualClientRpc(ulong networkObjectId) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (GetAllTurretsAsDict().TryGetValue(networkObjectId, out Turret value) && (int)value.turretMode == 2) { value.hasLineOfSight = false; value.lostLOSTimer = 0f; value.mainAudio.Stop(); value.farAudio.Stop(); value.berserkAudio.Stop(); value.bulletCollisionAudio.Stop(); value.bulletParticles.Stop(true, (ParticleSystemStopBehavior)1); value.turretAnimator.SetInteger("TurretMode", 0); } } [ServerRpc(RequireOwnership = false)] public void SwitchTurretModeServerRpc(ulong networkObjectId, TurretMode turretMode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) if ((int)turretMode == 0) { StopTurretFireVisualServerRpc(networkObjectId); } SwitchTurretModeClientRpc(networkObjectId, turretMode); } [ClientRpc] public void SwitchTurretModeClientRpc(ulong networkObjectId, TurretMode turretMode) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected I4, but got Unknown if (GetAllTurretsAsDict().TryGetValue(networkObjectId, out Turret value)) { value.turretMode = turretMode; value.SwitchTurretMode((int)turretMode); value.SetToModeClientRpc((int)turretMode); } } [ServerRpc(RequireOwnership = false)] public void TurnTowardsLaserBeamIfHasLOSServerRpc(ulong networkObjectId, int laserPointerRaycastId) { TurnTowardsLaserBeamIfHasLOSClientRpc(networkObjectId, laserPointerRaycastId); } [ClientRpc] public void TurnTowardsLaserBeamIfHasLOSClientRpc(ulong networkObjectId, int laserPointerRaycastId) { if (GetAllTurretsAsDict().TryGetValue(networkObjectId, out Turret value) && GetAllLaserPointerRaycastsAsDict().TryGetValue(laserPointerRaycastId, out LaserPointerRaycast value2)) { value.TurnTowardsLaserBeamIfHasLOS(value2); } } [ServerRpc(RequireOwnership = false)] public void SyncAllTurretsAndRaycastsServerRpc() { SyncAllTurretsAndRaycastsClientRpc(); } [ClientRpc] public void SyncAllTurretsAndRaycastsClientRpc() { LaserLogger.LogInfo("Syncing turrets and laser pointers"); currentTurretsAsDict = (currentTurrets = FindAllTurrets()).ToDictionary((Turret t) => ((NetworkBehaviour)t).NetworkObjectId); currentLaserPointerRaycastAsDict = (currentLaserPointerRaycast = FindAllLaserPointerRaycasts()).ToDictionary((LaserPointerRaycast t) => ((object)t).GetHashCode()); } [ServerRpc] public void SyncHostConfigurationServerRpc() { if (((NetworkBehaviour)this).IsHost) { LaserLogger.LogInfo("Syncing host mod configuration for other players"); SyncHostConfigurationClientRpc("IsPointerBuyable", LethalConfigHelper.IsPointerBuyable.Value); SyncHostConfigurationClientRpc("IsPointerCanTurnOnAndOffTurrets", LethalConfigHelper.IsPointerCanTurnOnAndOffTurrets.Value); SyncHostConfigurationClientRpc("IsPointerCanControlTurrets", LethalConfigHelper.IsPointerCanControlTurrets.Value); SyncHostConfigurationClientRpc("IsPointerCanDetonateLandmines", LethalConfigHelper.IsPointerCanDetonateLandmines.Value); SyncHostConfigurationClientRpc("PointerLaserDrainSpeed", LethalConfigHelper.PointerLaserDrainSpeed.Value); SyncHostConfigurationClientRpc("PointerLaserPrice", LethalConfigHelper.PointerLaserPrice.Value); } } [ClientRpc] public void SyncHostConfigurationClientRpc(string key, object value) { LaserLogger.LogInfo($"Syncing host mod configuration for player (key: {key}, value: {value})"); HostConfigurationForPlayers.Remove(key); if (!HostConfigurationForPlayers.TryAdd(key, value)) { LaserLogger.LogWarning($"Error while syncing host mod configuration for player (key: {key}, value: {value})"); } if (key.Equals("IsPointerBuyable") && HostConfigurationForPlayers.TryGetValue("IsPointerBuyable", out object value2) && !(bool)value2) { LaserLogger.LogInfo("Laser pointer removed from the ship's store"); Items.RemoveShopItem(BuyableLaserPointer.LaserPointerItemInstance); } } [ServerRpc(RequireOwnership = false)] public void AskHostForSyncServerRpc() { LaserLogger.LogInfo("Asking host to sync configuration"); SyncHostConfigurationServerRpc(); } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; ((MonoBehaviour)this).StartCoroutine(WaitForSomeTime()); } } private IEnumerator WaitForSomeTime() { yield return (object)new WaitUntil((Func<bool>)(() => ((NetworkBehaviour)this).NetworkObject.IsSpawned)); SyncAllTurretsAndRaycastsServerRpc(); AskHostForSyncServerRpc(); } } } namespace Anubis.LC.LaserControlPlugin.Helpers { public static class LaserLogger { private static ManualLogSource Logger = Logger.CreateLogSource("Anubis.LaserControl"); internal static void Log(LogLevel level, object data, bool overrideDebugConfiguration = false) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (overrideDebugConfiguration) { Logger.Log(level, data); } else if ((int)level == 2 || LethalConfigHelper.IsDebug.Value) { Logger.Log(level, data); } } internal static void LogFatal(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)1, data, overrideDebugConfiguration); } internal static void LogError(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)2, data, overrideDebugConfiguration); } internal static void LogWarning(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)4, data, overrideDebugConfiguration); } internal static void LogMessage(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)8, data, overrideDebugConfiguration); } internal static void LogInfo(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)16, data, overrideDebugConfiguration); } internal static void LogDebug(object data, bool overrideDebugConfiguration = false) { Log((LogLevel)32, data, overrideDebugConfiguration); } } public static class LethalConfigHelper { public static Dictionary<string, object> HostConfigurationForPlayers = new Dictionary<string, object>(); public static ConfigEntry<bool> IsPointerBuyable; public static ConfigEntry<bool> IsPointerCanTurnOnAndOffTurrets; public static ConfigEntry<bool> IsPointerCanDetonateLandmines; public static ConfigEntry<bool> IsPointerCanControlTurrets; public static ConfigEntry<float> PointerLaserDrainSpeed; public static ConfigEntry<int> PointerLaserPrice; public static ConfigEntry<bool> IsDebug; public static void SetLehalConfig(ConfigFile config) { //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Expected O, but got Unknown //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Expected O, but got Unknown //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Expected O, but got Unknown //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Expected O, but got Unknown //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Expected O, but got Unknown //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Expected O, but got Unknown //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown IsDebug = config.Bind<bool>("Debug", "See all logs", true, "All logs will be throw to console"); IsPointerBuyable = config.Bind<bool>("General", "Pointer Laser Buyable?", true, "The pointer laser is buyable (no scrap worth)"); IsPointerBuyable.SettingChanged += delegate { HostConfigurationForPlayers.Remove("IsPointerBuyable"); HostConfigurationForPlayers.TryAdd("IsPointerBuyable", IsPointerBuyable.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; PointerLaserPrice = config.Bind<int>("General", "Laser Pointer Price", 50, "Determines laser pointer price"); PointerLaserPrice.SettingChanged += delegate { HostConfigurationForPlayers.Remove("PointerLaserPrice"); HostConfigurationForPlayers.TryAdd("PointerLaserPrice", PointerLaserPrice.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; IsPointerCanTurnOnAndOffTurrets = config.Bind<bool>("General", "Can Turn On/Off Turrets?", true, "The laser pointer can turn off and on turrets"); IsPointerCanTurnOnAndOffTurrets.SettingChanged += delegate { HostConfigurationForPlayers.Remove("IsPointerCanTurnOnAndOffTurrets"); HostConfigurationForPlayers.TryAdd("IsPointerCanTurnOnAndOffTurrets", IsPointerCanTurnOnAndOffTurrets.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; IsPointerCanDetonateLandmines = config.Bind<bool>("General", "Can Detonate Landmines?", true, "The laser pointer can detonate landmines"); IsPointerCanDetonateLandmines.SettingChanged += delegate { HostConfigurationForPlayers.Remove("IsPointerCanDetonateLandmines"); HostConfigurationForPlayers.TryAdd("IsPointerCanDetonateLandmines", IsPointerCanDetonateLandmines.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; IsPointerCanControlTurrets = config.Bind<bool>("General", "Can Control Turrets?", true, "The laser pointer can control turrets"); IsPointerCanControlTurrets.SettingChanged += delegate { HostConfigurationForPlayers.Remove("IsPointerCanControlTurrets"); HostConfigurationForPlayers.TryAdd("IsPointerCanControlTurrets", IsPointerCanControlTurrets.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; PointerLaserDrainSpeed = config.Bind<float>("General", "Laser Pointer Drain Speed", 35f, "Determines the batery drain speed"); PointerLaserDrainSpeed.SettingChanged += delegate { HostConfigurationForPlayers.Remove("PointerLaserDrainSpeed"); HostConfigurationForPlayers.TryAdd("PointerLaserDrainSpeed", PointerLaserDrainSpeed.Value); if ((Object)(object)Networking.Instance != (Object)null) { Networking.Instance.SyncHostConfigurationServerRpc(); } }; if (!HostConfigurationForPlayers.TryAdd("IsPointerBuyable", IsPointerBuyable.Value) || !HostConfigurationForPlayers.TryAdd("IsPointerCanTurnOnAndOffTurrets", IsPointerCanTurnOnAndOffTurrets.Value) || !HostConfigurationForPlayers.TryAdd("IsPointerCanControlTurrets", IsPointerCanControlTurrets.Value) || !HostConfigurationForPlayers.TryAdd("IsPointerCanDetonateLandmines", IsPointerCanDetonateLandmines.Value) || !HostConfigurationForPlayers.TryAdd("PointerLaserDrainSpeed", PointerLaserDrainSpeed.Value)) { LaserLogger.LogError("Could not add mod configuration to dictionary"); } LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(IsPointerBuyable, true)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(IsPointerCanTurnOnAndOffTurrets, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(IsPointerCanDetonateLandmines, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(IsPointerCanControlTurrets, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(IsDebug, false)); ConfigEntry<float> pointerLaserDrainSpeed = PointerLaserDrainSpeed; FloatSliderOptions val = new FloatSliderOptions(); ((BaseRangeOptions<float>)val).Min = 15f; ((BaseRangeOptions<float>)val).Max = 100f; ((BaseOptions)val).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(pointerLaserDrainSpeed, val)); ConfigEntry<int> pointerLaserPrice = PointerLaserPrice; IntSliderOptions val2 = new IntSliderOptions(); ((BaseRangeOptions<int>)val2).Min = 15; ((BaseRangeOptions<int>)val2).Max = 3000; ((BaseOptions)val2).RequiresRestart = true; LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(pointerLaserPrice, val2)); LethalConfigManager.SetModIcon(LoadNewSprite(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "icon.png"))); LethalConfigManager.SetModDescription("Binding the laser pointer to the turret. What bad things could happen?"); } private static Sprite LoadNewSprite(string filePath, float pixelsPerUnit = 100f) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) try { Texture2D val = LoadTexture(filePath); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0f, 0f), pixelsPerUnit); } catch { return null; } } private static Texture2D LoadTexture(string filePath) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (File.Exists(filePath)) { byte[] array = File.ReadAllBytes(filePath); Texture2D val = new Texture2D(2, 2); if (ImageConversion.LoadImage(val, array)) { return val; } } return null; } } public static class ModStaticHelper { public const string modGUID = "Anubis.LaserControl"; public const string modName = "LaserControl"; public const string modVersion = "0.1.7"; public static ManualLogSource Logger = Logger.CreateLogSource("Anubis.LaserControl"); public static bool IsThisModInstalled(string mod) { if (Chainloader.PluginInfos.TryGetValue(mod, out var _)) { Logger.LogInfo((object)("Mod " + mod + " is loaded alongside Anubis.LaserControl")); return true; } return false; } } } namespace Anubis.LC.LaserControlPlugin.Extensions { public static class FlashlightItemExtensions { public static LaserPointerRaycast LaserPointerRaycastCurrentInstance; public static void UseLaserPointerItemBatteries(this FlashlightItem flashlightItem, Turret? turret = null, float? reduceSpeed = null) { float num = (reduceSpeed.HasValue ? reduceSpeed.Value : Networking.Instance.GetConfigItemValueOfPlayer<float>("PointerLaserDrainSpeed")); Battery insertedBattery = ((GrabbableObject)flashlightItem).insertedBattery; insertedBattery.charge -= Time.deltaTime / num; flashlightItem.DestroyIfBatteryIsEmpty(turret); } public static IEnumerator DestroyIfBatteryIsEmpty(this FlashlightItem flashlightItem, Turret? turret = null) { if (((GrabbableObject)flashlightItem).insertedBattery.charge <= 0f) { if (Object.op_Implicit((Object)(object)LaserPointerRaycastCurrentInstance)) { Object.Destroy((Object)(object)LaserPointerRaycastCurrentInstance); } if (Object.op_Implicit((Object)(object)turret)) { LaserLogger.LogInfo("No battery to the laser pointer. Turning off turret"); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)turret).NetworkObjectId, (TurretMode)0); yield return turret.TurnOffAndOnTurret(); } yield return true; } yield return false; } } public static class TurretExtensions { private static readonly float beamDistance = 35f; private static Turret? PrevUsedTurret; public static IEnumerator TurnOffAndOnTurret(this Turret turret) { LaserLogger.LogWarning("-----------------"); LaserLogger.LogInfo("Turret Temp High -> OFF"); LaserLogger.LogWarning("-----------------"); Networking.Instance.SwitchTurretModeServerRpc(((NetworkBehaviour)turret).NetworkObjectId, (TurretMode)0); turret.ToggleTurretEnabled(false); yield return (object)new WaitForSeconds(3f); turret.ToggleTurretEnabled(true); LaserLogger.LogWarning("-----------------"); LaserLogger.LogInfo("Turret Temp Low -> ON"); LaserLogger.LogWarning("-----------------"); } private static Vector3 GetEndPositionOfBeam(Light light) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)light).transform.forward; Vector3 position = ((Component)light).transform.position; return position + forward * beamDistance; } public static void TurnTowardsLaserBeamIfHasLOS(this Turret turret, LaserPointerRaycast laserBeamObject) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)laserBeamObject == (Object)null) && !((Object)(object)laserBeamObject?.light == (Object)null)) { Vector3 endPositionOfBeam = GetEndPositionOfBeam(laserBeamObject.light); LaserLogger.LogInfo("Turret firing by player control"); turret.hasLineOfSight = true; turret.lostLOSTimer = 0f; turret.targetingDeadPlayer = false; turret.targetTransform = ((Component)laserBeamObject.light).transform; turret.tempTransform.position = endPositionOfBeam; turret.turnTowardsObjectCompass.LookAt(turret.tempTransform); } } } } namespace Anubis.LC.LaserControlPlugin.Components { public class LaserPointerRaycast : MonoBehaviour { private FlashlightItem? item; public Light light { get { if (!item.usingPlayerHelmetLight || !Object.op_Implicit((Object)(object)((GrabbableObject)item).playerHeldBy)) { return item.flashlightBulb; } return ((GrabbableObject)item).playerHeldBy.helmetLight; } } public bool state { get { if (((GrabbableObject)item).isBeingUsed) { return ((NetworkBehaviour)item).IsOwner && !item.usingPlayerHelmetLight; } return false; } } public void Awake() { item = ((Component)this).GetComponent<FlashlightItem>(); } } public class LaserPointerRaycastTarget : MonoBehaviour { private FlashlightItem? item; public Light light { get { if (!item.usingPlayerHelmetLight || !Object.op_Implicit((Object)(object)((GrabbableObject)item).playerHeldBy)) { return item.flashlightBulb; } return ((GrabbableObject)item).playerHeldBy.helmetLight; } } public bool state { get { if (((GrabbableObject)item).isBeingUsed) { return ((NetworkBehaviour)item).IsOwner && !item.usingPlayerHelmetLight; } return false; } } public void Awake() { item = ((Component)this).GetComponent<FlashlightItem>(); } public void Update() { if (!state || LaserPointerTarget.Count <= 0) { return; } foreach (LaserPointerTarget instance in LaserPointerTarget.Instances) { instance.Warmup(((Component)light).transform, item); } } } public interface ILaserPointerTarget { void Warmup(Transform origin, FlashlightItem laserPointer); } public abstract class LaserPointerTarget : MonoBehaviour, ILaserPointerTarget { public static List<ILaserPointerTarget> Instances = new List<ILaserPointerTarget>(); protected float tempCounter; protected bool triggered = false; protected Vector3 offset = Vector3.up * 0.1f; protected Vector3 hitPoint; public static int Count => Instances.Count; protected void Awake() { Instances.Add(this); } protected void OnDestroy() { Instances.Remove(this); } public abstract void Warmup(Transform origin, FlashlightItem laserPointer); protected bool HasCollision(Vector3 point, Vector3 direction, Vector3 center, float radius = 1f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Dot(center - point, Vector3.up) / Vector3.Dot(direction, Vector3.up); hitPoint = point + direction * num; if (num > 0f) { return Vector3.Distance(center, hitPoint) <= radius; } return false; } } public class LaserPointerTargetLandmine : LaserPointerTarget { private readonly float radius = 0.53f; private readonly float maxTemp = 1f; protected Landmine? target; protected new void Awake() { base.Awake(); target = ((Component)this).GetComponent<Landmine>(); } public override void Warmup(Transform origin, FlashlightItem laserPointer) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (Networking.Instance.GetConfigItemValueOfPlayer<bool>("IsPointerCanDetonateLandmines") && Object.op_Implicit((Object)(object)target) && !target.hasExploded && !triggered && HasCollision(origin.position, origin.forward, ((Component)this).transform.position + offset, radius) && !Physics.Linecast(origin.position, hitPoint, 1051400, (QueryTriggerInteraction)1)) { laserPointer.UseLaserPointerItemBatteries(); tempCounter += Time.deltaTime; if (tempCounter >= maxTemp) { LaserLogger.LogInfo("Landmine detonated"); target.TriggerMineOnLocalClientByExiting(); } } } } public class LaserPointerTargetTurret : LaserPointerTarget { private readonly float radius = 1f; private readonly float maxTemp = 0.4f; private bool IsStartedCorouting = false; protected Turret? target; protected new void Awake() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) base.Awake(); offset = Vector3.up * 0.2f; target = ((Component)this).GetComponent<Turret>(); } public override void Warmup(Transform origin, FlashlightItem laserPointer) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (Networking.Instance.GetConfigItemValueOfPlayer<bool>("IsPointerCanTurnOnAndOffTurrets") && Object.op_Implicit((Object)(object)target) && !triggered && HasCollision(origin.position, origin.forward, ((Component)this).transform.position + offset, radius) && !Physics.Linecast(origin.position, hitPoint, 1051400, (QueryTriggerInteraction)1)) { laserPointer.UseLaserPointerItemBatteries(target, 5f); tempCounter += Time.deltaTime; if (tempCounter >= maxTemp && !IsStartedCorouting) { ((MonoBehaviour)this).StartCoroutine(TurnOffAndOnTurret(target)); } } } private IEnumerator TurnOffAndOnTurret(Turret turret) { IsStartedCorouting = true; triggered = true; yield return turret.TurnOffAndOnTurret(); tempCounter = 0f; triggered = false; IsStartedCorouting = false; } } }