Decompiled source of betterdoor v0.1.6

BepInEx/plugins/HJM_betterdoor/HJM.doors.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HJM.Remakes;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 HJM.Remakes
{
	internal struct Packet
	{
		internal int Op;

		internal int Value;

		internal ulong Id;

		internal ulong Actor;

		internal float Scalar;

		internal Vector3 Position;

		internal Vector3 Direction;
	}
	internal sealed class Wire
	{
		private readonly string name;

		private readonly Action<ulong, Packet> request;

		private readonly Action<Packet> state;

		private NetworkManager attached;

		internal bool Ready
		{
			get
			{
				if ((Object)(object)attached != (Object)null)
				{
					return attached.IsListening;
				}
				return false;
			}
		}

		internal bool Server
		{
			get
			{
				if (Ready)
				{
					return attached.IsServer;
				}
				return false;
			}
		}

		internal Wire(string n, Action<ulong, Packet> r, Action<Packet> s)
		{
			name = n;
			request = r;
			state = s;
		}

		internal void Tick()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)(object)attached && Ready)
			{
				return;
			}
			if ((Object)(object)attached != (Object)null)
			{
				try
				{
					attached.CustomMessagingManager.UnregisterNamedMessageHandler(name + ".request");
					attached.CustomMessagingManager.UnregisterNamedMessageHandler(name + ".state");
				}
				catch
				{
				}
			}
			attached = null;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsListening && singleton.CustomMessagingManager != null)
			{
				attached = singleton;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler(name + ".request", new HandleNamedMessageDelegate(OnRequest));
				singleton.CustomMessagingManager.RegisterNamedMessageHandler(name + ".state", new HandleNamedMessageDelegate(OnState));
			}
		}

		private void OnRequest(ulong sender, FastBufferReader reader)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (Server && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 64)
			{
				Packet arg = Read(reader);
				request(sender, arg);
			}
		}

		private void OnState(ulong sender, FastBufferReader reader)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Ready && !Server && sender == 0L && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position == 64)
			{
				state(Read(reader));
			}
		}

		internal void Ask(Packet p)
		{
			if (Ready)
			{
				if (Server)
				{
					request(attached.LocalClientId, p);
				}
				else
				{
					Send(name + ".request", 0uL, p);
				}
			}
		}

		internal void Publish(Packet p)
		{
			if (!Server)
			{
				return;
			}
			state(p);
			foreach (ulong connectedClientsId in attached.ConnectedClientsIds)
			{
				if (connectedClientsId != 0L)
				{
					Send(name + ".state", connectedClientsId, p);
				}
			}
		}

		internal void Reply(ulong id, Packet p)
		{
			if (id == 0L)
			{
				state(p);
			}
			else
			{
				Send(name + ".state", id, p);
			}
		}

		private unsafe void Send(string channel, ulong target, Packet p)
		{
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(64, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref p.Op, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref p.Value, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref p.Id, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref p.Actor, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Scalar, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Position.x, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Position.y, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Position.z, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Direction.x, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Direction.y, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref p.Direction.z, default(ForPrimitives));
				SendPadding(ref p, val);
				attached.CustomMessagingManager.SendNamedMessage(channel, target, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void SendPadding(ref Packet p, FastBufferWriter w)
		{
			//IL_0008: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			num = 0;
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref num, default(ForPrimitives));
			num = 0;
			((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref num, default(ForPrimitives));
		}

		private static Packet Read(FastBufferReader r)
		{
			//IL_0013: 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_002a: 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_0041: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			Packet result = default(Packet);
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref result.Op, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<int>(ref result.Value, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref result.Id, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref result.Actor, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Scalar, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Position.x, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Position.y, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Position.z, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Direction.x, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Direction.y, default(ForPrimitives));
			((FastBufferReader)(ref r)).ReadValueSafe<float>(ref result.Direction.z, default(ForPrimitives));
			return result;
		}

		internal static PlayerControllerB Player(ulong sender)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				return null;
			}
			PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				if ((Object)(object)val != (Object)null && val.actualClientId == sender && val.isPlayerControlled && !val.isPlayerDead)
				{
					return val;
				}
			}
			return null;
		}

		internal static T Object<T>(ulong id) where T : Component
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.SpawnManager == null || !singleton.SpawnManager.SpawnedObjects.TryGetValue(id, out var value))
			{
				return default(T);
			}
			return ((Component)value).GetComponent<T>();
		}
	}
}
namespace HJM.DoorTools
{
	public static class DoorDamage
	{
		public static int Remaining(int health, int force, int perForce)
		{
			if (health <= 0)
			{
				return 0;
			}
			if (force <= 0 || perForce <= 0)
			{
				return health;
			}
			long num = (long)force * (long)perForce;
			if (num < health)
			{
				return health - (int)num;
			}
			return 0;
		}
	}
	public sealed class KeyPressGate
	{
		private readonly Dictionary<int, float> lastPress = new Dictionary<int, float>();

