Decompiled source of Cofferforge v0.1.2

plugins/Cofferforge/Cofferforge.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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: InternalsVisibleTo("Cofferforge.Harness")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Cofferforge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("Cofferforge")]
[assembly: AssemblyTitle("Cofferforge")]
[assembly: AssemblyVersion("0.1.1.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 Cofferforge
{
	internal static class ChestContact
	{
		private static readonly Collider[] Nearby = (Collider[])(object)new Collider[128];

		private static readonly MethodInfo NativeQuery = AccessTools.Method(typeof(Physics), "OverlapBoxNonAlloc", new Type[5]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(Collider[]),
			typeof(Quaternion),
			typeof(int)
		}, (Type[])null);

		internal static IEnumerable<CodeInstruction> ReplaceQuery(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			if (list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, NativeQuery)) != 1)
			{
				throw new InvalidOperationException("Expected one native support overlap query");
			}
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, NativeQuery))
				{
					yield return new CodeInstruction(item)
					{
						opcode = OpCodes.Ldarg_0,
						operand = null
					};
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ChestContact), "Query", (Type[])null, (Type[])null));
				}
				else
				{
					yield return item;
				}
			}
		}

		internal static int Query(Vector3 center, Vector3 halfSize, Collider[] results, Quaternion rotation, int mask, WearNTear receiver)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.OverlapBoxNonAlloc(center, halfSize, results, rotation, mask);
			if (!Plugin.Ready || num >= results.Length || !ChestSnaps.IsChest(((Component)receiver).gameObject) || !ChestSnaps.CachedBounds(((Component)receiver).gameObject, out var bounds))
			{
				return num;
			}
			if (Vector3.Dot(((Component)receiver).transform.up, Vector3.up) < 0.9999f)
			{
				return num;
			}
			int num2 = Physics.OverlapBoxNonAlloc(center - Vector3.up * 0.5f, halfSize + Vector3.up * 0.5f, Nearby, rotation, mask);
			if (num2 == Nearby.Length)
			{
				Array.Clear(Nearby, 0, num2);
				return num;
			}
			for (int i = 0; i < num2; i++)
			{
				if (num >= results.Length)
				{
					break;
				}
				Collider val = Nearby[i];
				if (!Object.op_Implicit((Object)(object)val) || val.isTrigger || Object.op_Implicit((Object)(object)val.attachedRigidbody))
				{
					continue;
				}
				WearNTear componentInParent = ((Component)val).GetComponentInParent<WearNTear>();
				if (!Object.op_Implicit((Object)(object)componentInParent) || (Object)(object)componentInParent == (Object)(object)receiver || !ChestSnaps.IsChest(((Component)componentInParent).gameObject) || !ChestSnaps.CachedBounds(((Component)componentInParent).gameObject, out var bounds2) || !Touches(((Component)componentInParent).transform, bounds2, ((Component)receiver).transform, bounds))
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < num; j++)
				{
					if ((Object)(object)results[j] == (Object)(object)val)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					results[num++] = val;
				}
			}
			Array.Clear(Nearby, 0, num2);
			return num;
		}

		internal static bool Touches(Transform lower, Bounds lb, Transform upper, Bounds ub)
		{
			//IL_0001: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00be: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00dd: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Dot(lower.up, Vector3.up) < 0.9999f || Vector3.Dot(upper.up, Vector3.up) < 0.9999f)
			{
				return false;
			}
			float y = lower.TransformPoint(new Vector3(((Bounds)(ref lb)).center.x, ((Bounds)(ref lb)).max.y, ((Bounds)(ref lb)).center.z)).y;
			float y2 = upper.TransformPoint(new Vector3(((Bounds)(ref ub)).center.x, ((Bounds)(ref ub)).min.y, ((Bounds)(ref ub)).center.z)).y;
			if (Mathf.Abs(y - y2) > 0.025f)
			{
				return false;
			}
			Vector3 delta = upper.TransformPoint(((Bounds)(ref ub)).center) - lower.TransformPoint(((Bounds)(ref lb)).center);
			delta.y = 0f;
			if (Overlaps(lower.right, delta, lower, lb, upper, ub) && Overlaps(lower.forward, delta, lower, lb, upper, ub) && Overlaps(upper.right, delta, lower, lb, upper, ub))
			{
				return Overlaps(upper.forward, delta, lower, lb, upper, ub);
			}
			return false;
		}

		private static bool Overlaps(Vector3 axis, Vector3 delta, Transform a, Bounds ab, Transform b, Bounds bb)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0030: 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_003f: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0069: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0091: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Abs(Vector3.Dot(axis, a.TransformVector(Vector3.right * ((Bounds)(ref ab)).extents.x))) + Mathf.Abs(Vector3.Dot(axis, a.TransformVector(Vector3.forward * ((Bounds)(ref ab)).extents.z)));
			float num2 = Mathf.Abs(Vector3.Dot(axis, b.TransformVector(Vector3.right * ((Bounds)(ref bb)).extents.x))) + Mathf.Abs(Vector3.Dot(axis, b.TransformVector(Vector3.forward * ((Bounds)(ref bb)).extents.z)));
			return Mathf.Abs(Vector3.Dot(axis, delta)) < num + num2 - 0.01f;
		}
	}
	internal static class ChestSnaps
	{
		internal const string Prefix = "Cofferforge ";

		private static readonly Dictionary<string, string> Names = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			{ "piece_chest_wood", "$piece_chestwood" },
			{ "piece_chest", "$piece_chest" },
			{ "piece_chest_private", "$piece_chestprivate" },
			{ "piece_chest_blackmetal", "$piece_chestblackmetal" },
			{ "piece_chest_grausten", "$piece_chestgrausten" },
			{ "piece_chest_barrel", "$piece_chestbarrel" },
			{ "piece_chest_warderobe", "$piece_chestwarderobe" }
		};

		private static readonly Dictionary<Piece, List<Transform>> Owned = new Dictionary<Piece, List<Transform>>();

		private static readonly Dictionary<Piece, Bounds> ClosedBounds = new Dictionary<Piece, Bounds>();

		internal static bool IsChest(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go))
			{
				return false;
			}
			string text = ((Object)go).name;
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = text.Substring(0, text.Length - 7);
			}
			if (!Names.TryGetValue(text, out var value))
			{
				return false;
			}
			Piece component = go.GetComponent<Piece>();
			if (Object.op_Implicit((Object)(object)component) && component.m_enabled && component.m_name == value && Object.op_Implicit((Object)(object)go.GetComponent<Container>()) && Object.op_Implicit((Object)(object)go.GetComponent<WearNTear>()) && component.m_resources != null)
			{
				return component.m_resources.Length != 0;
			}
			return false;
		}

		internal static void Add(Piece piece)
		{
			//IL_004b: 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_00b7: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Ready || !IsChest(((Component)piece).gameObject) || Owned.ContainsKey(piece) || !TryBounds(((Component)piece).transform, out var result))
			{
				return;
			}
			List<Transform> list = new List<Transform>(8);
			Owned.Add(piece, list);
			ClosedBounds.Add(piece, result);
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j < 2; j++)
				{
					for (int k = 0; k < 2; k++)
					{
						GameObject val = new GameObject("Cofferforge " + ((i == 0) ? "bottom" : "top") + " " + j + "/" + k);
						val.transform.SetParent(((Component)piece).transform, false);
						val.transform.localPosition = new Vector3((j == 0) ? ((Bounds)(ref result)).min.x : ((Bounds)(ref result)).max.x, (i == 0) ? ((Bounds)(ref result)).min.y : ((Bounds)(ref result)).max.y, (k == 0) ? ((Bounds)(ref result)).min.z : ((Bounds)(ref result)).max.z);
						val.tag = "snappoint";
						list.Add(val.transform);
					}
				}
			}
		}

		private static bool ActiveUnder(Transform node, Transform root)
		{
			Transform val = node;
			while (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)root)
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					return false;
				}
				val = val.parent;
			}
			return true;
		}

		internal static bool TryBounds(Transform root, out Bounds result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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)
			//IL_011e: 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_005f: 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)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			result = default(Bounds);
			bool found = false;
			Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!val.enabled || val.isTrigger || !ActiveUnder(((Component)val).transform, root))
				{
					continue;
				}
				BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null);
				if (val2 != null)
				{
					Include(root, ((Component)val2).transform, new Bounds(val2.center, val2.size), ref result, ref found);
					continue;
				}
				MeshCollider val3 = (MeshCollider)(object)((val is MeshCollider) ? val : null);
				if (val3 != null && Object.op_Implicit((Object)(object)val3.sharedMesh))
				{
					Include(root, ((Component)val3).transform, val3.sharedMesh.bounds, ref result, ref found);
					continue;
				}
				return false;
			}
			if (!found)
			{
				return false;
			}
			MeshFilter[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val4 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val4.sharedMesh) && ActiveUnder(((Component)val4).transform, root))
				{
					Include(root, ((Component)val4).transform, val4.sharedMesh.bounds, ref result, ref found);
				}
			}
			Vector3 size = ((Bounds)(ref result)).size;
			if (size.x > 0.1f && size.y > 0.1f && size.z > 0.1f && size.x < 10f && size.y < 10f)
			{
				return size.z < 10f;
			}
			return false;
		}

		private static void Include(Transform root, Transform child, Bounds local, ref Bounds result, ref bool found)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			for (int i = 0; i < 8; i++)
			{
				((Vector3)(ref val))..ctor(((i & 1) == 0) ? ((Bounds)(ref local)).min.x : ((Bounds)(ref local)).max.x, ((i & 2) == 0) ? ((Bounds)(ref local)).min.y : ((Bounds)(ref local)).max.y, ((i & 4) == 0) ? ((Bounds)(ref local)).min.z : ((Bounds)(ref local)).max.z);
				val = root.InverseTransformPoint(child.TransformPoint(val));
				if (!found)
				{
					result = new Bounds(val, Vector3.zero);
					found = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val);
				}
			}
		}

		internal static bool CachedBounds(GameObject go, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			Piece component = go.GetComponent<Piece>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return ClosedBounds.TryGetValue(component, out bounds);
			}
			return false;
		}

		internal static void Forget(Piece piece)
		{
			Owned.Remove(piece);
			ClosedBounds.Remove(piece);
		}

		internal static void RemoveAll()
		{
			foreach (KeyValuePair<Piece, List<Transform>> item in Owned)
			{
				foreach (Transform item2 in item.Value)
				{
					if (Object.op_Implicit((Object)(object)item2))
					{
						Object.Destroy((Object)(object)((Component)item2).gameObject);
					}
				}
			}
			Owned.Clear();
			ClosedBounds.Clear();
		}
	}
	[HarmonyPatch(typeof(Piece), "Awake")]
	internal static class PieceAwakePatch
	{
		private static void Postfix(Piece __instance)
		{
			ChestSnaps.Add(__instance);
		}
	}
	[HarmonyPatch(typeof(Piece), "OnDestroy")]
	internal static class PieceDestroyPatch
	{
		private static void Prefix(Piece __instance)
		{
			ChestSnaps.Forget(__instance);
		}
	}
	[BepInPlugin("SmeagsMods.Cofferforge", "Cofferforge", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "SmeagsMods.Cofferforge";

		public const string Name = "Cofferforge";

		public const string Version = "0.1.1";

		internal static bool Ready;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("SmeagsMods.Cofferforge");
			try
			{
				harmony.PatchAll(typeof(Plugin).Assembly);
				Ready = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Cofferforge 0.1.1: chest snap points and scoped chest support enabled.");
			}
			catch (Exception ex)
			{
				Ready = false;
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)("Cofferforge disabled: native patch contract did not match. " + ex));
			}
		}

		private void OnDestroy()
		{
			Ready = false;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			ChestSnaps.RemoveAll();
		}
	}
	internal static class PreviewPlacement
	{
		private delegate bool FindSnap(Player player, Transform ghost, float distance, out Transform source, out Transform target, List<Piece> pieces);

		private delegate bool RayTest(Player player, out Vector3 point, out Vector3 normal, out Piece piece, out Heightmap heightmap, out Collider waterSurface, bool water);

		private static readonly MethodInfo NativeFind = AccessTools.Method(typeof(Player), "FindClosestSnapPoints", (Type[])null, (Type[])null);

		private static readonly FindSnap Find = AccessTools.MethodDelegate<FindSnap>(NativeFind, (object)null, true);

		private static readonly RayTest Ray = AccessTools.MethodDelegate<RayTest>(AccessTools.Method(typeof(Player), "PieceRayTest", (Type[])null, (Type[])null), (object)null, true);

		private static readonly FieldRef<Player, int> Manual = AccessTools.FieldRefAccess<Player, int>("m_manualSnapPoint");

		private static readonly FieldRef<Player, bool> Alt = AccessTools.FieldRefAccess<Player, bool>("m_altPlace");

		private static readonly FieldInfo TiltRestriction = AccessTools.Field(typeof(Piece), "m_notOnTiltingSurface");

		internal static IEnumerable<CodeInstruction> ReplaceFinder(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			if (list.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, NativeFind)) != 1)
			{
				throw new InvalidOperationException("Expected one native placement snap search");
			}
			if (list.Count((CodeInstruction i) => i.opcode == OpCodes.Ldfld && object.Equals(i.operand, TiltRestriction)) != 1)
			{
				throw new InvalidOperationException("Expected one native tilt restriction read");
			}
			foreach (CodeInstruction item in list)
			{
				if (item.opcode == OpCodes.Ldfld && object.Equals(item.operand, TiltRestriction))
				{
					yield return new CodeInstruction(item)
					{
						opcode = OpCodes.Ldarg_0,
						operand = null
					};
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PreviewPlacement), "KeepTiltRestriction", (Type[])null, (Type[])null));
				}
				else
				{
					yield return (CodeInstruction)((!CodeInstructionExtensions.Calls(item, NativeFind)) ? ((object)item) : ((object)new CodeInstruction(item)
					{
						opcode = OpCodes.Call,
						operand = AccessTools.Method(typeof(PreviewPlacement), "FindForPlacement", (Type[])null, (Type[])null)
					}));
				}
			}
		}

		internal static bool KeepTiltRestriction(Piece piece, Player player)
		{
			//IL_0042: 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_00f7: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!piece.m_notOnTiltingSurface)
			{
				return false;
			}
			if (!Plugin.Ready || Manual.Invoke(player) >= 0 || !ChestSnaps.IsChest(((Component)piece).gameObject) || !ChestSnaps.CachedBounds(((Component)piece).gameObject, out var bounds) || Vector3.Dot(((Component)piece).transform.up, Vector3.up) < 0.9999f)
			{
				return true;
			}
			int num;
			if (!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive())
			{
				if (ZInput.GetButton("AltPlace"))
				{
					goto IL_00a3;
				}
				if (!ZInput.GetButton("JoyAltPlace"))
				{
					goto IL_00a5;
				}
				num = ((!ZInput.GetButton("JoyRotate")) ? 1 : 0);
			}
			else
			{
				num = (Alt.Invoke(player) ? 1 : 0);
			}
			if (num != 0)
			{
				goto IL_00a3;
			}
			goto IL_00a5;
			IL_00a3:
			return true;
			IL_00a5:
			if (Ray(player, out var _, out var normal, out var piece2, out var _, out var _, piece.m_waterPiece || piece.m_noInWater) && Object.op_Implicit((Object)(object)piece2) && ChestSnaps.IsChest(((Component)piece2).gameObject) && ChestSnaps.CachedBounds(((Component)piece2).gameObject, out bounds) && Vector3.Dot(((Component)piece2).transform.up, Vector3.up) > 0.9999f)
			{
				return !(Mathf.Abs(normal.y) <= 0.5f);
			}
			return true;
		}

		internal static bool FindForPlacement(Player player, Transform ghost, float distance, out Transform source, out Transform target, List<Piece> pieces)
		{
			//IL_003f: 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_00a8: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Ready && Manual.Invoke(player) < 0 && ChestSnaps.IsChest(((Component)ghost).gameObject) && ChestSnaps.CachedBounds(((Component)ghost).gameObject, out var bounds) && Vector3.Dot(ghost.up, Vector3.up) > 0.9999f)
			{
				Piece component = ((Component)ghost).GetComponent<Piece>();
				if (Ray(player, out var point, out var normal, out var piece, out var _, out var _, component.m_waterPiece || component.m_noInWater))
				{
					bool flag = Object.op_Implicit((Object)(object)piece) && ChestSnaps.IsChest(((Component)piece).gameObject) && Vector3.Dot(((Component)piece).transform.up, Vector3.up) > 0.9999f;
					bool flag2 = flag && normal.y > 0.5f;
					Bounds bounds3;
					if (flag2 || normal.y > 0.9999f)
					{
						if (flag2 && ChestSnaps.CachedBounds(((Component)piece).gameObject, out var bounds2))
						{
							point.y = ((Component)piece).transform.TransformPoint(new Vector3(((Bounds)(ref bounds2)).center.x, ((Bounds)(ref bounds2)).max.y, ((Bounds)(ref bounds2)).center.z)).y;
						}
						ghost.position = point - ghost.TransformVector(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z));
					}
					else if (flag && Mathf.Abs(normal.y) <= 0.5f && ChestSnaps.CachedBounds(((Component)piece).gameObject, out bounds3))
					{
						Vector3 val = ((Component)piece).transform.InverseTransformDirection(normal);
						Vector3 val2 = ((Mathf.Abs(val.x) >= Mathf.Abs(val.z)) ? (Vector3.right * Mathf.Sign(val.x)) : (Vector3.forward * Mathf.Sign(val.z)));
						Vector3 val3 = ((Component)piece).transform.TransformDirection(val2);
						Vector3 normalized = ((Vector3)(ref val3)).normalized;
						float num = Mathf.Abs(Vector3.Dot(normalized, ((Component)piece).transform.TransformVector(Vector3.Scale(val2, ((Bounds)(ref bounds3)).extents))));
						float num2 = Mathf.Abs(Vector3.Dot(normalized, ghost.TransformVector(Vector3.right * ((Bounds)(ref bounds)).extents.x))) + Mathf.Abs(Vector3.Dot(normalized, ghost.TransformVector(Vector3.forward * ((Bounds)(ref bounds)).extents.z)));
						point = ((Component)piece).transform.TransformPoint(((Bounds)(ref bounds3)).center) + normalized * (num + num2);
						point.y = ((Component)piece).transform.TransformPoint(new Vector3(((Bounds)(ref bounds3)).center.x, ((Bounds)(ref bounds3)).min.y, ((Bounds)(ref bounds3)).center.z)).y;
						ghost.position = point - ghost.TransformVector(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z));
					}
				}
			}
			return Find(player, ghost, distance, out source, out target, pieces);
		}
	}
	internal static class SupportPatches
	{
		private static readonly FieldInfo Supports = AccessTools.Field(typeof(WearNTear), "m_supports");

		private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

		internal static bool ForPlacement(WearNTear support, Player player)
		{
			if (support.m_supports)
			{
				return true;
			}
			GameObject val = Ghost.Invoke(player);
			if (Plugin.Ready && Object.op_Implicit((Object)(object)val) && ChestSnaps.IsChest(((Component)support).gameObject))
			{
				return ChestSnaps.IsChest(val);
			}
			return false;
		}

		internal static bool ForStructure(WearNTear support, WearNTear receiver)
		{
			if (!support.m_supports)
			{
				if (Plugin.Ready && ChestSnaps.IsChest(((Component)support).gameObject))
				{
					return ChestSnaps.IsChest(((Component)receiver).gameObject);
				}
				return false;
			}
			return true;
		}

		internal static IEnumerable<CodeInstruction> Replace(IEnumerable<CodeInstruction> instructions, MethodInfo helper, int expectedReads)
		{
			List<CodeInstruction> list = instructions.ToList();
			int num = list.Count((CodeInstruction i) => i.opcode == OpCodes.Ldfld && object.Equals(i.operand, Supports));
			if (num != expectedReads)
			{
				throw new InvalidOperationException("Expected " + expectedReads + " support reads, found " + num);
			}
			foreach (CodeInstruction item in list)
			{
				if (item.opcode == OpCodes.Ldfld && object.Equals(item.operand, Supports))
				{
					yield return new CodeInstruction(item)
					{
						opcode = OpCodes.Ldarg_0,
						operand = null
					};
					yield return new CodeInstruction(OpCodes.Call, (object)helper);
				}
				else
				{
					yield return item;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class PlacementSupportPatch
	{
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return PreviewPlacement.ReplaceFinder(SupportPatches.Replace(instructions, AccessTools.Method(typeof(SupportPatches), "ForPlacement", (Type[])null, (Type[])null), 1));
		}
	}
	[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
	internal static class StructuralSupportPatch
	{
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ChestContact.ReplaceQuery(SupportPatches.Replace(instructions, AccessTools.Method(typeof(SupportPatches), "ForStructure", (Type[])null, (Type[])null), 2));
		}
	}
}