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 Better Lockpicker v1.0.0
BepInEx/plugins/BetterLockpicker.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BetterLockpicker.Config; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalNetworkAPI; using LethalNetworkAPI.Utils; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; [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("BetterLockpicker")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Mod for Lethal Company, that enhance Lockpicker")] [assembly: AssemblyFileVersion("1.1.8.0")] [assembly: AssemblyInformationalVersion("1.1.8")] [assembly: AssemblyProduct("BetterLockpicker")] [assembly: AssemblyTitle("BetterLockpicker")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.8.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } internal static class LethalConfigCompat { [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Register(ConfigEntry<bool> boolConfigEntry) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)boolConfigEntry); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(boolConfigEntry, false)); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Register(ConfigEntry<int> intConfigEntry) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)intConfigEntry); LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(intConfigEntry, false)); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Register(ConfigEntry<float> floatConfigEntry) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)floatConfigEntry); LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(floatConfigEntry, false)); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void Register(ConfigEntry<string> stringConfigEntry) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)stringConfigEntry); LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(stringConfigEntry, false)); } } } namespace BetterLockpicker { internal static class LockpickerNetSync { private struct Pending { public ulong PickerNetId; public ulong DoorNetId; public float LockingTime; public bool TemporaryLockingAtStart; public float ReceivedAt; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnLockingStarted; } [CompilerGenerated] private sealed class <InitWhenReady>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitWhenReady>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_003b; case 1: <>1__state = -1; goto IL_003b; case 2: { <>1__state = -1; goto IL_0066; } IL_003b: if ((Object)(object)NetworkManager.Singleton == (Object)null) { <>2__current = null; <>1__state = 1; return true; } TryRegisterHandlers(); goto IL_0066; IL_0066: if ((Object)(object)NetworkManager.Singleton != (Object)null) { <>2__current = null; <>1__state = 2; return true; } _registeredForCurrentNm = false; _nmInstanceId = 0; _pendingByPicker.Clear(); _pendingByDoor.Clear(); goto IL_003b; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string MsgLockingStarted = "BetterLockpicker_LockingStarted_v1"; private const float PendingTtlSeconds = 10f; private static bool _registeredForCurrentNm; private static int _nmInstanceId; private static readonly Dictionary<ulong, Pending> _pendingByPicker = new Dictionary<ulong, Pending>(); private static readonly Dictionary<ulong, Pending> _pendingByDoor = new Dictionary<ulong, Pending>(); [IteratorStateMachine(typeof(<InitWhenReady>d__7))] internal static IEnumerator InitWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitWhenReady>d__7(0); } private static void TryRegisterHandlers() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } int instanceID = ((Object)singleton).GetInstanceID(); if (!_registeredForCurrentNm || _nmInstanceId != instanceID) { _registeredForCurrentNm = true; _nmInstanceId = instanceID; _pendingByPicker.Clear(); _pendingByDoor.Clear(); CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnLockingStarted; if (obj == null) { HandleNamedMessageDelegate val = OnLockingStarted; <>O.<0>__OnLockingStarted = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("BetterLockpicker_LockingStarted_v1", (HandleNamedMessageDelegate)obj); } } internal static void SendLockingStartedToAll(ulong pickerNetId, ulong doorNetId, float lockingTime) { //IL_0029: 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) //IL_003b: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(20, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref pickerNetId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref doorNetId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref lockingTime, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessageToAll("BetterLockpicker_LockingStarted_v1", val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } internal static bool TryConsumePending(ulong pickerNetId, ulong doorNetId, out float lockingTime, out bool temporaryLockingAtStart) { CleanupExpired(); if (_pendingByPicker.TryGetValue(pickerNetId, out var value) && value.DoorNetId == doorNetId) { lockingTime = value.LockingTime; temporaryLockingAtStart = value.TemporaryLockingAtStart; RemovePending(value); return true; } lockingTime = 0f; temporaryLockingAtStart = false; return false; } internal static bool TryConsumePendingDoor(ulong doorNetId, out float lockingTime, out bool temporaryLockingAtStart) { CleanupExpired(); if (_pendingByDoor.TryGetValue(doorNetId, out var value)) { lockingTime = value.LockingTime; temporaryLockingAtStart = value.TemporaryLockingAtStart; RemovePending(value); return true; } lockingTime = 0f; temporaryLockingAtStart = false; return false; } internal static bool TryPeekPendingDoor(ulong doorNetId, out float lockingTime, out bool temporaryLockingAtStart) { CleanupExpired(); if (_pendingByDoor.TryGetValue(doorNetId, out var value)) { lockingTime = value.LockingTime; temporaryLockingAtStart = value.TemporaryLockingAtStart; return true; } lockingTime = 0f; temporaryLockingAtStart = false; return false; } private static void OnLockingStarted(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0032: Unknown result type (might be due to invalid IL or missing references) ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives)); ulong num2 = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num2, default(ForPrimitives)); float lockingTime = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref lockingTime, default(ForPrimitives)); bool temporaryLockingAtStart = Plugin.TemporaryLockingVar?.Value ?? ConfigSettings.TemporaryLocking; Pending pending = default(Pending); pending.PickerNetId = num; pending.DoorNetId = num2; pending.LockingTime = lockingTime; pending.TemporaryLockingAtStart = temporaryLockingAtStart; pending.ReceivedAt = Time.realtimeSinceStartup; Pending pending2 = pending; _pendingByPicker[num] = pending2; _pendingByDoor[num2] = pending2; TryApplyNow(pending2); } private static void CleanupExpired() { if (_pendingByDoor.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; List<ulong> list = null; foreach (KeyValuePair<ulong, Pending> item in _pendingByDoor) { if (realtimeSinceStartup - item.Value.ReceivedAt > 10f) { if (list == null) { list = new List<ulong>(); } list.Add(item.Key); } } if (list == null) { return; } foreach (ulong item2 in list) { if (_pendingByDoor.TryGetValue(item2, out var value)) { RemovePending(value); } } } private static void RemovePending(Pending p) { _pendingByDoor.Remove(p.DoorNetId); _pendingByPicker.Remove(p.PickerNetId); } private static void TryApplyNow(Pending p) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.SpawnManager.SpawnedObjects.TryGetValue(p.DoorNetId, out var value)) { return; } DoorLock componentInChildren = ((Component)value).GetComponentInChildren<DoorLock>(); if (!((Object)(object)componentInChildren == (Object)null)) { LockPicker val = null; if (singleton.SpawnManager.SpawnedObjects.TryGetValue(p.PickerNetId, out var value2)) { val = ((Component)value2).GetComponent<LockPicker>(); } if ((Object)(object)val != (Object)null) { LockpickerState.RegisterLockingSession(val, componentInChildren, p.LockingTime, p.TemporaryLockingAtStart); } else { LockpickerState.RegisterLockingDoor(componentInChildren, p.LockingTime, p.TemporaryLockingAtStart); } bool doLockDoor = singleton.IsClient && !singleton.IsServer; LockpickerTiming.ApplyLockingSettings(componentInChildren, p.LockingTime, doLockDoor); RemovePending(p); } } } internal static class LockpickerState { private struct LockingSession { public DoorLock Door; public float LockingTime; public bool TemporaryLockingAtStart; public LockingSession(DoorLock door, float lockingTime, bool temporaryLockingAtStart) { Door = door; LockingTime = lockingTime; TemporaryLockingAtStart = temporaryLockingAtStart; } } private static readonly Dictionary<LockPicker, LockingSession> _lockingSessions = new Dictionary<LockPicker, LockingSession>(); private static readonly Dictionary<DoorLock, float> _lockingDoorTimes = new Dictionary<DoorLock, float>(); private static readonly Dictionary<DoorLock, bool> _lockingDoorTemporary = new Dictionary<DoorLock, bool>(); private static readonly HashSet<DoorLock> _lockingDoors = new HashSet<DoorLock>(); public static void RegisterLockingSession(LockPicker picker, DoorLock door, float lockingTime, bool temporaryLockingAtStart) { if (!((Object)(object)picker == (Object)null) && !((Object)(object)door == (Object)null)) { if (_lockingSessions.TryGetValue(picker, out var value) && (Object)(object)value.Door != (Object)null) { ClearLockingDoor(value.Door); } _lockingSessions[picker] = new LockingSession(door, lockingTime, temporaryLockingAtStart); RegisterLockingDoor(door, lockingTime, temporaryLockingAtStart); } } public static void RegisterLockingDoor(DoorLock door, float lockingTime, bool temporaryLockingAtStart) { if (!((Object)(object)door == (Object)null)) { _lockingDoors.Add(door); _lockingDoorTimes[door] = lockingTime; _lockingDoorTemporary[door] = temporaryLockingAtStart; } } public static bool TryGetLockingDoor(LockPicker picker, out DoorLock door) { if ((Object)(object)picker != (Object)null && _lockingSessions.TryGetValue(picker, out var value) && (Object)(object)value.Door != (Object)null) { door = value.Door; return true; } door = null; return false; } public static bool TryGetLockingSession(LockPicker picker, out DoorLock door, out float lockingTime, out bool temporaryLockingAtStart) { if ((Object)(object)picker != (Object)null && _lockingSessions.TryGetValue(picker, out var value) && (Object)(object)value.Door != (Object)null) { door = value.Door; lockingTime = value.LockingTime; temporaryLockingAtStart = value.TemporaryLockingAtStart; return true; } door = null; lockingTime = 0f; temporaryLockingAtStart = false; return false; } public static bool TryGetLockingDoorTime(DoorLock door, out float lockingTime) { if ((Object)(object)door != (Object)null && _lockingDoorTimes.TryGetValue(door, out lockingTime)) { return true; } lockingTime = 0f; return false; } public static bool TryGetLockingDoorTemporary(DoorLock door, out bool temporaryLockingAtStart) { if ((Object)(object)door != (Object)null && _lockingDoorTemporary.TryGetValue(door, out temporaryLockingAtStart)) { return true; } temporaryLockingAtStart = false; return false; } public static bool HasLockingSession(LockPicker picker) { if ((Object)(object)picker != (Object)null) { return _lockingSessions.ContainsKey(picker); } return false; } public static bool IsLockingDoor(DoorLock door) { if ((Object)(object)door != (Object)null) { return _lockingDoors.Contains(door); } return false; } public static void ClearLockingDoor(DoorLock door) { if (!((Object)(object)door == (Object)null)) { _lockingDoors.Remove(door); _lockingDoorTimes.Remove(door); _lockingDoorTemporary.Remove(door); } } public static void ClearLockingSession(LockPicker picker) { if (!((Object)(object)picker == (Object)null)) { if (_lockingSessions.TryGetValue(picker, out var value) && (Object)(object)value.Door != (Object)null) { ClearLockingDoor(value.Door); } _lockingSessions.Remove(picker); } } } internal static class LockpickerTiming { internal static ulong GetDoorNetworkId(DoorLock door) { if ((Object)(object)door == (Object)null) { return 0uL; } NetworkObject componentInParent = ((Component)door).GetComponentInParent<NetworkObject>(); if (!((Object)(object)componentInParent != (Object)null)) { return 0uL; } return componentInParent.NetworkObjectId; } internal static void ApplyUnlockingSettings(DoorLock door, float seconds) { float seconds2 = Mathf.Max(0.1f, seconds); SetCountdown(door, seconds2, preserveProgress: false); } internal static void ApplyLockingSettings(DoorLock door, float seconds, bool doLockDoor) { float num = Mathf.Max(0.1f, seconds); if (doLockDoor) { door.LockDoor(num); } SetCountdown(door, num, preserveProgress: true); InteractTrigger component = ((Component)door).GetComponent<InteractTrigger>(); if ((Object)(object)component != (Object)null) { bool temporaryLockingAtStart; bool flag = LockpickerState.TryGetLockingDoorTemporary(door, out temporaryLockingAtStart) && temporaryLockingAtStart; component.holdTip = (flag ? "Blocking door" : "Locking door"); component.timeToHold = num; } } internal static void SetCountdown(DoorLock door, float seconds, bool preserveProgress) { if ((Object)(object)door == (Object)null) { return; } seconds = Mathf.Max(0.1f, seconds); if (!preserveProgress || Mathf.Abs(door.lockPickTimeLeft - door.maxTimeLeft) < 0.001f) { door.maxTimeLeft = seconds; door.lockPickTimeLeft = seconds; } else { float num = door.lockPickTimeLeft / Mathf.Max(0.01f, door.maxTimeLeft); door.maxTimeLeft = seconds; door.lockPickTimeLeft = Mathf.Clamp(seconds * num, 0f, seconds); } if ((Object)(object)door.twinDoor != (Object)null) { DoorLock twinDoor = door.twinDoor; if (!preserveProgress || Mathf.Abs(twinDoor.lockPickTimeLeft - twinDoor.maxTimeLeft) < 0.001f) { twinDoor.maxTimeLeft = seconds; twinDoor.lockPickTimeLeft = seconds; } else { float num2 = twinDoor.lockPickTimeLeft / Mathf.Max(0.01f, twinDoor.maxTimeLeft); twinDoor.maxTimeLeft = seconds; twinDoor.lockPickTimeLeft = Mathf.Clamp(seconds * num2, 0f, seconds); } InteractTrigger component = ((Component)twinDoor).GetComponent<InteractTrigger>(); if ((Object)(object)component != (Object)null) { component.timeToHold = seconds; } } } } [BepInPlugin("Azx.BetterLockpicker", "Better Lockpicker", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "Azx.BetterLockpicker"; public const string PluginName = "Better Lockpicker"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; internal static Harmony Harmony; internal static Plugin Instance; internal static LNetworkVariable<bool> CanLockDoorsVar; internal static LNetworkVariable<bool> TemporaryLockingVar; internal static LNetworkVariable<int> LockingTimeVar; internal static LNetworkVariable<int> UnlockingTimeVar; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Harmony = new Harmony("Azx.BetterLockpicker"); ConfigSettings.Init((BaseUnityPlugin)(object)this); CanLockDoorsVar = LNetworkVariable<bool>.Connect("Azx.BetterLockpicker.CanLockDoors", ConfigSettings.CanLockDoors, (LNetworkVariableWritePerms)0, (Action<bool, bool>)delegate(bool oldV, bool newV) { Log.LogDebug((object)$"CanLockDoors sync: {oldV} -> {newV}"); }); TemporaryLockingVar = LNetworkVariable<bool>.Connect("Azx.BetterLockpicker.TemporaryLocking", ConfigSettings.TemporaryLocking, (LNetworkVariableWritePerms)0, (Action<bool, bool>)delegate(bool oldV, bool newV) { Log.LogDebug((object)$"TemporaryLocking sync: {oldV} -> {newV}"); }); LockingTimeVar = LNetworkVariable<int>.Connect("Azx.BetterLockpicker.LockingTime", ConfigSettings.LockingTime, (LNetworkVariableWritePerms)0, (Action<int, int>)delegate(int oldV, int newV) { Log.LogDebug((object)$"LockingTime sync: {oldV} -> {newV}"); }); UnlockingTimeVar = LNetworkVariable<int>.Connect("Azx.BetterLockpicker.UnlockingTime", ConfigSettings.UnlockingTime, (LNetworkVariableWritePerms)0, (Action<int, int>)delegate(int oldV, int newV) { Log.LogDebug((object)$"UnlockingTime sync: {oldV} -> {newV}"); }); LNetworkUtils.OnNetworkStart += delegate(bool isServer) { if (isServer) { if (CanLockDoorsVar != null) { CanLockDoorsVar.Value = ConfigSettings.CanLockDoors; } if (TemporaryLockingVar != null) { TemporaryLockingVar.Value = ConfigSettings.TemporaryLocking; } if (LockingTimeVar != null) { LockingTimeVar.Value = ConfigSettings.LockingTime; } if (UnlockingTimeVar != null) { UnlockingTimeVar.Value = ConfigSettings.UnlockingTime; } } }; Harmony.PatchAll(); ((MonoBehaviour)this).StartCoroutine(LockpickerNetSync.InitWhenReady()); Log.LogInfo((object)"Better Lockpicker 1.0.0 loaded."); } internal static bool IsHost() { if (Object.op_Implicit((Object)(object)NetworkManager.Singleton)) { if (!NetworkManager.Singleton.IsServer) { return NetworkManager.Singleton.IsHost; } return true; } return false; } } public static class PluginInfo { public const string PLUGIN_GUID = "BetterLockpicker"; public const string PLUGIN_NAME = "BetterLockpicker"; public const string PLUGIN_VERSION = "1.1.8"; } } namespace BetterLockpicker.Patches { public static class LockpickerPatches { [HarmonyPatch(typeof(LockPicker), "ItemActivate")] internal static class LockPicker_ItemActivate_Patch { private static readonly MethodInfo GetLockPickerDoorPositionMethod = AccessTools.Method(typeof(LockPicker), "GetLockPickerDoorPosition", (Type[])null, (Type[])null); private static readonly MethodInfo PlaceOnDoorMethod = AccessTools.Method(typeof(LockPicker), "PlaceOnDoor", new Type[2] { typeof(DoorLock), typeof(bool) }, (Type[])null); private static readonly FieldInfo PlaceOnLockPicker1Field = AccessTools.Field(typeof(LockPicker), "placeOnLockPicker1"); private static void Postfix(LockPicker __instance, bool used, bool buttonDown) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (!buttonDown || (Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !((GrabbableObject)__instance).isHeld) { return; } LNetworkVariable<bool> canLockDoorsVar = Plugin.CanLockDoorsVar; if ((canLockDoorsVar != null) ? (!canLockDoorsVar.Value) : ConfigSettings.CanLockDoors) { return; } PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Ray(((Component)playerHeldBy.gameplayCamera).transform.position, ((Component)playerHeldBy.gameplayCamera).transform.forward), ref val, 3f, 2816)) { return; } DoorLock component = ((Component)((RaycastHit)(ref val)).transform).GetComponent<DoorLock>(); if (!((Object)(object)component == (Object)null) && !component.isPickingLock && !component.isLocked) { AnimatedObjectTrigger component2 = ((Component)component).GetComponent<AnimatedObjectTrigger>(); if (!((Object)(object)component2 != (Object)null) || !component2.boolValue) { Vector3 val2 = (Vector3)GetLockPickerDoorPositionMethod.Invoke(__instance, new object[1] { component }); bool flag = (bool)PlaceOnLockPicker1Field.GetValue(__instance); playerHeldBy.DiscardHeldObject(true, ((NetworkBehaviour)component).NetworkObject, val2, true); __instance.PlaceLockPickerServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)component).NetworkObject), flag); PlaceOnDoorMethod.Invoke(__instance, new object[2] { component, flag }); } } } } [HarmonyPatch(typeof(LockPicker), "PlaceOnDoor")] internal static class LockPicker_PlaceOnDoor_Patch { private struct PrefixState { public bool DoorWasLockedBefore; public ulong DoorNetId; public ulong PickerNetId; } private static void Prefix(LockPicker __instance, DoorLock doorScript, out PrefixState __state) { __state = new PrefixState { DoorWasLockedBefore = ((Object)(object)doorScript != (Object)null && doorScript.isLocked), DoorNetId = (((Object)(object)doorScript != (Object)null) ? LockpickerTiming.GetDoorNetworkId(doorScript) : 0), PickerNetId = (((Object)(object)__instance != (Object)null) ? ((NetworkBehaviour)__instance).NetworkObjectId : 0) }; } private static void Postfix(LockPicker __instance, DoorLock doorScript, bool lockPicker1, PrefixState __state) { if ((Object)(object)__instance == (Object)null || (Object)(object)doorScript == (Object)null) { return; } if (__state.PickerNetId != 0L && __state.DoorNetId != 0L && LockpickerNetSync.TryConsumePending(__state.PickerNetId, __state.DoorNetId, out var lockingTime, out var temporaryLockingAtStart)) { LockpickerState.RegisterLockingSession(__instance, doorScript, lockingTime, temporaryLockingAtStart); bool doLockDoor = (Object)(object)NetworkManager.Singleton == (Object)null || (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer); LockpickerTiming.ApplyLockingSettings(doorScript, lockingTime, doLockDoor); } else if (LockpickerState.HasLockingSession(__instance) || LockpickerState.IsLockingDoor(doorScript)) { float num = Plugin.LockingTimeVar?.Value ?? ConfigSettings.LockingTime; bool temporaryLockingAtStart2 = Plugin.TemporaryLockingVar?.Value ?? ConfigSettings.TemporaryLocking; float lockingTime3; if (LockpickerState.TryGetLockingSession(__instance, out var _, out var lockingTime2, out var temporaryLockingAtStart3)) { if (lockingTime2 > 0.01f) { num = lockingTime2; } temporaryLockingAtStart2 = temporaryLockingAtStart3; } else if (LockpickerState.TryGetLockingDoorTime(doorScript, out lockingTime3) && lockingTime3 > 0.01f) { num = lockingTime3; if (LockpickerState.TryGetLockingDoorTemporary(doorScript, out var temporaryLockingAtStart4)) { temporaryLockingAtStart2 = temporaryLockingAtStart4; } } LockpickerState.RegisterLockingSession(__instance, doorScript, num, temporaryLockingAtStart2); bool doLockDoor2 = (Object)(object)NetworkManager.Singleton == (Object)null || (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer); LockpickerTiming.ApplyLockingSettings(doorScript, num, doLockDoor2); } else if (__state.DoorWasLockedBefore) { LockpickerTiming.ApplyUnlockingSettings(doorScript, Plugin.UnlockingTimeVar?.Value ?? ConfigSettings.UnlockingTime); LockpickerState.ClearLockingSession(__instance); } else { LNetworkVariable<bool> canLockDoorsVar = Plugin.CanLockDoorsVar; if (!((canLockDoorsVar != null) ? (!canLockDoorsVar.Value) : ConfigSettings.CanLockDoors)) { float num2 = Mathf.Max(0.1f, (float)(Plugin.LockingTimeVar?.Value ?? ConfigSettings.LockingTime)); bool temporaryLockingAtStart5 = Plugin.TemporaryLockingVar?.Value ?? ConfigSettings.TemporaryLocking; LockpickerState.RegisterLockingSession(__instance, doorScript, num2, temporaryLockingAtStart5); bool doLockDoor3 = (Object)(object)NetworkManager.Singleton == (Object)null || (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer); LockpickerTiming.ApplyLockingSettings(doorScript, num2, doLockDoor3); } } } } [HarmonyPatch(typeof(LockPicker), "FinishPickingLock")] internal static class LockPicker_FinishPickingLock_Patch { private struct FinishState { public DoorLock Door; public float LockingTime; public bool TemporaryLockingAtStart; } private static void Prefix(LockPicker __instance, out FinishState __state) { __state = default(FinishState); if (LockpickerState.TryGetLockingSession(__instance, out var door, out var lockingTime, out var temporaryLockingAtStart)) { __state.Door = door; __state.LockingTime = lockingTime; __state.TemporaryLockingAtStart = temporaryLockingAtStart; } } private static void Postfix(LockPicker __instance, FinishState __state) { if (!((Object)(object)__state.Door == (Object)null)) { LockpickerState.ClearLockingSession(__instance); if (!__state.TemporaryLockingAtStart) { float num = Mathf.Max(0.1f, (__state.LockingTime > 0.01f) ? __state.LockingTime : ((float)(Plugin.LockingTimeVar?.Value ?? ConfigSettings.LockingTime))); __state.Door.LockDoor(num); } } } } [HarmonyPatch(typeof(LockPicker), "EquipItem")] internal static class LockPicker_EquipItem_Patch { private static void Postfix(LockPicker __instance) { if (LockpickerState.TryGetLockingDoor(__instance, out var door)) { LockpickerState.ClearLockingSession(__instance); if ((Object)(object)door != (Object)null && door.isLocked) { door.UnlockDoorSyncWithServer(); } } } } [HarmonyPatch(typeof(DoorLock), "Update")] internal static class DoorLock_Update_Patch { private static void Postfix(DoorLock __instance) { if ((Object)(object)__instance == (Object)null) { return; } if (LockpickerState.IsLockingDoor(__instance) && (!__instance.isLocked || !__instance.isPickingLock)) { LockpickerState.ClearLockingDoor(__instance); } else { if (!__instance.isLocked || !__instance.isPickingLock) { return; } ulong doorNetworkId = LockpickerTiming.GetDoorNetworkId(__instance); if (!LockpickerState.IsLockingDoor(__instance) && doorNetworkId != 0L && LockpickerNetSync.TryConsumePendingDoor(doorNetworkId, out var lockingTime, out var temporaryLockingAtStart) && lockingTime > 0.01f) { LockpickerState.RegisterLockingDoor(__instance, lockingTime, temporaryLockingAtStart); bool doLockDoor = (Object)(object)NetworkManager.Singleton == (Object)null || (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer); LockpickerTiming.ApplyLockingSettings(__instance, lockingTime, doLockDoor); } if (LockpickerState.IsLockingDoor(__instance) && LockpickerState.TryGetLockingDoorTime(__instance, out var lockingTime2) && lockingTime2 > 0.01f) { InteractTrigger component = ((Component)__instance).GetComponent<InteractTrigger>(); if (Mathf.Abs(__instance.maxTimeLeft - lockingTime2) > 0.05f || ((Object)(object)component != (Object)null && Mathf.Abs(component.timeToHold - lockingTime2) > 0.05f)) { LockpickerTiming.ApplyLockingSettings(__instance, lockingTime2, doLockDoor: false); } if ((Object)(object)component != (Object)null) { bool temporaryLockingAtStart2; string arg = ((LockpickerState.TryGetLockingDoorTemporary(__instance, out temporaryLockingAtStart2) && temporaryLockingAtStart2) ? "Blocking door" : "Locking door"); component.disabledHoverTip = $"{arg}: {(int)__instance.lockPickTimeLeft} sec."; } } } } } [HarmonyPatch(typeof(LockPicker), "PlaceLockPickerServerRpc")] internal static class LockPicker_PlaceLockPickerServerRpc_Patch { private struct RpcState { public bool IsServerStage; public bool DoorWasLockedBefore; public ulong DoorNetId; } private static readonly FieldInfo RpcExecStageField = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_exec_stage"); private static void Prefix(LockPicker __instance, NetworkObjectReference doorObject, bool lockPicker1, out RpcState __state) { __state = default(RpcState); __state.IsServerStage = IsServerRpcStage(__instance); NetworkObject val = default(NetworkObject); if (__state.IsServerStage && ((NetworkObjectReference)(ref doorObject)).TryGet(ref val, (NetworkManager)null) && !((Object)(object)val == (Object)null)) { __state.DoorNetId = val.NetworkObjectId; DoorLock componentInChildren = ((Component)val).GetComponentInChildren<DoorLock>(); __state.DoorWasLockedBefore = (Object)(object)componentInChildren != (Object)null && componentInChildren.isLocked; } } private static void Postfix(LockPicker __instance, NetworkObjectReference doorObject, bool lockPicker1, RpcState __state) { NetworkObject val = default(NetworkObject); if (__state.IsServerStage && ((NetworkObjectReference)(ref doorObject)).TryGet(ref val, (NetworkManager)null) && !((Object)(object)val == (Object)null)) { DoorLock componentInChildren = ((Component)val).GetComponentInChildren<DoorLock>(); if (!((Object)(object)componentInChildren == (Object)null) && !__state.DoorWasLockedBefore) { float num = Mathf.Max(0.1f, (float)(Plugin.LockingTimeVar?.Value ?? ConfigSettings.LockingTime)); bool temporaryLockingAtStart = Plugin.TemporaryLockingVar?.Value ?? ConfigSettings.TemporaryLocking; LockpickerState.RegisterLockingSession(__instance, componentInChildren, num, temporaryLockingAtStart); LockpickerTiming.ApplyLockingSettings(componentInChildren, num, doLockDoor: true); LockpickerNetSync.SendLockingStartedToAll(((NetworkBehaviour)__instance).NetworkObjectId, __state.DoorNetId, num); } } } private static bool IsServerRpcStage(LockPicker instance) { if ((Object)(object)instance == (Object)null) { return false; } if (RpcExecStageField != null) { object value = RpcExecStageField.GetValue(instance); if (value != null) { return value.ToString() == "Server"; } } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null) { return singleton.IsServer; } return false; } } private const int DoorMask = 2816; } } namespace BetterLockpicker.Config { internal static class ConfigSettings { private static ConfigEntry<bool> _canLockDoors; private static ConfigEntry<bool> _temporaryLocking; private static ConfigEntry<int> _lockingTime; private static ConfigEntry<int> _unlockingTime; private static readonly bool _default_canLockDoors = true; private static readonly bool _default_temporaryLocking = false; private static readonly int _default_lockingTime = 30; private static readonly int _default_unlockingTime = 30; internal static bool CanLockDoors = _default_canLockDoors; internal static bool TemporaryLocking = _default_temporaryLocking; internal static int LockingTime = _default_lockingTime; internal static int UnlockingTime = _default_unlockingTime; internal static void Init(BaseUnityPlugin plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown ConfigFile config = plugin.Config; _canLockDoors = config.Bind<bool>("Locking Doors", "CanLockDoors", _default_canLockDoors, new ConfigDescription("When enabled, lockpickers can be used to lock doors.", (AcceptableValueBase)null, Array.Empty<object>())); _temporaryLocking = config.Bind<bool>("Locking Doors", "Temporary Locking", _default_temporaryLocking, new ConfigDescription("When enabled, lockpickers can only hold doors shut while attached to the door. When the lockpicker detaches from the door, the door will always be unlocked.", (AcceptableValueBase)null, Array.Empty<object>())); _lockingTime = config.Bind<int>("Locking Doors", "LockingTime", _default_lockingTime, new ConfigDescription("The time it takes to lock a door (in seconds).", (AcceptableValueBase)null, Array.Empty<object>())); _unlockingTime = config.Bind<int>("Unlocking Doors", "UnlockingTime", _default_unlockingTime, new ConfigDescription("The time it takes to unlock a door (in seconds).", (AcceptableValueBase)null, Array.Empty<object>())); LethalConfigCompat.Register(_canLockDoors); LethalConfigCompat.Register(_temporaryLocking); LethalConfigCompat.Register(_lockingTime); LethalConfigCompat.Register(_unlockingTime); _canLockDoors.SettingChanged += OnCanLockDoorsChanged; _temporaryLocking.SettingChanged += OnTemporaryLockingChanged; _lockingTime.SettingChanged += OnLockingTimeChanged; _unlockingTime.SettingChanged += OnUnlockingTimeChanged; UpdateCanLockDoors(); UpdateTemporaryLocking(); UpdateLockingTime(); UpdateUnlockingTime(); } private static void OnCanLockDoorsChanged(object sender, EventArgs e) { UpdateCanLockDoors(); } private static void OnTemporaryLockingChanged(object sender, EventArgs e) { UpdateTemporaryLocking(); } private static void OnLockingTimeChanged(object sender, EventArgs e) { UpdateLockingTime(); } private static void OnUnlockingTimeChanged(object sender, EventArgs e) { UpdateUnlockingTime(); } private static void UpdateCanLockDoors() { CanLockDoors = _canLockDoors?.Value ?? _default_canLockDoors; if (Plugin.IsHost() && Plugin.CanLockDoorsVar != null) { Plugin.CanLockDoorsVar.Value = CanLockDoors; } } private static void UpdateTemporaryLocking() { TemporaryLocking = _temporaryLocking?.Value ?? _default_temporaryLocking; if (Plugin.IsHost() && Plugin.TemporaryLockingVar != null) { Plugin.TemporaryLockingVar.Value = TemporaryLocking; } } private static void UpdateLockingTime() { LockingTime = _lockingTime?.Value ?? _default_lockingTime; if (Plugin.IsHost() && Plugin.LockingTimeVar != null) { Plugin.LockingTimeVar.Value = LockingTime; } } private static void UpdateUnlockingTime() { UnlockingTime = _unlockingTime?.Value ?? _default_unlockingTime; if (Plugin.IsHost() && Plugin.UnlockingTimeVar != null) { Plugin.UnlockingTimeVar.Value = UnlockingTime; } } } }