		public bool Accept(int key, bool down, float time)
		{
			if (!down)
			{
				return false;
			}
			if (lastPress.TryGetValue(key, out var value) && time >= value && time - value < 0.35f)
			{
				return false;
			}
			lastPress[key] = time;
			return true;
		}
	}
	[BepInPlugin("hjm.doortools", "工具破门与钥匙锁门", "0.1.6")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance;

		internal static Wire Bus;

		internal static ConfigEntry<int> Health;

		internal static ConfigEntry<int> Damage;

		internal static readonly Dictionary<DoorLock, Packet> States = new Dictionary<DoorLock, Packet>();

		private bool adaptersInstalled;

		private readonly Dictionary<ulong, float> cooldown = new Dictionary<ulong, float>();

		private float query;

		private int seed = int.MinValue;

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (value.Metadata.Name == "DoorBreach" || value.Metadata.Name == "KeysLockDoors")
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Disable old door plugins before DoorTools.");
					return;
				}
			}
			Instance = this;
			Health = ((BaseUnityPlugin)this).Config.Bind<int>("Doors", "Health", 100, new ConfigDescription("普通门生命值;铲子标准20伤害,100血需5下", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100000), Array.Empty<object>()));
			Damage = ((BaseUnityPlugin)this).Config.Bind<int>("Doors", "DamagePerHitForce", 20, new ConfigDescription("原生命中力度1换算成多少门伤害;普通铲子力度1", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), Array.Empty<object>()));
			Bus = new Wire("hjm.doortools.v1", Request, Apply);
			new Harmony("hjm.doortools").PatchAll();
		}

		private void Update()
		{
			if (Bus == null)
			{
				return;
			}
			if (!adaptersInstalled)
			{
				WeaponAdapters.Install();
				adaptersInstalled = true;
			}
			Bus.Tick();
			if (!Bus.Ready)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (seed != instance.randomMapSeed)
				{
					seed = instance.randomMapSeed;
					States.Clear();
					cooldown.Clear();
					query = 0f;
				}
				if (!Bus.Server && !instance.inShipPhase && Time.unscaledTime >= query)
				{
					query = Time.unscaledTime + 5f;
					Bus.Ask(new Packet
					{
						Op = 9
					});
				}
			}
		}

		private void Request(ulong sender, Packet p)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			if (p.Op == 9)
			{
				foreach (Packet value7 in States.Values)
				{
					Packet current = value7;
					DoorLock val = Resolve(current);
					if ((Object)(object)val != (Object)null)
					{
						current.Scalar = (val.isLocked ? 1 : 0);
						Bus.Reply(sender, current);
					}
				}
				return;
			}
			PlayerControllerB val2 = Wire.Player(sender);
			DoorLock val3 = Resolve(p);
			if (p.Op == 2 || p.Op == 3)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Key server request op=" + p.Op + " playerFound=" + ((Object)(object)val2 != (Object)null) + " doorFound=" + ((Object)(object)val3 != (Object)null)));
			}
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || !((NetworkBehaviour)val3).IsSpawned || Vector3.Distance(((Component)val2.gameplayCamera).transform.position, ((Component)val3).transform.position) > 5f)
			{
				return;
			}
			GrabbableObject currentlyHeldObjectServer = val2.currentlyHeldObjectServer;
			if ((Object)(object)currentlyHeldObjectServer == (Object)null)
			{
				return;
			}
			ulong key = sender * 2 + (ulong)((p.Op == 2 || p.Op == 3) ? 1 : 0);
			if (cooldown.TryGetValue(key, out var value) && Time.unscaledTime - value < ((p.Op == 2 || p.Op == 3) ? 0.35f : 0.12f))
			{
				return;
			}
			RaycastHit val4 = default(RaycastHit);
			if (!Physics.Raycast(new Ray(((Component)val2.gameplayCamera).transform.position, ((Component)val2.gameplayCamera).transform.forward), ref val4, 3.5f, 2816, (QueryTriggerInteraction)((p.Op == 1) ? 2 : 0)) || (Object)(object)FindDoor(((RaycastHit)(ref val4)).collider) != (Object)(object)val3)
			{
				if (p.Op != 1)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Key request rejected: server ray target differs");
				}
			}
			else if (!Broken(val3))
			{
				if (p.Op == 1 && WeaponAdapters.Force(currentlyHeldObjectServer) > 0)
				{
					cooldown[key] = Time.unscaledTime;
					int health = (States.TryGetValue(val3, out var value2) ? value2.Value : Health.Value);
					health = DoorDamage.Remaining(health, WeaponAdapters.Force(currentlyHeldObjectServer), Damage.Value);
					Bus.Publish(new Packet
					{
						Op = 1,
						Id = p.Id,
						Actor = p.Actor,
						Value = health,
						Scalar = (val3.isLocked ? 1 : 0)
					});
				}
				else if (p.Op == 2 && currentlyHeldObjectServer is KeyItem && !val3.isLocked && !Opened(val3) && !val3.isPickingLock)
				{
					cooldown[key] = Time.unscaledTime;
					Packet value4;
					int value3 = (States.TryGetValue(val3, out value4) ? value4.Value : Health.Value);
					Bus.Publish(new Packet
					{
						Op = 1,
						Id = p.Id,
						Actor = p.Actor,
						Value = value3,
						Scalar = 1f
					});
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Key LOCK accepted: door=" + ((NetworkBehaviour)val3).NetworkObjectId + ":" + ((NetworkBehaviour)val3).NetworkBehaviourId + " locked=" + val3.isLocked));
					Bus.Reply(sender, new Packet
					{
						Op = 5,
						Value = 1
					});
					Bus.Reply(sender, new Packet
					{
						Op = 4,
						Id = ((NetworkBehaviour)currentlyHeldObjectServer).NetworkObjectId,
						Actor = sender
					});
				}
				else if (p.Op == 3 && currentlyHeldObjectServer is KeyItem && val3.isLocked && !val3.isPickingLock)
				{
					cooldown[key] = Time.unscaledTime;
					Packet value6;
					int value5 = (States.TryGetValue(val3, out value6) ? value6.Value : Health.Value);
					Bus.Publish(new Packet
					{
						Op = 1,
						Id = p.Id,
						Actor = p.Actor,
						Value = value5,
						Scalar = 0f
					});
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Key UNLOCK accepted: door=" + ((NetworkBehaviour)val3).NetworkObjectId + ":" + ((NetworkBehaviour)val3).NetworkBehaviourId));
					Bus.Reply(sender, new Packet
					{
						Op = 4,
						Id = ((NetworkBehaviour)currentlyHeldObjectServer).NetworkObjectId,
						Actor = sender
					});
				}
			}
		}

		private static void Apply(Packet p)
		{
			if (p.Op == 4)
			{
				PlayerControllerB val = (((Object)(object)StartOfRound.Instance == (Object)null) ? null : StartOfRound.Instance.localPlayerController);
				if ((Object)(object)val != (Object)null && val.actualClientId == p.Actor && val.currentlyHeldObjectServer is KeyItem && ((NetworkBehaviour)val.currentlyHeldObjectServer).NetworkObjectId == p.Id)
				{
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Confirmed key action: consume key=" + p.Id));
					val.DespawnHeldObject();
				}
				return;
			}
			if (p.Op == 5)
			{
				KeyInput.Notify("门已上锁");
				return;
			}
			DoorLock val2 = Resolve(p);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			bool flag = Broken(val2);
			Packet value;
			bool num = !States.TryGetValue(val2, out value) || value.Value != p.Value || value.Scalar != p.Scalar;
			States[val2] = p;
			if (num && (Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Door state applied door=" + p.Id + ":" + p.Actor + " hp=" + p.Value + " locked=" + (p.Scalar > 0f) + " localServer=" + (Bus != null && Bus.Server)));
			}
			if (p.Value <= 0)
			{
				if (!flag)
				{
					Break(val2);
				}
				else
				{
					RestoreUnlocked(val2);
				}
				if ((Object)(object)val2.twinDoor != (Object)null)
				{
					DoorLock twinDoor = val2.twinDoor;
					bool num2 = Broken(twinDoor);
					States[twinDoor] = new Packet
					{
						Op = 1,
						Id = ((NetworkBehaviour)twinDoor).NetworkObjectId,
						Actor = ((NetworkBehaviour)twinDoor).NetworkBehaviourId,
						Value = 0
					};
					if (!num2)
					{
						Break(twinDoor);
					}
					else
					{
						RestoreUnlocked(twinDoor);
					}
				}
			}
			else if (p.Scalar > 0f && !val2.isLocked)
			{
				val2.LockDoor(30f);
			}
			else if (p.Scalar <= 0f)
			{
				if (val2.isLocked)
				{
					val2.UnlockDoor();
				}
				if ((Object)(object)val2.twinDoor != (Object)null && val2.twinDoor.isLocked)
				{
					val2.twinDoor.UnlockDoor();
				}
			}
		}

		private static void Break(DoorLock d)
		{
			if (d.isLocked)
			{
				d.UnlockDoor();
			}
			RestoreUnlocked(d);
			d.SetDoorAsOpen(true);
			AnimatedObjectTrigger component = ((Component)d).GetComponent<AnimatedObjectTrigger>();
			if ((Object)(object)component != (Object)null)
			{
				component.SetBoolOnClientOnly(true);
			}
		}

		internal static void RestoreUnlocked(DoorLock d)
		{
			d.isLocked = false;
			d.isPickingLock = false;
			float timeToHold = (float)AccessTools.Field(typeof(DoorLock), "defaultTimeToHold").GetValue(d);
			InteractTrigger[] array = (InteractTrigger[])(object)new InteractTrigger[2] { d.doorTrigger, d.doorTriggerB };
			foreach (InteractTrigger val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.interactable = true;
					val.hoverTip = "Use door : [LMB]";
					val.disabledHoverTip = "";
					val.holdTip = "";
					val.timeToHold = timeToHold;
					val.timeToHoldSpeedMultiplier = 1f;
				}
			}
			object? value = AccessTools.Field(typeof(DoorLock), "navMeshObstacle").GetValue(d);
			NavMeshObstacle val2 = (NavMeshObstacle)((value is NavMeshObstacle) ? value : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.carving = false;
			}
		}

		internal static DoorLock Resolve(Packet p)
		{
			Transform val = Wire.Object<Transform>(p.Id);
			if (!((Object)(object)val == (Object)null))
			{
				return FindNetworkDoor(val, p.Actor);
			}
			return null;
		}

		internal static DoorLock FindNetworkDoor(Transform root, ulong behaviour)
		{
			DoorLock[] componentsInChildren = ((Component)root).GetComponentsInChildren<DoorLock>(true);
			foreach (DoorLock val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).GetComponentInParent<NetworkObject>(true) != (Object)null && (Object)(object)((Component)((Component)val).GetComponentInParent<NetworkObject>(true)).transform == (Object)(object)root && ((NetworkBehaviour)val).NetworkBehaviourId == behaviour)
				{
					return val;
				}
			}
			return null;
		}

		internal static int ShovelForce(Shovel weapon)
		{
			if (!((Object)(object)weapon == (Object)null))
			{
				return Math.Max(0, weapon.shovelHitForce);
			}
			return 0;
		}

		internal static bool Opened(DoorLock d)
		{
			AnimatedObjectTrigger component = ((Component)d).GetComponent<AnimatedObjectTrigger>();
			if ((Object)(object)component != (Object)null)
			{
				return component.boolValue;
			}
			return false;
		}

		internal static bool Broken(DoorLock d)
		{
			if ((Object)(object)d != (Object)null && States.TryGetValue(d, out var value))
			{
				return value.Value <= 0;
			}
			return false;
		}

		internal static DoorLock FindDoor(Collider c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			DoorLock component = ((Component)c).GetComponent<DoorLock>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			TriggerPointToDoor component2 = ((Component)c).GetComponent<TriggerPointToDoor>();
			if (!((Object)(object)component2 != (Object)null))
			{
				return ((Component)c).GetComponentInParent<DoorLock>();
			}
			return component2.pointToDoor;
		}

		internal static void KeyLog(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}

		internal static void AskKey(DoorLock d, int op)
		{
			Bus.Ask(new Packet
			{
				Op = op,
				Id = ((NetworkBehaviour)d).NetworkObjectId,
				Actor = ((NetworkBehaviour)d).NetworkBehaviourId
			});
		}

		internal static void Action(PlayerControllerB p, int action)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (!((Object)(object)p == (Object)null) && ((NetworkBehaviour)p).IsOwner && Bus != null && Bus.Ready && Physics.Raycast(((Component)p.gameplayCamera).transform.position, ((Component)p.gameplayCamera).transform.forward, ref val, 3.2f, 2816, (QueryTriggerInteraction)2))
			{
				DoorLock val2 = FindDoor(((RaycastHit)(ref val)).collider);
				if ((Object)(object)val2 != (Object)null && ((NetworkBehaviour)val2).IsSpawned)
				{
					Bus.Ask(new Packet
					{
						Op = action,
						Id = ((NetworkBehaviour)val2).NetworkObjectId,
						Actor = ((NetworkBehaviour)val2).NetworkBehaviourId
					});
				}
			}
		}
	}
	[HarmonyPatch(typeof(Shovel), "HitShovel")]
	internal static class ShovelHit
	{
		private static void Postfix(Shovel __instance, bool cancel)
		{
			if (!cancel && ((NetworkBehaviour)__instance).IsOwner)
			{
				Plugin.Action(((GrabbableObject)__instance).playerHeldBy, 1);
			}
		}
	}
	[HarmonyPatch(typeof(GrabbableObject), "UseItemOnClient")]
	internal static class KeyUseEntrance
	{
		[HarmonyPriority(800)]
		private static bool Prefix(GrabbableObject __instance, bool __0)
		{
			KeyItem val = (KeyItem)(object)((__instance is KeyItem) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			KeyInput.Use(val, __0);
			return false;
		}
	}
	[HarmonyPatch(typeof(KeyItem), "ItemActivate")]
	internal static class KeyLock
	{
		[HarmonyPriority(800)]
		private static bool Prefix(KeyItem __instance, bool __1)
		{
			KeyInput.Use(__instance, __1);
			return false;
		}
	}
	internal static class KeyInput
	{
		private static readonly KeyPressGate Gate = new KeyPressGate();

		internal static void Notify(string text)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("钥匙", text, false, false, "LC_Tip1");
			}
		}

		internal static void Use(KeyItem key, bool down)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!down)
			{
				return;
			}
			PlayerControllerB playerHeldBy = ((GrabbableObject)key).playerHeldBy;
			if ((Object)(object)playerHeldBy == (Object)null || !((NetworkBehaviour)key).IsOwner || (Object)(object)playerHeldBy.currentlyHeldObjectServer != (Object)(object)key || !Gate.Accept(((Object)key).GetInstanceID(), down, Time.unscaledTime))
			{
				return;
			}
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(((Component)playerHeldBy.gameplayCamera).transform.position, ((Component)playerHeldBy.gameplayCamera).transform.forward, ref val, 3f, 2816, (QueryTriggerInteraction)0))
			{
				Plugin.KeyLog("Key use: no native ray hit");
				return;
			}
			DoorLock val2 = Plugin.FindDoor(((RaycastHit)(ref val)).collider);
			Plugin.KeyLog("Key use: collider=" + ((Object)((RaycastHit)(ref val)).collider).name + " door=" + (((Object)(object)val2 == (Object)null) ? "none" : ((Object)val2).name) + " locked=" + ((Object)(object)val2 != (Object)null && val2.isLocked) + " opened=" + ((Object)(object)val2 != (Object)null && Plugin.Opened(val2)) + " itemType=" + ((object)key).GetType().FullName);
			if (!((Object)(object)val2 == (Object)null))
			{
				if (Plugin.Broken(val2))
				{
					Notify("门锁已损坏,无法上锁");
					return;
				}
				if (!val2.isLocked && Plugin.Opened(val2))
				{
					Notify("请先关门再上锁");
					return;
				}
				if (Plugin.Bus == null || !Plugin.Bus.Ready || !((NetworkBehaviour)val2).IsSpawned)
				{
					Plugin.KeyLog("Key use rejected: network or door not ready");
					Notify("门尚未准备好,请稍后再试");
					return;
				}
				Plugin.KeyLog("Key request: " + (val2.isLocked ? "UNLOCK" : "LOCK") + " door=" + ((NetworkBehaviour)val2).NetworkObjectId + ":" + ((NetworkBehaviour)val2).NetworkBehaviourId);
				Plugin.AskKey(val2, val2.isLocked ? 3 : 2);
			}
		}
	}
	[HarmonyPatch(typeof(DoorLock), "OpenOrCloseDoor")]
	internal static class LockedDoorCannotOpen
	{
		private static bool Prefix(DoorLock __instance)
		{
			return !__instance.isLocked;
		}
	}
	[HarmonyPatch(typeof(DoorLock), "SetDoorAsOpen")]
	internal static class LockedDoorSetState
	{
		private static void Prefix(DoorLock __instance, ref bool __0)
		{
			if (__instance.isLocked)
			{
				__0 = false;
			}
		}
	}
	[HarmonyPatch(typeof(AnimatedObjectTrigger), "SetBoolOnClientOnly")]
	internal static class LockedDoorSetAnimation
	{
		private static void Prefix(AnimatedObjectTrigger __instance, ref bool __0)
		{
			DoorLock component = ((Component)__instance).GetComponent<DoorLock>();
			if ((Object)(object)component != (Object)null && component.isLocked)
			{
				__0 = false;
			}
		}
	}
	[HarmonyPatch(typeof(DoorLock), "LockDoor")]
	internal static class NoRelock
	{
		private static bool Prefix(DoorLock __instance)
		{
			return !Plugin.Broken(__instance);
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "ShipHasLeft")]
	internal static class Clear
	{
		private static void Postfix()
		{
			Plugin.States.Clear();
		}
	}
	[HarmonyPatch(typeof(AnimatedObjectTrigger), "TriggerAnimation")]
	internal static class LockedDoorAnimation
	{
		private static bool Prefix(AnimatedObjectTrigger __instance)
		{
			DoorLock component = ((Component)__instance).GetComponent<DoorLock>();
			if (!((Object)(object)component == (Object)null))
			{
				return !component.isLocked;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(AnimatedObjectTrigger), "TriggerAnimationNonPlayer")]
	internal static class LockedEnemyDoorAnimation
	{
		private static bool Prefix(AnimatedObjectTrigger __instance)
		{
			DoorLock component = ((Component)__instance).GetComponent<DoorLock>();
			if (!((Object)(object)component == (Object)null))
			{
				return !component.isLocked;
			}
			return true;
		}
	}
	internal static class WeaponAdapters
	{
		private static readonly string[] Known = new string[3] { "UsualScrap.Behaviors.CrowbarScript", "UsualScrap.Behaviors.ScissorsScript", "UsualScrap.Behaviors.SizableScissorsScript" };

		internal static int Force(GrabbableObject item)
		{
			Shovel val = (Shovel)(object)((item is Shovel) ? item : null);
			if ((Object)(object)val != (Object)null)
			{
				return Plugin.ShovelForce(val);
			}
			if ((Object)(object)item == (Object)null || Array.IndexOf<string>(Known, ((object)item).GetType().FullName) < 0)
			{
				return 0;
			}
			FieldInfo fieldInfo = AccessTools.Field(((object)item).GetType(), "meleeWeaponHitForce");
			if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(int)))
			{
				return 0;
			}
			return Math.Max(0, (int)fieldInfo.GetValue(item));
		}

		internal static void Install()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			Harmony val = new Harmony("hjm.doortools.weaponadapters");
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				string[] known = Known;
				foreach (string name in known)
				{
					Type type = assembly.GetType(name, throwOnError: false);
					if (!(type == null))
					{
						MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "HitMeleeWeapon", new Type[1] { typeof(bool) }, (Type[])null);
						if (methodInfo != null)
						{
							val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(WeaponAdapters), "AfterHit", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						}
					}
				}
			}
		}

		private static void AfterHit(GrabbableObject __instance, bool __0)
		{
			if (!__0 && ((NetworkBehaviour)__instance).IsOwner)
			{
				Plugin.Action(__instance.playerHeldBy, 1);
			}
		}
	}
}