Decompiled source of PairedDrawbridges v0.1.3

BepInEx/plugins/PairedDrawbridges/PairedDrawbridges.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SmeagsMods")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyInformationalVersion("0.1.2")]
[assembly: AssemblyProduct("PairedDrawbridges")]
[assembly: AssemblyTitle("PairedDrawbridges")]
[assembly: AssemblyVersion("0.1.2.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 PairedDrawbridges
{
	[HarmonyPatch(typeof(Player), "PieceRayTest")]
	internal static class AimPlacement
	{
		private static void Postfix(Player __instance, bool water, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface, GameObject ___m_placementGhost, int ___m_manualSnapPoint, int ___m_placeRayMask, Transform ___m_eye, bool ___m_altPlace, ref bool __result)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			if (water || (Object)(object)___m_placementGhost == (Object)null || ___m_manualSnapPoint < 0 || (Object)(object)GameCamera.instance == (Object)null)
			{
				return;
			}
			bool num;
			if (!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive())
			{
				if (ZInput.GetButton("AltPlace"))
				{
					return;
				}
				if (!ZInput.GetButton("JoyAltPlace"))
				{
					goto IL_0060;
				}
				num = !ZInput.GetButton("JoyRotate");
			}
			else
			{
				num = ___m_altPlace;
			}
			if (num)
			{
				return;
			}
			goto IL_0060;
			IL_0060:
			Piece component = ___m_placementGhost.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null || FreeEndSnapping.Kind(((Component)component).gameObject) == 0)
			{
				return;
			}
			List<Transform> list = new List<Transform>();
			component.GetSnapPoints(list);
			if (___m_manualSnapPoint >= list.Count || (Object)(object)list[___m_manualSnapPoint] != (Object)(object)FreeEndSnapping.Ensure(component))
			{
				return;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, ___m_placeRayMask) || (Object)(object)((RaycastHit)(ref val)).collider == (Object)null || ((RaycastHit)(ref val)).collider.isTrigger)
			{
				return;
			}
			Piece componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent == (Object)null || FreeEndSnapping.Kind(((Component)componentInParent).gameObject) == 0)
			{
				return;
			}
			ZNetView component2 = ((Component)componentInParent).GetComponent<ZNetView>();
			if ((Object)(object)component2 == (Object)null || !component2.IsValid() || (Object)(object)((Component)componentInParent).GetComponent<Door>() == (Object)null)
			{
				return;
			}
			Rigidbody attachedRigidbody = ((RaycastHit)(ref val)).collider.attachedRigidbody;
			if (!((Object)(object)attachedRigidbody != (Object)null) || (attachedRigidbody.isKinematic && !((Object)(object)((Component)attachedRigidbody).transform != (Object)(object)((Component)componentInParent).transform.Find("door"))))
			{
				float num2 = __instance.m_maxPlaceDistance + (float)component.m_extraPlacementDistance;
				Transform val2 = FreeEndSnapping.Ensure(componentInParent);
				if (!((Object)(object)val2 == (Object)null) && !(Vector3.Distance(___m_eye.position, ((RaycastHit)(ref val)).point) >= num2) && !(Vector3.Distance(___m_eye.position, val2.position) >= num2))
				{
					point = val2.position;
					normal = ((Component)componentInParent).transform.up;
					piece = componentInParent;
					heightmap = null;
					waterSurface = null;
					__result = true;
				}
			}
		}
	}
	public sealed class BridgePose
	{
		public string Id = "";

		public int Kind;

		public Vector3 Tip;

		public Vector3 Left;

		public Vector3 Right;

		public Vector3 Out;

		public Vector3 Up;

		public bool Valid = true;
	}
	public static class PairRules
	{
		public const float HorizontalTolerance = 0.25f;

		public const float HeightTolerance = 0.15f;

		public const float FacingDot = -0.9986295f;

		public const float UpDot = 0.99939084f;

		private static bool Finite(Vector3 v)
		{
			if (!float.IsNaN(v.X + v.Y + v.Z))
			{
				return !float.IsInfinity(v.X + v.Y + v.Z);
			}
			return false;
		}

		private static bool Close(Vector3 a, Vector3 b)
		{
			Vector3 vector = a - b;
			if (Math.Abs(vector.Y) <= 0.15f)
			{
				return vector.X * vector.X + vector.Z * vector.Z <= 0.0625f;
			}
			return false;
		}

		public static bool Connects(BridgePose a, BridgePose b)
		{
			if (!a.Valid || !b.Valid || a.Id == b.Id || a.Kind != b.Kind || !Finite(a.Tip) || !Finite(b.Tip) || !Finite(a.Left) || !Finite(a.Right) || !Finite(b.Left) || !Finite(b.Right) || !Finite(a.Out) || !Finite(b.Out) || !Finite(a.Up) || !Finite(b.Up))
			{
				return false;
			}
			if (Math.Abs(a.Out.LengthSquared() - 1f) > 0.001f || Math.Abs(b.Out.LengthSquared() - 1f) > 0.001f || Math.Abs(a.Up.LengthSquared() - 1f) > 0.001f || Math.Abs(b.Up.LengthSquared() - 1f) > 0.001f)
			{
				return false;
			}
			if (a.Up.Y >= 0.99939084f && b.Up.Y >= 0.99939084f && Vector3.Dot(a.Up, b.Up) >= 0.99939084f && Vector3.Dot(a.Out, b.Out) <= -0.9986295f && Close(a.Tip, b.Tip) && Close(a.Left, b.Right))
			{
				return Close(a.Right, b.Left);
			}
			return false;
		}

		public static BridgePose FindPartner(BridgePose source, IReadOnlyList<BridgePose> all)
		{
			BridgePose bridgePose = null;
			foreach (BridgePose item in all)
			{
				if (Connects(source, item))
				{
					if (bridgePose != null)
					{
						return null;
					}
					bridgePose = item;
				}
			}
			if (bridgePose == null)
			{
				return null;
			}
			int num = 0;
			foreach (BridgePose item2 in all)
			{
				if (Connects(bridgePose, item2))
				{
					num++;
				}
			}
			if (num != 1)
			{
				return null;
			}
			return bridgePose;
		}

		public static bool Lowered(int nativeState)
		{
			return nativeState != 0;
		}

		public static bool TargetForInteraction(int sourceState)
		{
			return !Lowered(sourceState);
		}

		public static bool NeedsChange(int currentState, bool targetLowered)
		{
			return Lowered(currentState) != targetLowered;
		}

		public static bool Fresh(long now, long issued, long lastApplied)
		{
			if (issued > lastApplied && issued <= now + 10000000)
			{
				return issued >= now - 20000000;
			}
			return false;
		}
	}
	[BepInPlugin("SmeagsMods.PairedDrawbridges", "Paired Drawbridges", "0.1.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Door), "Awake")]
		private static class RegisterBridge
		{
			private static void Postfix(Door __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && BridgeAgent.Kind(component.GetZDO().GetPrefab()) != 0 && (Object)(object)((Component)__instance).GetComponent<BridgeAgent>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<BridgeAgent>();
				}
			}
		}

		[HarmonyPatch(typeof(Door), "Interact")]
		private static class ValidatePairAccess
		{
			private static bool Prefix(Door __instance, Humanoid character, bool hold, ref bool __result)
			{
				//IL_004c: 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)
				if (hold)
				{
					return true;
				}
				BridgeAgent component = ((Component)__instance).GetComponent<BridgeAgent>();
				BridgeAgent bridgeAgent = component?.Partner();
				if ((Object)(object)bridgeAgent == (Object)null)
				{
					return true;
				}
				if ((Object)(object)character != (Object)(object)Player.m_localPlayer || !component.Ready() || !bridgeAgent.Ready())
				{
					__result = false;
					return false;
				}
				if (!PrivateArea.CheckAccess(((Component)component).transform.position, 0f, true, false) || !PrivateArea.CheckAccess(((Component)bridgeAgent).transform.position, 0f, true, false))
				{
					__result = true;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Door), "Open")]
		private static class RoutePairCommand
		{
			private static bool Prefix(Door __instance)
			{
				BridgeAgent component = ((Component)__instance).GetComponent<BridgeAgent>();
				BridgeAgent bridgeAgent = component?.Partner();
				if ((Object)(object)bridgeAgent == (Object)null)
				{
					return true;
				}
				component.Request(bridgeAgent);
				return false;
			}
		}

		public const string Guid = "SmeagsMods.PairedDrawbridges";

		private Harmony harmony;

		internal static readonly HashSet<BridgeAgent> Bridges = new HashSet<BridgeAgent>();

		internal static readonly MethodInfo CanInteract = AccessTools.Method(typeof(Door), "CanInteract", (Type[])null, (Type[])null);

		internal static readonly MethodInfo UseDoor = AccessTools.Method(typeof(Door), "RPC_UseDoor", (Type[])null, (Type[])null);

		internal static readonly MethodInfo WardEnabled = AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null);

		internal static readonly MethodInfo WardInside = AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null);

		internal static readonly MethodInfo WardPermitted = AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null);

		internal static readonly FieldInfo Wards = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		private void Awake()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			if (CanInteract == null || UseDoor == null || WardEnabled == null || WardInside == null || WardPermitted == null || Wards == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Unsupported game API; Paired Drawbridges is disabled.");
				return;
			}
			harmony = new Harmony("SmeagsMods.PairedDrawbridges");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Paired Drawbridges 0.1.2 loaded. Requires matching mod on every client and server.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	public sealed class BridgeAgent : MonoBehaviour
	{
		private const string RequestRpc = "SmeagsPD_Request_v1";

		private const string ApplyRpc = "SmeagsPD_Apply_v1";

		private static readonly int BusyKey = StringExtensionMethods.GetStableHashCode("SmeagsPD_BusyUntil_v1");

		private static readonly int RequestKey = StringExtensionMethods.GetStableHashCode("SmeagsPD_LastRequest_v1");

		private static readonly int ApplyKey = StringExtensionMethods.GetStableHashCode("SmeagsPD_LastApply_v1");

		private static readonly int LargeHash = StringExtensionMethods.GetStableHashCode("piece_drawbridge");

		private static readonly int LogHash = StringExtensionMethods.GetStableHashCode("piece_drawbridge_log");

		private ZNetView view;

		private Door door;

		private float lastLocalRequest = -10f;

		private long Now => ZNet.instance.GetTime().Ticks;

		private string Id => ((object)Unsafe.As<ZDOID, ZDOID>(ref view.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString();

		private int State => view.GetZDO().GetInt(ZDOVars.s_state, 0);

		private bool Valid
		{
			get
			{
				if ((Object)(object)view != (Object)null && view.IsValid() && ((Behaviour)this).isActiveAndEnabled && (Object)(object)door != (Object)null && ((Behaviour)door).enabled && (Object)(object)door.m_keyItem == (Object)null && !door.m_canNotBeClosed)
				{
					return door.m_checkGuardStone;
				}
				return false;
			}
		}

		internal static int Kind(int prefab)
		{
			if (prefab != LargeHash)
			{
				if (prefab != LogHash)
				{
					return 0;
				}
				return 2;
			}
			return 1;
		}

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			door = ((Component)this).GetComponent<Door>();
			if (!((Object)(object)view == (Object)null) && view.IsValid())
			{
				view.Register<ZPackage>("SmeagsPD_Request_v1", (Action<long, ZPackage>)OnRequest);
				view.Register<ZPackage>("SmeagsPD_Apply_v1", (Action<long, ZPackage>)OnApply);
				Plugin.Bridges.Add(this);
			}
		}

		private void OnDestroy()
		{
			Plugin.Bridges.Remove(this);
		}

		internal bool Ready()
		{
			if (Valid)
			{
				return (bool)Plugin.CanInteract.Invoke(door, null);
			}
			return false;
		}

		internal BridgePose Pose()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_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_006c: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			int num = (Valid ? Kind(view.GetZDO().GetPrefab()) : 0);
			Vector3 val = BridgeGeometry.Tip(num);
			float num2 = BridgeGeometry.HalfWidth(num);
			Vector3 lossyScale = ((Component)this).transform.lossyScale;
			BridgePose obj = new BridgePose
			{
				Id = ((num == 0) ? "invalid" : Id),
				Kind = num
			};
			int valid;
			if (num != 0)
			{
				Vector3 val2 = lossyScale - Vector3.one;
				valid = ((((Vector3)(ref val2)).sqrMagnitude < 1E-06f) ? 1 : 0);
			}
			else
			{
				valid = 0;
			}
			obj.Valid = (byte)valid != 0;
			obj.Tip = Vec(((Component)this).transform.TransformPoint(val));
			obj.Left = Vec(((Component)this).transform.TransformPoint(val + new Vector3(0f, 0f, 0f - num2)));
			obj.Right = Vec(((Component)this).transform.TransformPoint(val + new Vector3(0f, 0f, num2)));
			obj.Out = Vec(((Component)this).transform.right);
			obj.Up = Vec(((Component)this).transform.up);
			return obj;
		}

		private static Vector3 Vec(Vector3 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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)
			return new Vector3(v.x, v.y, v.z);
		}

		internal BridgeAgent Partner()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			List<BridgePose> list = new List<BridgePose>();
			Dictionary<string, BridgeAgent> dictionary = new Dictionary<string, BridgeAgent>();
			foreach (BridgeAgent bridge in Plugin.Bridges)
			{
				if (!((Object)(object)bridge == (Object)null) && bridge.Valid)
				{
					BridgePose bridgePose = bridge.Pose();
					list.Add(bridgePose);
					dictionary[bridgePose.Id] = bridge;
				}
			}
			BridgePose bridgePose2 = PairRules.FindPartner(Pose(), list);
			if (bridgePose2 == null || !dictionary.TryGetValue(bridgePose2.Id, out var value))
			{
				return null;
			}
			if (!ZNetScene.instance.IsAreaReady(((Component)this).transform.position) || !ZNetScene.instance.IsAreaReady(((Component)value).transform.position))
			{
				return null;
			}
			return value;
		}

		private static BridgeAgent Coordinator(BridgeAgent a, BridgeAgent b)
		{
			if (StringComparer.Ordinal.Compare(a.Id, b.Id) >= 0)
			{
				return b;
			}
			return a;
		}

		private static BridgeAgent Find(ZDOID id)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(id) : null);
			if (!((Object)(object)val == (Object)null))
			{
				return val.GetComponent<BridgeAgent>();
			}
			return null;
		}

		private static Player FindPlayer(ZDOID id, long peer)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(id) : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ZNetView component = val.GetComponent<ZNetView>();
			if (!((Object)(object)component != (Object)null) || !component.IsValid() || component.GetZDO().GetOwner() != peer)
			{
				return null;
			}
			return val.GetComponent<Player>();
		}

		internal void Request(BridgeAgent partner)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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)
			if (!((Object)(object)Player.m_localPlayer == (Object)null) && !(Time.realtimeSinceStartup - lastLocalRequest < 0.3f) && Ready() && partner.Ready() && PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false) && PrivateArea.CheckAccess(((Component)partner).transform.position, 0f, true, false))
			{
				ZNetView component = ((Component)Player.m_localPlayer).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid())
				{
					lastLocalRequest = Time.realtimeSinceStartup;
					ZPackage val = new ZPackage();
					val.Write(view.GetZDO().m_uid);
					val.Write(partner.view.GetZDO().m_uid);
					val.Write(component.GetZDO().m_uid);
					val.Write(PairRules.Lowered(State));
					val.Write(Now);
					Coordinator(this, partner).view.InvokeRPC("SmeagsPD_Request_v1", new object[1] { val });
				}
			}
		}

		private static bool HasAccess(Player actor, Vector3 position)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			long playerID = actor.GetPlayerID();
			if (playerID == 0L)
			{
				return false;
			}
			bool flag = false;
			foreach (PrivateArea item in (List<PrivateArea>)Plugin.Wards.GetValue(null))
			{
				if (!((Object)(object)item == (Object)null) && (bool)Plugin.WardEnabled.Invoke(item, null) && (bool)Plugin.WardInside.Invoke(item, new object[2] { position, 0f }))
				{
					Piece component = ((Component)item).GetComponent<Piece>();
					if (((Object)(object)component != (Object)null && component.GetCreator() == playerID) || (bool)Plugin.WardPermitted.Invoke(item, new object[1] { playerID }))
					{
						return true;
					}
					flag = true;
				}
			}
			return !flag;
		}

		private void OnRequest(long sender, ZPackage pkg)
		{
			//IL_0017: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid || !view.IsOwner())
			{
				return;
			}
			ZDOID id = pkg.ReadZDOID();
			ZDOID id2 = pkg.ReadZDOID();
			ZDOID val = pkg.ReadZDOID();
			bool flag = pkg.ReadBool();
			long num = pkg.ReadLong();
			long now = Now;
			ZDO zDO = view.GetZDO();
			if (now >= zDO.GetLong(BusyKey, 0L) && PairRules.Fresh(now, num, zDO.GetLong(RequestKey, 0L)))
			{
				BridgeAgent bridgeAgent = Find(id);
				BridgeAgent bridgeAgent2 = Find(id2);
				Player val2 = FindPlayer(val, sender);
				if (!((Object)(object)bridgeAgent == (Object)null) && !((Object)(object)bridgeAgent2 == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)bridgeAgent.Partner() != (Object)(object)bridgeAgent2) && !((Object)(object)Coordinator(bridgeAgent, bridgeAgent2) != (Object)(object)this) && bridgeAgent.Ready() && bridgeAgent2.Ready() && PairRules.Lowered(bridgeAgent.State) == flag && !(Vector3.Distance(((Component)val2).transform.position, ((Component)bridgeAgent).transform.position) > 10f) && HasAccess(val2, ((Component)bridgeAgent).transform.position) && HasAccess(val2, ((Component)bridgeAgent2).transform.position))
				{
					zDO.Set(RequestKey, num);
					zDO.Set(BusyKey, now + 30000000);
					bool lowered = !flag;
					SendApply(bridgeAgent, bridgeAgent2, val, sender, lowered, now);
					SendApply(bridgeAgent2, bridgeAgent, val, sender, lowered, now);
				}
			}
		}

		private void SendApply(BridgeAgent target, BridgeAgent other, ZDOID actor, long actorPeer, bool lowered, long issued)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(view.GetZDO().m_uid);
			val.Write(other.view.GetZDO().m_uid);
			val.Write(actor);
			val.Write(actorPeer);
			val.Write(lowered);
			val.Write(issued);
			target.view.InvokeRPC("SmeagsPD_Apply_v1", new object[1] { val });
		}

		private void OnApply(long sender, ZPackage pkg)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid || !view.IsOwner())
			{
				return;
			}
			BridgeAgent bridgeAgent = Find(pkg.ReadZDOID());
			BridgeAgent bridgeAgent2 = Find(pkg.ReadZDOID());
			ZDOID id = pkg.ReadZDOID();
			long num = pkg.ReadLong();
			bool targetLowered = pkg.ReadBool();
			long num2 = pkg.ReadLong();
			if ((Object)(object)bridgeAgent == (Object)null || (Object)(object)bridgeAgent2 == (Object)null || !bridgeAgent.Valid || bridgeAgent.view.GetZDO().GetOwner() != sender || (Object)(object)Coordinator(this, bridgeAgent2) != (Object)(object)bridgeAgent || (Object)(object)Partner() != (Object)(object)bridgeAgent2 || !PairRules.Fresh(Now, num2, view.GetZDO().GetLong(ApplyKey, 0L)))
			{
				return;
			}
			Player val = FindPlayer(id, num);
			if ((Object)(object)val == (Object)null || !HasAccess(val, ((Component)this).transform.position) || !HasAccess(val, ((Component)bridgeAgent2).transform.position))
			{
				return;
			}
			if (PairRules.NeedsChange(State, targetLowered))
			{
				if (!Ready())
				{
					return;
				}
				Plugin.UseDoor.Invoke(door, new object[2] { num, true });
			}
			view.GetZDO().Set(ApplyKey, num2);
		}
	}
	internal static class BridgeGeometry
	{
		internal static Vector3 Tip(int kind)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (kind != 1)
			{
				return new Vector3(5.916488f, -0.1687252f, 0f);
			}
			return new Vector3(9.558413f, 0.4232784f, 0f);
		}

		internal static float HalfWidth(int kind)
		{
			if (kind != 1)
			{
				return 1.126295f;
			}
			return 2.2754803f;
		}
	}
	public sealed class FreeEndSnapMarker : MonoBehaviour
	{
	}
	internal static class FreeEndSnapping
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class InitializePrefabs
		{
			private static void Postfix(ZNetScene __instance)
			{
				string[] array = new string[2] { "piece_drawbridge", "piece_drawbridge_log" };
				foreach (string text in array)
				{
					GameObject prefab = __instance.GetPrefab(text);
					if ((Object)(object)prefab != (Object)null)
					{
						Ensure(prefab.GetComponent<Piece>());
					}
				}
			}
		}

		[HarmonyPatch(typeof(Piece), "Awake")]
		private static class InitializeInstance
		{
			private static void Postfix(Piece __instance)
			{
				Ensure(__instance);
			}
		}

		[HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[] { typeof(List<Transform>) })]
		private static class BeforeSnapEnumeration
		{
			private static void Prefix(Piece __instance)
			{
				Ensure(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "FindClosestSnapPoints")]
		private static class FindRaisedFreeEnd
		{
			private static void Postfix(Transform ghost, float maxSnapDistance, ref Transform a, ref Transform b, List<Piece> pieces, int ___m_manualSnapPoint, ref bool __result)
			{
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
				if (__result || (Object)(object)ghost == (Object)null || Kind(((Component)ghost).gameObject) == 0)
				{
					return;
				}
				Transform val = Ensure(((Component)ghost).GetComponent<Piece>());
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				if (___m_manualSnapPoint >= 0)
				{
					List<Transform> list = new List<Transform>();
					((Component)ghost).GetComponent<Piece>().GetSnapPoints(list);
					if (___m_manualSnapPoint >= list.Count || (Object)(object)list[___m_manualSnapPoint] != (Object)(object)val)
					{
						return;
					}
				}
				List<Piece> list2 = new List<Piece>();
				Piece.GetAllPiecesInRadius(val.position, 12f, list2);
				Transform val2 = null;
				Piece item = null;
				float num = maxSnapDistance;
				foreach (Piece item2 in list2)
				{
					if (!((Object)(object)item2 == (Object)null) && !((Object)(object)((Component)item2).transform == (Object)(object)ghost) && Kind(((Component)item2).gameObject) != 0)
					{
						Transform val3 = Ensure(item2);
						float num2 = Vector3.Distance(val.position, val3.position);
						if (num2 < num)
						{
							num = num2;
							val2 = val3;
							item = item2;
						}
					}
				}
				if (!((Object)(object)val2 == (Object)null))
				{
					a = val;
					b = val2;
					if (!pieces.Contains(item))
					{
						pieces.Add(item);
					}
					__result = true;
				}
			}
		}

		internal static int Kind(GameObject go)
		{
			ZNetView component = go.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				return BridgeAgent.Kind(component.GetZDO().GetPrefab());
			}
			string text = ((Object)go).name;
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = text.Substring(0, text.Length - "(Clone)".Length);
			}
			return BridgeAgent.Kind(StringExtensionMethods.GetStableHashCode(text));
		}

		internal static Transform Ensure(Piece piece)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)piece == (Object)null)
			{
				return null;
			}
			int num = Kind(((Component)piece).gameObject);
			if (num == 0)
			{
				return null;
			}
			Transform transform = ((Component)piece).transform;
			Vector3 val = BridgeGeometry.Tip(num);
			Transform val2 = null;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				if (((Component)child).CompareTag("snappoint"))
				{
					Vector3 val3 = child.localPosition - val;
					if (((Vector3)(ref val3)).sqrMagnitude < 1E-06f)
					{
						return child;
					}
				}
				if ((Object)(object)((Component)child).GetComponent<FreeEndSnapMarker>() != (Object)null)
				{
					val2 = child;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				GameObject val4 = new GameObject("Free end");
				val4.transform.SetParent(transform, false);
				val4.AddComponent<FreeEndSnapMarker>();
				val2 = val4.transform;
			}
			val2.localPosition = val;
			val2.localRotation = Quaternion.identity;
			val2.localScale = Vector3.one;
			((Component)val2).gameObject.tag = "snappoint";
			return val2;
		}
	}
}