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 LampToggle v1.0.0
plugins/LampToggle/LampToggle.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LampToggle")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LampToggle")] [assembly: AssemblyTitle("LampToggle")] [assembly: AssemblyVersion("1.0.0.0")] 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; } } } namespace LampToggle { [BepInPlugin("lc.lamptoggle", "LampToggle", "2.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "lc.lamptoggle"; public const string PLUGIN_NAME = "LampToggle"; public const string PLUGIN_VERSION = "2.0.1"; internal static ManualLogSource Log; internal static Plugin Instance; internal static InputActions Actions; private Harmony _harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Actions = new InputActions(); _harmony = new Harmony("lc.lamptoggle"); _harmony.PatchAll(); Log.LogInfo((object)"LampToggle v2.0.1 loaded."); } } public class InputActions : LcInputActions { [InputAction("<Keyboard>/f", Name = "Toggle Last Light")] public InputAction ToggleLightKey { get; set; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerControllerBPatch { private enum LightKind { None, Handlamp, VanillaFlashlight } private struct LightSearchResult { public GrabbableObject? Item; public int SlotIndex; public bool IsCurrentlyHeld; public LightKind Kind; } private static int _lastLightSlot = -1; private static string? _lastLightTypeName; private static string? _lastLightItemName; private static LightKind _lastLightKind = LightKind.None; [HarmonyPatch("Update")] [HarmonyPostfix] private static void OnUpdate(PlayerControllerB __instance) { try { if (!ShouldHandleInput(__instance)) { return; } RememberCurrentlyHeldLight(__instance); MaintainHeldLightState(__instance); MaintainPocketLightBatteryState(__instance); if (Plugin.Actions.ToggleLightKey.WasPressedThisFrame()) { LightSearchResult result = ResolveTargetLight(__instance); if (!((Object)(object)result.Item == (Object)null)) { ToggleResolvedLight(__instance, result); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"Error in PlayerControllerBPatch.OnUpdate: {arg}"); } } private static bool ShouldHandleInput(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (!((NetworkBehaviour)player).IsOwner) { return false; } if (!player.isPlayerControlled) { return false; } if (player.inTerminalMenu) { return false; } if (player.isTypingChat) { return false; } if (player.isTestingPlayer) { return false; } return true; } private static void RememberCurrentlyHeldLight(PlayerControllerB player) { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return; } int currentItemSlot = player.currentItemSlot; if (currentItemSlot < 0 || currentItemSlot >= player.ItemSlots.Length) { return; } GrabbableObject val = player.ItemSlots[currentItemSlot]; if (!((Object)(object)val == (Object)null)) { LightKind lightKind = GetLightKind(val); if (lightKind != 0) { _lastLightSlot = currentItemSlot; _lastLightKind = lightKind; _lastLightTypeName = ((object)val).GetType().FullName ?? ((object)val).GetType().Name; _lastLightItemName = (((Object)(object)val.itemProperties != (Object)null) ? val.itemProperties.itemName : null); } } } private static void MaintainHeldLightState(PlayerControllerB player) { try { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return; } int currentItemSlot = player.currentItemSlot; if (currentItemSlot < 0 || currentItemSlot >= player.ItemSlots.Length) { return; } GrabbableObject val = player.ItemSlots[currentItemSlot]; if ((Object)(object)val == (Object)null) { return; } LightKind lightKind = GetLightKind(val); if (lightKind != 0) { bool boolFieldOrProperty = GetBoolFieldOrProperty(val, "isBeingUsed"); if (lightKind == LightKind.Handlamp) { MaintainHeldHandlampState(val, boolFieldOrProperty); } else if (lightKind == LightKind.VanillaFlashlight && boolFieldOrProperty) { SyncPlayerHelmetLight(player, enabled: true, val); } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"MaintainHeldLightState failed: {arg}"); } } private static void MaintainPocketLightBatteryState(PlayerControllerB player) { try { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return; } for (int i = 0; i < player.ItemSlots.Length; i++) { if (i == player.currentItemSlot) { continue; } GrabbableObject val = player.ItemSlots[i]; if ((Object)(object)val == (Object)null) { continue; } LightKind lightKind = GetLightKind(val); if (lightKind != 0 && GetBoolFieldOrProperty(val, "isBeingUsed") && !CanTurnOnLight(val)) { switch (lightKind) { case LightKind.Handlamp: ForcePocketHandlampState(val, enabled: false); break; case LightKind.VanillaFlashlight: SetBoolFieldOrProperty(val, "isBeingUsed", value: false); SyncPlayerHelmetLight(player, enabled: false, val); break; } } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"MaintainPocketLightBatteryState failed: {arg}"); } } private static void MaintainHeldHandlampState(GrabbableObject item, bool enabled) { try { TryInvokeNoArgMethod(item, "InitializeComponents"); SetBoolFieldOrProperty(item, "isBeingUsed", enabled); SetBoolFieldOrProperty(item, "previouslightstate", enabled); SetNamedLightEnabled(item, "pocketLight", enabled); SetNamedLightEnabled(item, "helmetLight", enabled); if (enabled) { EnableAllChildLights(item); } else { DisableAllChildLights(item); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"MaintainHeldHandlampState failed: {arg}"); } } private static LightSearchResult ResolveTargetLight(PlayerControllerB player) { LightSearchResult result = FindHeldLight(player); if ((Object)(object)result.Item != (Object)null) { UpdateLastTrackedLight(result); return result; } LightSearchResult result2 = FindRememberedLight(player); if ((Object)(object)result2.Item != (Object)null) { return result2; } LightSearchResult result3 = FindFirstSupportedLight(player); if ((Object)(object)result3.Item != (Object)null) { UpdateLastTrackedLight(result3); return result3; } return EmptyResult(); } private static LightSearchResult FindHeldLight(PlayerControllerB player) { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return EmptyResult(); } int currentItemSlot = player.currentItemSlot; if (currentItemSlot < 0 || currentItemSlot >= player.ItemSlots.Length) { return EmptyResult(); } GrabbableObject val = player.ItemSlots[currentItemSlot]; if ((Object)(object)val == (Object)null) { return EmptyResult(); } LightKind lightKind = GetLightKind(val); if (lightKind == LightKind.None) { return EmptyResult(); } return BuildResult(val, currentItemSlot, isHeld: true, lightKind); } private static LightSearchResult FindRememberedLight(PlayerControllerB player) { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return EmptyResult(); } if (_lastLightSlot < 0 || _lastLightSlot >= player.ItemSlots.Length) { return EmptyResult(); } GrabbableObject val = player.ItemSlots[_lastLightSlot]; if ((Object)(object)val == (Object)null) { return EmptyResult(); } LightKind lightKind = GetLightKind(val); if (lightKind == LightKind.None) { return EmptyResult(); } string? a = ((object)val).GetType().FullName ?? ((object)val).GetType().Name; string a2 = (((Object)(object)val.itemProperties != (Object)null) ? val.itemProperties.itemName : null); if (!string.Equals(a, _lastLightTypeName, StringComparison.Ordinal) || !string.Equals(a2, _lastLightItemName, StringComparison.Ordinal) || lightKind != _lastLightKind) { return EmptyResult(); } return BuildResult(val, _lastLightSlot, player.currentItemSlot == _lastLightSlot, lightKind); } private static LightSearchResult FindFirstSupportedLight(PlayerControllerB player) { if (player.ItemSlots == null || player.ItemSlots.Length == 0) { return EmptyResult(); } for (int i = 0; i < player.ItemSlots.Length; i++) { GrabbableObject val = player.ItemSlots[i]; if (!((Object)(object)val == (Object)null)) { LightKind lightKind = GetLightKind(val); if (lightKind != 0) { return BuildResult(val, i, player.currentItemSlot == i, lightKind); } } } return EmptyResult(); } private static LightSearchResult BuildResult(GrabbableObject item, int slotIndex, bool isHeld, LightKind kind) { LightSearchResult result = default(LightSearchResult); result.Item = item; result.SlotIndex = slotIndex; result.IsCurrentlyHeld = isHeld; result.Kind = kind; return result; } private static LightSearchResult EmptyResult() { LightSearchResult result = default(LightSearchResult); result.Item = null; result.SlotIndex = -1; result.IsCurrentlyHeld = false; result.Kind = LightKind.None; return result; } private static void UpdateLastTrackedLight(LightSearchResult result) { if (!((Object)(object)result.Item == (Object)null)) { _lastLightSlot = result.SlotIndex; _lastLightKind = result.Kind; _lastLightTypeName = ((object)result.Item).GetType().FullName ?? ((object)result.Item).GetType().Name; _lastLightItemName = (((Object)(object)result.Item.itemProperties != (Object)null) ? result.Item.itemProperties.itemName : null); } } private static LightKind GetLightKind(GrabbableObject item) { Type type = ((object)item).GetType(); string text = type.FullName ?? type.Name; string text2 = (((Object)(object)item.itemProperties != (Object)null) ? item.itemProperties.itemName : null); if (text == "UsualScrap.Behaviors.HandlampScript") { return LightKind.Handlamp; } if (text == "FlashlightItem") { return LightKind.VanillaFlashlight; } if (!string.IsNullOrEmpty(text2)) { if (text2.IndexOf("handlamp", StringComparison.OrdinalIgnoreCase) >= 0) { return LightKind.Handlamp; } if (string.Equals(text2, "Flashlight", StringComparison.OrdinalIgnoreCase)) { return LightKind.VanillaFlashlight; } if (string.Equals(text2, "Pro-flashlight", StringComparison.OrdinalIgnoreCase)) { return LightKind.VanillaFlashlight; } if (string.Equals(text2, "Pro flashlight", StringComparison.OrdinalIgnoreCase)) { return LightKind.VanillaFlashlight; } if (string.Equals(text2, "Golden flashlight", StringComparison.OrdinalIgnoreCase)) { return LightKind.VanillaFlashlight; } if (text2.IndexOf("flashlight", StringComparison.OrdinalIgnoreCase) >= 0) { return LightKind.VanillaFlashlight; } } return LightKind.None; } private static void ToggleResolvedLight(PlayerControllerB player, LightSearchResult result) { if ((Object)(object)result.Item == (Object)null) { return; } bool flag = !GetBoolFieldOrProperty(result.Item, "isBeingUsed"); if (!flag || CanTurnOnLight(result.Item)) { switch (result.Kind) { case LightKind.Handlamp: ToggleHandlamp(result, flag); break; case LightKind.VanillaFlashlight: ToggleVanillaFlashlight(player, result, flag); break; } UpdateLastTrackedLight(result); } } private static void ToggleHandlamp(LightSearchResult result, bool targetState) { if ((Object)(object)result.Item == (Object)null) { return; } if (result.IsCurrentlyHeld) { if (!targetState || CanTurnOnLight(result.Item)) { if (TryInvokeItemActivate(result.Item, targetState)) { SyncHeldHandlampStateAfterSuccessfulToggle(result.Item, targetState); } else { Plugin.Log.LogWarning((object)"Held Handlamp: ItemActivate failed."); } } } else { ForcePocketHandlampState(result.Item, targetState); } } private static void ToggleVanillaFlashlight(PlayerControllerB player, LightSearchResult result, bool targetState) { if ((Object)(object)result.Item == (Object)null) { return; } if (result.IsCurrentlyHeld) { if (!targetState || CanTurnOnLight(result.Item)) { if (TryInvokeItemActivate(result.Item, targetState)) { SetBoolFieldOrProperty(result.Item, "isBeingUsed", targetState); SyncPlayerHelmetLight(player, targetState, result.Item); } else { Plugin.Log.LogWarning((object)"Held vanilla flashlight: ItemActivate failed."); } } } else { TryTogglePocketFlashlightRpc(player, targetState); SetBoolFieldOrProperty(result.Item, "isBeingUsed", targetState); SyncPlayerHelmetLight(player, targetState, result.Item); PlayPocketVanillaFlashlightToggleSound(result.Item, targetState); } } private static bool CanTurnOnLight(GrabbableObject item) { try { if (!GetBoolFieldOrProperty(GetFieldOrPropertyObject(item, "itemProperties"), "requiresBattery")) { return true; } object fieldOrPropertyObject = GetFieldOrPropertyObject(item, "insertedBattery"); if (fieldOrPropertyObject == null) { return false; } return GetFloatFieldOrProperty(fieldOrPropertyObject, "charge") > 0.0001f; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"CanTurnOnLight failed: {arg}"); return true; } } private static void SyncHeldHandlampStateAfterSuccessfulToggle(GrabbableObject item, bool state) { try { TryInvokeNoArgMethod(item, "InitializeComponents"); SetBoolFieldOrProperty(item, "isBeingUsed", state); SetBoolFieldOrProperty(item, "previouslightstate", state); SetNamedLightEnabled(item, "pocketLight", state); SetNamedLightEnabled(item, "helmetLight", state); if (state) { EnableAllChildLights(item); } else { DisableAllChildLights(item); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"SyncHeldHandlampStateAfterSuccessfulToggle failed: {arg}"); } } private static void ForcePocketHandlampState(GrabbableObject item, bool enabled) { try { TryInvokeNoArgMethod(item, "InitializeComponents"); SetBoolFieldOrProperty(item, "isBeingUsed", enabled); SetBoolFieldOrProperty(item, "previouslightstate", enabled); if (enabled) { ApplyPocketHandlampEnable(item); } else { ApplyPocketHandlampDisable(item); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"ForcePocketHandlampState failed: {arg}"); } } private static void ApplyPocketHandlampEnable(GrabbableObject item) { if (TryInvokeFlexibleBoolMethod(item, "ToggleLights", value: true)) { SetNamedLightEnabled(item, "pocketLight", enabled: true); SetNamedLightEnabled(item, "helmetLight", enabled: true); DisableHandlampHeldOnlyLightsIfPocketLightsExist(item); return; } if (TryInvokeNoArgMethod(item, "ToggleLights")) { SetNamedLightEnabled(item, "pocketLight", enabled: true); SetNamedLightEnabled(item, "helmetLight", enabled: true); DisableHandlampHeldOnlyLightsIfPocketLightsExist(item); return; } SetNamedLightEnabled(item, "pocketLight", enabled: true); SetNamedLightEnabled(item, "helmetLight", enabled: true); TryInvokeFlexibleBoolMethod(item, "ToggleStateClientRpc", value: true); TryInvokeFlexibleBoolMethod(item, "ToggleStateServerRpc", value: true); TryInvokeFlexibleBoolMethod(item, "ToggleCoroutineServerRpc", value: true); TryInvokeFlexibleBoolMethod(item, "ToggleCoroutine", value: true); TryInvokeFlexibleBoolMethod(item, "ToggleState", value: true); DisableHandlampHeldOnlyLightsIfPocketLightsExist(item); } private static void ApplyPocketHandlampDisable(GrabbableObject item) { if (!TryInvokeFlexibleBoolMethod(item, "ToggleLights", value: false)) { TryInvokeNoArgMethod(item, "ToggleLights"); } SetNamedLightEnabled(item, "pocketLight", enabled: false); SetNamedLightEnabled(item, "helmetLight", enabled: false); TryInvokeFlexibleBoolMethod(item, "ToggleStateClientRpc", value: false); TryInvokeFlexibleBoolMethod(item, "ToggleStateServerRpc", value: false); TryInvokeFlexibleBoolMethod(item, "ToggleCoroutineServerRpc", value: false); TryInvokeFlexibleBoolMethod(item, "ToggleCoroutine", value: false); TryInvokeFlexibleBoolMethod(item, "ToggleState", value: false); DisableAllChildLights(item); } private static void DisableHandlampHeldOnlyLightsIfPocketLightsExist(GrabbableObject item) { try { object? fieldOrPropertyObject = GetFieldOrPropertyObject(item, "pocketLight"); Light val = (Light)((fieldOrPropertyObject is Light) ? fieldOrPropertyObject : null); object? fieldOrPropertyObject2 = GetFieldOrPropertyObject(item, "helmetLight"); Light val2 = (Light)((fieldOrPropertyObject2 is Light) ? fieldOrPropertyObject2 : null); if (!((Object)(object)val != (Object)null) && !((Object)(object)val2 != (Object)null)) { return; } Light[] componentsInChildren = ((Component)item).GetComponentsInChildren<Light>(true); foreach (Light val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && val3 != val && val3 != val2) { ((Behaviour)val3).enabled = false; } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"DisableHandlampHeldOnlyLightsIfPocketLightsExist failed: {arg}"); } } private static void EnableAllChildLights(GrabbableObject item) { try { Light[] componentsInChildren = ((Component)item).GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = true; } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"EnableAllChildLights failed: {arg}"); } } private static bool TryTogglePocketFlashlightRpc(PlayerControllerB player, bool enabled) { try { MethodInfo[] array = (from m in typeof(PlayerControllerB).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "PocketFlashlightServerRpc" select m).ToArray(); foreach (MethodInfo methodInfo in array) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(bool)) { methodInfo.Invoke(player, new object[1] { enabled }); return true; } if (parameters.Length == 0) { methodInfo.Invoke(player, Array.Empty<object>()); return true; } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"TryTogglePocketFlashlightRpc failed: {arg}"); } return false; } private static void SyncPlayerHelmetLight(PlayerControllerB player, bool enabled, GrabbableObject sourceItem) { try { SetBoolFieldOrProperty(player, "pocketedFlashlight", enabled); SetBoolFieldOrProperty(player, "usingPlayerHelmetLight", enabled); object? fieldOrPropertyObject = GetFieldOrPropertyObject(player, "helmetLight"); Light val = (Light)((fieldOrPropertyObject is Light) ? fieldOrPropertyObject : null); if (!((Object)(object)val == (Object)null)) { if (enabled) { CopyBestFlashlightLightToHelmetLight(sourceItem, val); } ((Behaviour)val).enabled = enabled; if (((Component)val).gameObject.activeSelf != enabled) { ((Component)val).gameObject.SetActive(enabled); } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"SyncPlayerHelmetLight failed: {arg}"); } } private static void CopyBestFlashlightLightToHelmetLight(GrabbableObject sourceItem, Light helmetLight) { try { Light val = FindBestSourceLightFromItem(sourceItem); if (!((Object)(object)val == (Object)null)) { CopyLightSettings(val, helmetLight); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"CopyBestFlashlightLightToHelmetLight failed: {arg}"); } } private static Light? FindBestSourceLightFromItem(GrabbableObject item) { try { string[] array = new string[7] { "flashlightBulb", "flashlightLight", "bulbLight", "mainLight", "spotLight", "flashlightSpot", "flashlightBeam" }; foreach (string name in array) { object? fieldOrPropertyObject = GetFieldOrPropertyObject(item, name); Light val = (Light)((fieldOrPropertyObject is Light) ? fieldOrPropertyObject : null); if ((Object)(object)val != (Object)null) { return val; } } Light[] componentsInChildren = ((Component)item).GetComponentsInChildren<Light>(true); if (componentsInChildren.Length == 0) { return null; } Light val2 = componentsInChildren.Where((Light l) => (Object)(object)l != (Object)null && (int)l.type == 0).OrderByDescending(GetLightScore).FirstOrDefault(); if ((Object)(object)val2 != (Object)null) { return val2; } return componentsInChildren.Where((Light l) => (Object)(object)l != (Object)null).OrderByDescending(GetLightScore).FirstOrDefault(); } catch (Exception arg) { Plugin.Log.LogWarning((object)$"FindBestSourceLightFromItem failed: {arg}"); return null; } } private static float GetLightScore(Light light) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) float num = 0f; num += light.intensity * 10f; num += light.range; num += light.spotAngle * 0.25f; if ((int)light.type == 0) { num += 1000f; } return num; } private static void CopyLightSettings(Light source, Light destination) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) destination.type = source.type; destination.color = source.color; destination.colorTemperature = source.colorTemperature; destination.useColorTemperature = source.useColorTemperature; destination.intensity = source.intensity; destination.range = source.range; destination.spotAngle = source.spotAngle; destination.innerSpotAngle = source.innerSpotAngle; destination.shadows = source.shadows; destination.shadowStrength = source.shadowStrength; destination.shadowBias = source.shadowBias; destination.shadowNormalBias = source.shadowNormalBias; destination.shadowNearPlane = source.shadowNearPlane; destination.cookie = source.cookie; destination.cookieSize = source.cookieSize; destination.renderMode = source.renderMode; destination.cullingMask = source.cullingMask; destination.bounceIntensity = source.bounceIntensity; destination.lightShadowCasterMode = source.lightShadowCasterMode; try { destination.shape = source.shape; } catch { } } private static void PlayPocketVanillaFlashlightToggleSound(GrabbableObject item, bool enabled) { try { AudioSource val = FindBestAudioSource(item); if (!((Object)(object)val == (Object)null)) { AudioClip val2 = FindBestVanillaFlashlightToggleClip(item, val, enabled); if ((Object)(object)val2 != (Object)null) { val.PlayOneShot(val2); } else if ((Object)(object)val.clip != (Object)null) { val.Play(); } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"PlayPocketVanillaFlashlightToggleSound failed: {arg}"); } } private static AudioSource? FindBestAudioSource(GrabbableObject item) { string[] array = new string[5] { "flashlightAudio", "flashLightAudio", "itemAudio", "audioSource", "thisAudio" }; foreach (string name in array) { object? fieldOrPropertyObject = GetFieldOrPropertyObject(item, name); AudioSource val = (AudioSource)((fieldOrPropertyObject is AudioSource) ? fieldOrPropertyObject : null); if ((Object)(object)val != (Object)null) { return val; } } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren<AudioSource>(true); if (componentsInChildren.Length != 0) { return componentsInChildren[0]; } return ((Component)item).GetComponent<AudioSource>(); } private static AudioClip? FindBestVanillaFlashlightToggleClip(GrabbableObject item, AudioSource source, bool enabled) { string preferredName = (enabled ? "on" : "off"); string[] array = new string[5] { enabled ? "flashlightTurnOnSound" : "flashlightTurnOffSound", enabled ? "switchOnAudio" : "switchOffAudio", enabled ? "turnOnSound" : "turnOffSound", enabled ? "lightOnSound" : "lightOffSound", enabled ? "useUpSFX" : "useDownSFX" }; foreach (string name in array) { object? fieldOrPropertyObject = GetFieldOrPropertyObject(item, name); AudioClip val = (AudioClip)((fieldOrPropertyObject is AudioClip) ? fieldOrPropertyObject : null); if ((Object)(object)val != (Object)null) { return val; } } array = new string[5] { "flashlightClips", "flashlightSounds", "toggleClips", "toggleSounds", "audioClips" }; foreach (string name2 in array) { if (!(GetFieldOrPropertyObject(item, name2) is AudioClip[] array2) || array2.Length == 0) { continue; } AudioClip val2 = ((IEnumerable<AudioClip>)array2).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => (Object)(object)c != (Object)null && ((Object)c).name != null && ((Object)c).name.IndexOf(preferredName, StringComparison.OrdinalIgnoreCase) >= 0)); if ((Object)(object)val2 != (Object)null) { return val2; } if (array2.Length >= 2) { if (!enabled) { return array2[1]; } return array2[0]; } return array2[0]; } if ((Object)(object)source.clip != (Object)null) { return source.clip; } return null; } private static bool TryInvokeItemActivate(GrabbableObject item, bool used) { try { MethodInfo method = ((object)item).GetType().GetMethod("ItemActivate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(bool), typeof(bool) }, null); if (method != null) { method.Invoke(item, new object[2] { used, true }); return true; } MethodInfo method2 = ((object)item).GetType().GetMethod("ItemActivate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null); if (method2 != null) { method2.Invoke(item, new object[1] { used }); return true; } return false; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"TryInvokeItemActivate failed: {arg}"); return false; } } private static bool TryInvokeFlexibleBoolMethod(object instance, string methodName, bool value) { string methodName2 = methodName; try { MethodInfo[] array = (from m in instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == methodName2 select m).ToArray(); foreach (MethodInfo methodInfo in array) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(bool)) { methodInfo.Invoke(instance, new object[1] { value }); return true; } if (parameters.Length == 0) { methodInfo.Invoke(instance, Array.Empty<object>()); return true; } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"TryInvokeFlexibleBoolMethod({methodName2}) failed: {arg}"); } return false; } private static bool TryInvokeNoArgMethod(object instance, string methodName) { try { MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null) { return false; } method.Invoke(instance, Array.Empty<object>()); return true; } catch (Exception arg) { Plugin.Log.LogWarning((object)$"TryInvokeNoArgMethod({methodName}) failed: {arg}"); return false; } } private static void SetNamedLightEnabled(object instance, string fieldOrPropertyName, bool enabled) { try { object? fieldOrPropertyObject = GetFieldOrPropertyObject(instance, fieldOrPropertyName); Light val = (Light)((fieldOrPropertyObject is Light) ? fieldOrPropertyObject : null); if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = enabled; if (((Component)val).gameObject.activeSelf != enabled) { ((Component)val).gameObject.SetActive(enabled); } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"SetNamedLightEnabled({fieldOrPropertyName}) failed: {arg}"); } } private static void DisableAllChildLights(GrabbableObject item) { try { Light[] componentsInChildren = ((Component)item).GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"DisableAllChildLights failed: {arg}"); } } private static object? GetFieldOrPropertyObject(object? instance, string name) { if (instance == null) { return null; } try { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(instance); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(instance); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"GetFieldOrPropertyObject({name}) failed: {arg}"); } return null; } private static bool GetBoolFieldOrProperty(object? instance, string name) { if (instance == null) { return false; } try { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { return (bool)field.GetValue(instance); } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool)) { return (bool)property.GetValue(instance); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"GetBoolFieldOrProperty({name}) failed: {arg}"); } return false; } private static float GetFloatFieldOrProperty(object? instance, string name) { if (instance == null) { return 0f; } try { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(instance); if (value is float result) { return result; } if (value is double num) { return (float)num; } } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object value2 = property.GetValue(instance); if (value2 is float result2) { return result2; } if (value2 is double) { double num2 = (double)value2; return (float)num2; } } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"GetFloatFieldOrProperty({name}) failed: {arg}"); } return 0f; } private static void SetBoolFieldOrProperty(object instance, string name, bool value) { try { Type type = instance.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(instance, value); return; } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool) && property.CanWrite) { property.SetValue(instance, value); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"SetBoolFieldOrProperty({name}) failed: {arg}"); } } } }