Decompiled source of BasedDecorPlacement v0.0.1

BasedDecorPlacement.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BasedDecorPlacement.API;
using BasedDecorPlacement.Patches;
using BasedDecorPlacement.PatchesAPI;
using BasedDecorPlacement.Tweaks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BasedDecorPlacement")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1")]
[assembly: AssemblyProduct("BasedDecorPlacement")]
[assembly: AssemblyTitle("BasedDecorPlacement")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BasedDecorPlacement
{
	internal enum RotationSnap
	{
		Zero = 0,
		Five = 5,
		Fifteen = 15,
		Thirty = 30,
		FortyFive = 45
	}
	internal enum RotationControlMode
	{
		Mouse,
		Keys
	}
	internal static class ConfigManager
	{
		internal static ConfigEntry<bool> ReparentItemsToUnlockableSurfaces;

		internal static ConfigEntry<float> ReparentItemsToUnlockableSurfaceOffset;

		internal static ConfigEntry<string> ReparentItemsToUnlockableSurfaceBlacklist;

		internal static ConfigEntry<bool> FixBrokenPrefabs;

		internal static ConfigEntry<bool> BuildModeOverhaul;

		internal static ConfigEntry<RotationControlMode> RotationMode;

		internal static ConfigEntry<RotationSnap> DefaultRotationSnap;

		internal static ConfigEntry<float> SelectionRange;

		internal static ConfigEntry<float> PlacementRange;

		internal static ConfigEntry<bool> ShowCurrentRotation;

		internal static ConfigEntry<string> PlaceableGhostColour;

		internal static ConfigEntry<string> BlockedGhostColour;

		internal static void Bind(ConfigFile config)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			ReparentItemsToUnlockableSurfaces = config.Bind<bool>("Unlockable Item Reparenting", "Reparent Items To Unlockables", true, "If true, reparent items back onto unlockable surfaces after load");
			ReparentItemsToUnlockableSurfaceOffset = config.Bind<float>("Unlockable Item Reparenting", "Unlockable Surface Offset", 0.05f, new ConfigDescription("Max distance allowed when matching an item back to a unlockable surface", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
			ReparentItemsToUnlockableSurfaceBlacklist = config.Bind<string>("Unlockable Item Reparenting", "Unlockable Blacklist", "HouseTeleporter, StockRoom0, BedRoom0, BedRoom1, Basement, House, Poolroom, Garden", "Unlockable names that item reparenting should ignore entirely");
			FixBrokenPrefabs = config.Bind<bool>("Unlockable Item Reparenting", "Fix broken unlockable prefabs", true, "If true, diagnoses issues in unlockable prefabs and tries to repair them. This can resolve items falling through some modded unlockables. Only valid for unlockables that store items");
			BuildModeOverhaul = config.Bind<bool>("Build Mode", "Build mode overhaul", true, "If true, enables build mode overhaul");
			RotationMode = config.Bind<RotationControlMode>("Build Mode", "Rotation mode", RotationControlMode.Mouse, "Mouse = hold left click and move mouse, Keys = Q/E rotate by snap");
			DefaultRotationSnap = config.Bind<RotationSnap>("Build Mode", "Default rotation snap", RotationSnap.Zero, "Default rotation snap");
			SelectionRange = config.Bind<float>("Build Mode", "Selection range", 5f, new ConfigDescription("How far away ship decor can be selected", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 10f), Array.Empty<object>()));
			PlacementRange = config.Bind<float>("Build Mode", "Placement range", 5f, new ConfigDescription("How far away ship decor can be positioned", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 10f), Array.Empty<object>()));
			ShowCurrentRotation = config.Bind<bool>("Build Mode", "Show current rotation", false, "Show the current unlockable rotation in the build mode tooltip");
			PlaceableGhostColour = config.Bind<string>("Build Mode", "Placeable ghost colour", "#00FF00", "Hex colour for the valid placement ghost");
			BlockedGhostColour = config.Bind<string>("Build Mode", "Blocked ghost colour", "#FF0000", "Hex colour for the blocked placement ghost");
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("MrHat.BasedDecorPlacement", "BasedDecorPlacement", "0.0.1")]
	internal class Plugin : BaseUnityPlugin
	{
		internal const string modGUID = "MrHat.BasedDecorPlacement";

		internal const string modName = "BasedDecorPlacement";

		internal const string modVersion = "0.0.1";

		internal static Harmony _harmony;

		internal static ManualLogSource mls;

		internal static Plugin Instance;

		internal static bool hasGeneralImprovements = Chainloader.PluginInfos.ContainsKey("ShaosilGaming.GeneralImprovements");

		internal static bool hasBetterDecorPlacement = Chainloader.PluginInfos.ContainsKey("viviko.BetterDecorPlacement");

		internal static bool hasSnapRotateFurniture = Chainloader.PluginInfos.ContainsKey("SleeplessKyru.SnapRotateFurniture");

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Instance = this;
			mls = Logger.CreateLogSource("MrHat.BasedDecorPlacement");
			_harmony = new Harmony("MrHat.BasedDecorPlacement");
			ConfigManager.Bind(((BaseUnityPlugin)this).Config);
			_harmony.PatchAll(typeof(ShipBuildModeManagerAPIPatches));
			if (ConfigManager.ReparentItemsToUnlockableSurfaces.Value)
			{
				_harmony.PatchAll(typeof(StartOfRoundUnlockableReparentPatches));
			}
			if (ConfigManager.FixBrokenPrefabs.Value)
			{
				_harmony.PatchAll(typeof(GameNetworkManagerPatches));
			}
			if (ConfigManager.BuildModeOverhaul.Value)
			{
				if (hasGeneralImprovements)
				{
					mls.LogDebug((object)"GeneralImprovements detected, unpatching methods for compatibility purposes...");
					_harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ShipBuildModeManager), "Awake", (Type[])null, (Type[])null), (HarmonyPatchType)2, "ShaosilGaming.GeneralImprovements");
					mls.LogDebug((object)"Unpatched GeneralImprovements ShipBuildModeManager.Awake postfix");
					_harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ShipBuildModeManager), "CreateGhostObjectAndHighlight", (Type[])null, (Type[])null), (HarmonyPatchType)2, "ShaosilGaming.GeneralImprovements");
					mls.LogDebug((object)"Unpatched GeneralImprovements ShipBuildModeManager.CreateGhostObjectAndHighlight postfix");
					_harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ShipBuildModeManager), "Update", (Type[])null, (Type[])null), (HarmonyPatchType)2, "ShaosilGaming.GeneralImprovements");
					mls.LogDebug((object)"Unpatched GeneralImprovements ShipBuildModeManager.Update postfix");
					_harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ShipBuildModeManager), "PlaceShipObject", (Type[])null, (Type[])null), (HarmonyPatchType)2, "ShaosilGaming.GeneralImprovements");
					mls.LogDebug((object)"Unpatched GeneralImprovements ShipBuildModeManager.PlaceShipObject postfix");
					_harmony.Unpatch((MethodBase)AccessTools.Method(typeof(AutoParentToShip), "Awake", (Type[])null, (Type[])null), (HarmonyPatchType)1, "ShaosilGaming.GeneralImprovements");
					mls.LogDebug((object)"Unpatched GeneralImprovements AutoParentToShip.Awake prefix");
					mls.LogInfo((object)"GeneralImprovements compatibility patches ran");
				}
				if (hasBetterDecorPlacement)
				{
					mls.LogDebug((object)"BetterDecorPlacement detected, unpatching compatibility conflicts...");
					Harmony.UnpatchID("viviko.BetterDecorPlacement");
					mls.LogInfo((object)"Unpatched BetterDecorPlacement for compatibility purposes");
				}
				if (hasSnapRotateFurniture)
				{
					mls.LogDebug((object)"SnapRotateFurniture detected, unpatching compatibility conflicts...");
					Harmony.UnpatchID("SleeplessKyru.SnapRotateFurniture");
					mls.LogInfo((object)"Unpatched SnapRotateFurniture for compatibility purposes");
				}
				_harmony.PatchAll(typeof(PlayerControllerBPatches));
				_harmony.PatchAll(typeof(ShipBuildModeManagerPatches));
				_harmony.PatchAll(typeof(StartMatchLeverPatches));
				_harmony.PatchAll(typeof(StartOfRoundPatches));
				_harmony.PatchAll(typeof(RoundManagerPatches));
				if (ConfigManager.RotationMode.Value == RotationControlMode.Mouse)
				{
					_harmony.PatchAll(typeof(ShipBuildModeManagerMouseRotationPatches));
				}
				if (ConfigManager.RotationMode.Value == RotationControlMode.Keys)
				{
					_harmony.PatchAll(typeof(ShipBuildModeManagerKeyRotationPatches));
				}
				mls.LogInfo((object)"BasedDecorPlacement loaded!");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "BasedDecorPlacement";

		public const string PLUGIN_NAME = "BasedDecorPlacement";

		public const string PLUGIN_VERSION = "0.0.1";
	}
}
namespace BasedDecorPlacement.Tweaks
{
	internal static class ShipFurnitureSurfaceReparent
	{
		private struct SurfaceInfo
		{
			public UnlockableItem Unlockable;

			public Transform Parent;

			public Collider Bounds;
		}

		private static readonly List<SurfaceInfo> registeredSurfaces = new List<SurfaceInfo>();

		private static readonly List<Collider> ignoredSurfaceBounds = new List<Collider>();

		private static readonly HashSet<string> blacklistedUnlockableNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static void Clear()
		{
			registeredSurfaces.Clear();
			ignoredSurfaceBounds.Clear();
		}

		internal static void Rebuild()
		{
			registeredSurfaces.Clear();
			ignoredSurfaceBounds.Clear();
			RefreshUnlockableBlacklist();
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.unlockablesList == (Object)null)
			{
				return;
			}
			AutoParentToShip[] array = Object.FindObjectsOfType<AutoParentToShip>();
			for (int i = 0; i < array.Length; i++)
			{
				array[i].MoveToOffset();
			}
			Physics.SyncTransforms();
			PlaceableObjectsSurface[] array2 = Object.FindObjectsOfType<PlaceableObjectsSurface>();
			foreach (PlaceableObjectsSurface val in array2)
			{
				PlaceableObjectsSurfaceRegistrationAPI registration;
				bool flag = PlaceableObjectsSurfaceRegistry.TryGet(val, out registration);
				NetworkObject parentTo = val.parentTo;
				Transform val2 = ((parentTo != null) ? ((Component)parentTo).transform : null);
				Collider placeableBounds = val.placeableBounds;
				if (flag && !registration.AllowAutomaticReparent)
				{
					if ((Object)(object)placeableBounds != (Object)null)
					{
						ignoredSurfaceBounds.Add(placeableBounds);
					}
				}
				else
				{
					if ((Object)(object)val2 == (Object)null || (Object)(object)placeableBounds == (Object)null)
					{
						continue;
					}
					NetworkObject parentTo2 = val.parentTo;
					PlaceableShipObject val3 = ((parentTo2 != null) ? ((Component)parentTo2).GetComponentInChildren<PlaceableShipObject>() : null) ?? ((Component)val).GetComponentInParent<PlaceableShipObject>();
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					int unlockableID = val3.unlockableID;
					if (unlockableID < 0 || unlockableID >= instance.unlockablesList.unlockables.Count)
					{
						continue;
					}
					UnlockableItem val4 = instance.unlockablesList.unlockables[unlockableID];
					if (val4 == null || val4.inStorage)
					{
						continue;
					}
					if (blacklistedUnlockableNames.Contains(val4.unlockableName))
					{
						if ((Object)(object)placeableBounds != (Object)null)
						{
							ignoredSurfaceBounds.Add(placeableBounds);
						}
					}
					else
					{
						registeredSurfaces.Add(new SurfaceInfo
						{
							Unlockable = val4,
							Parent = val2,
							Bounds = placeableBounds
						});
					}
				}
			}
		}

		internal static void RelinkAll(bool useGroundedOffset)
		{
			if (registeredSurfaces.Count == 0)
			{
				return;
			}
			GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>();
			foreach (GrabbableObject val in array)
			{
				if (val.isInShipRoom)
				{
					RelinkItem(val, useGroundedOffset);
				}
			}
			Physics.SyncTransforms();
		}

		private static void RelinkItem(GrabbableObject item, bool useGroundedOffset)
		{
			//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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_014a: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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)
			//IL_00ee: 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_00fd: 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)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			if (PlaceableObjectsSurfaceRegistry.IsIgnored(item) || item is ClipboardItem || (item is PhysicsProp && item.itemProperties.itemName == "Sticky note"))
			{
				return;
			}
			float num = ((useGroundedOffset && item.hasHitGround) ? item.itemProperties.verticalOffset : 0f);
			Vector3 val = ((Component)item).transform.position + Vector3.down * num;
			float num2 = ConfigManager.ReparentItemsToUnlockableSurfaceOffset.Value * ConfigManager.ReparentItemsToUnlockableSurfaceOffset.Value;
			Bounds bounds;
			for (int i = 0; i < ignoredSurfaceBounds.Count; i++)
			{
				Collider val2 = ignoredSurfaceBounds[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				bounds = val2.bounds;
				if (!(((Bounds)(ref bounds)).SqrDistance(val) > num2))
				{
					Vector3 val3 = val2.ClosestPoint(val);
					float num3 = Vector3.Dot(val - val3, ((Component)val2).transform.up);
					if (num3 >= -0.001f)
					{
						return;
					}
				}
			}
			float num4 = float.MaxValue;
			int num5 = -1;
			Vector3 val4 = default(Vector3);
			for (int j = 0; j < registeredSurfaces.Count; j++)
			{
				Collider bounds2 = registeredSurfaces[j].Bounds;
				if ((Object)(object)bounds2 == (Object)null)
				{
					continue;
				}
				bounds = bounds2.bounds;
				if (!(((Bounds)(ref bounds)).SqrDistance(val) > num2))
				{
					Vector3 val5 = bounds2.ClosestPoint(val);
					float num6 = Vector3.Dot(val - val5, ((Component)bounds2).transform.up);
					if (!(num6 < -0.001f) && !(num6 >= num4))
					{
						num4 = num6;
						num5 = j;
						val4 = val5;
					}
				}
			}
			if (num5 >= 0)
			{
				SurfaceInfo surfaceInfo = registeredSurfaces[num5];
				Vector3 position = val4 + ((Component)surfaceInfo.Bounds).transform.up * item.itemProperties.verticalOffset;
				((Component)item).transform.SetParent(surfaceInfo.Parent, true);
				((Component)item).transform.position = position;
				item.parentObject = null;
				item.startFallingPosition = (item.targetFloorPosition = ((Component)item).transform.localPosition) + Vector3.up * 0.0001f;
				item.fallTime = 1f;
				item.hasHitGround = true;
				item.reachedFloorTarget = true;
			}
		}

		private static void RefreshUnlockableBlacklist()
		{
			blacklistedUnlockableNames.Clear();
			string value = ConfigManager.ReparentItemsToUnlockableSurfaceBlacklist.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return;
			}
			string[] array = value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (!string.IsNullOrWhiteSpace(text))
				{
					blacklistedUnlockableNames.Add(text);
				}
			}
		}
	}
}
namespace BasedDecorPlacement.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class GameNetworkManagerPatches
	{
		private static bool hasScanned;

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix()
		{
			//IL_052b: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_0561: Unknown result type (might be due to invalid IL or missing references)
			//IL_0575: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Expected O, but got Unknown
			//IL_0606: Unknown result type (might be due to invalid IL or missing references)
			//IL_0615: Unknown result type (might be due to invalid IL or missing references)
			if (hasScanned)
			{
				return;
			}
			hasScanned = true;
			int num = LayerMask.NameToLayer("InteractableObject");
			int num2 = LayerMask.NameToLayer("Triggers");
			int num3 = LayerMask.NameToLayer("PlaceableShipObjects");
			int num4 = LayerMask.NameToLayer("Room");
			int num5 = LayerMask.NameToLayer("Default");
			UnlockablesList[] array = Resources.FindObjectsOfTypeAll<UnlockablesList>();
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = 0;
			int num10 = 0;
			foreach (UnlockablesList val in array)
			{
				if ((Object)(object)val == (Object)null || val.unlockables == null)
				{
					continue;
				}
				for (int j = 0; j < val.unlockables.Count; j++)
				{
					UnlockableItem val2 = val.unlockables[j];
					if (val2 == null || (Object)(object)val2.prefabObject == (Object)null || !hashSet.Add(val2.prefabObject))
					{
						continue;
					}
					num6++;
					PlaceableObjectsSurface[] componentsInChildren = val2.prefabObject.GetComponentsInChildren<PlaceableObjectsSurface>(true);
					if (componentsInChildren == null || componentsInChildren.Length == 0)
					{
						continue;
					}
					HashSet<Collider> hashSet2 = new HashSet<Collider>();
					List<BoxCollider> list = new List<BoxCollider>();
					HashSet<Collider> hashSet3 = new HashSet<Collider>();
					HashSet<Collider> hashSet4 = new HashSet<Collider>();
					List<string> list2 = new List<string>();
					List<string> list3 = new List<string>();
					foreach (PlaceableObjectsSurface val3 in componentsInChildren)
					{
						if ((Object)(object)val3 == (Object)null)
						{
							continue;
						}
						GameObject gameObject = ((Component)val3).gameObject;
						if (gameObject.tag != "InteractTrigger")
						{
							list3.Add("PlaceableObjectsSurface object has wrong tag or has custom properties");
						}
						if (gameObject.layer != num)
						{
							list3.Add("PlaceableObjectsSurface object has wrong layer or has custom properties");
						}
						Collider[] components = gameObject.GetComponents<Collider>();
						foreach (Collider val4 in components)
						{
							if (!((Object)(object)val4 == (Object)null))
							{
								hashSet2.Add(val4);
								hashSet4.Add(val4);
							}
						}
						if ((Object)(object)val3.placeableBounds == (Object)null)
						{
							list3.Add("PlaceableObjectsSurface is missing its PlaceableBounds reference");
							continue;
						}
						hashSet3.Add(val3.placeableBounds);
						GameObject gameObject2 = ((Component)val3.placeableBounds).gameObject;
						if (gameObject2.layer != num2)
						{
							list3.Add("PlaceableBounds object has wrong layer or has custom properties");
						}
						Collider[] components2 = gameObject2.GetComponents<Collider>();
						foreach (Collider val5 in components2)
						{
							if (!((Object)(object)val5 == (Object)null))
							{
								hashSet2.Add(val5);
								hashSet3.Add(val5);
							}
						}
					}
					foreach (Collider item in hashSet2)
					{
						if ((Object)(object)item == (Object)null || ((Component)item).gameObject.layer == num3)
						{
							continue;
						}
						BoxCollider val6 = (BoxCollider)(object)((item is BoxCollider) ? item : null);
						if (val6 != null && !hashSet3.Contains((Collider)(object)val6))
						{
							list.Add(val6);
						}
						if (!item.isTrigger)
						{
							item.isTrigger = true;
							num9++;
							if (hashSet3.Contains(item))
							{
								list2.Add("PlaceableBounds collider was not trigger and was changed");
							}
							else if (hashSet4.Contains(item))
							{
								list2.Add("PlaceableObjectsSurface collider was not trigger and was changed");
							}
							else
							{
								list3.Add("Collider was not trigger and was changed");
							}
						}
					}
					Collider[] componentsInChildren2 = val2.prefabObject.GetComponentsInChildren<Collider>(true);
					bool flag = true;
					bool flag2 = false;
					foreach (Collider val7 in componentsInChildren2)
					{
						if (!((Object)(object)val7 == (Object)null) && ((Component)val7).gameObject.layer != num3)
						{
							if (!val7.isTrigger)
							{
								flag = false;
							}
							int layer = ((Component)val7).gameObject.layer;
							bool flag3 = layer == num4 || layer == num5;
							if (!val7.isTrigger && flag3)
							{
								flag2 = true;
								break;
							}
						}
					}
					if (flag && !flag2 && list.Count > 0)
					{
						PlaceableShipObject componentInChildren = val2.prefabObject.GetComponentInChildren<PlaceableShipObject>(true);
						if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.mainMesh != (Object)null)
						{
							Transform transform = ((Component)componentInChildren.mainMesh).transform;
							Transform val8 = transform.Find("GeneratedRoomBounds");
							if ((Object)(object)val8 == (Object)null)
							{
								GameObject val9 = new GameObject("GeneratedRoomBounds");
								val8 = val9.transform;
								val8.SetParent(transform, false);
							}
							BoxCollider val10 = list[0];
							val8.position = ((Component)val10).transform.position;
							val8.rotation = ((Component)val10).transform.rotation;
							val8.localScale = ((Component)val10).transform.lossyScale;
							Transform obj = val8;
							obj.localPosition += new Vector3(0f, 0f, -0.015f);
							((Component)val8).gameObject.layer = LayerMask.NameToLayer("Room");
							BoxCollider[] components3 = ((Component)val8).GetComponents<BoxCollider>();
							for (int num11 = components3.Length - 1; num11 >= 0; num11--)
							{
								Object.DestroyImmediate((Object)(object)components3[num11]);
							}
							for (int num12 = 0; num12 < list.Count; num12++)
							{
								BoxCollider val11 = list[num12];
								if (!((Object)(object)val11 == (Object)null))
								{
									BoxCollider val12 = ((Component)val8).gameObject.AddComponent<BoxCollider>();
									val12.center = val11.center;
									val12.size = val11.size;
									((Collider)val12).isTrigger = false;
									((Collider)val12).enabled = ((Collider)val11).enabled;
									((Collider)val12).sharedMaterial = ((Collider)val11).sharedMaterial;
									((Collider)val12).contactOffset = ((Collider)val11).contactOffset;
									num10++;
								}
							}
							list2.Add("Box collider components were cloned because no collision was detected");
						}
					}
					if (list3.Count == 0 && list2.Count == 0)
					{
						continue;
					}
					if (list3.Count > 0)
					{
						num8++;
						Plugin.mls.LogInfo((object)(val2.unlockableName + " prefab check"));
						for (int num13 = 0; num13 < list3.Count; num13++)
						{
							Plugin.mls.LogError((object)(" " + list3[num13]));
						}
					}
					if (list2.Count > 0)
					{
						num7++;
						if (list3.Count == 0)
						{
							Plugin.mls.LogInfo((object)(val2.unlockableName + " prefab check"));
						}
						for (int num14 = 0; num14 < list2.Count; num14++)
						{
							Plugin.mls.LogWarning((object)(" " + list2[num14]));
						}
					}
				}
			}
			Plugin.mls.LogInfo((object)"Unlockables prefab scan finished");
			Plugin.mls.LogInfo((object)$"Checked: {num6}");
			if (num7 > 0)
			{
				Plugin.mls.LogWarning((object)$"Warnings: {num7}");
			}
			if (num8 > 0)
			{
				Plugin.mls.LogError((object)$"Errors: {num8}");
			}
			Plugin.mls.LogInfo((object)$"Colliders changed to trigger: {num9}");
			Plugin.mls.LogInfo((object)$"Box colliders added: {num10}");
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatches
	{
		[HarmonyPatch("PlayerLookInput")]
		[HarmonyPrefix]
		private static bool PlayerLookInputPrefix()
		{
			if (!ShipBuildModeManagerPatches.IsRotateHeld())
			{
				return true;
			}
			StartOfRound.Instance.playerLookMagnitudeThisFrame = 0f;
			return false;
		}

		[HarmonyPatch("Interact_performed")]
		[HarmonyPatch("ItemSecondaryUse_performed")]
		[HarmonyPatch("ItemTertiaryUse_performed")]
		[HarmonyPatch("QEItemInteract_performed")]
		[HarmonyPatch("OpenMenu_performed")]
		[HarmonyPrefix]
		private static bool LotsOfButtonsPrefix()
		{
			return (Object)(object)ShipBuildModeManager.Instance == (Object)null || !ShipBuildModeManager.Instance.InBuildMode;
		}
	}
	internal class RoundManagerPatches
	{
		[HarmonyPatch(typeof(RoundManager), "SyncScrapValuesClientRpc")]
		[HarmonyPostfix]
		private static void SyncScrapValuesClientRpcPostfix()
		{
			ShipBuildModeManagerAPIPatches.roundStateBuildBlocked = false;
		}
	}
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	internal class ShipBuildModeManagerKeyRotationPatches
	{
		private static bool qHeld;

		private static bool eHeld;

		private static float qHeldTime;

		private static float eHeldTime;

		private static float qRepeatTime;

		private static float eRepeatTime;

		private static void ResetQ()
		{
			qHeld = false;
			qHeldTime = 0f;
			qRepeatTime = 0f;
		}

		private static void ResetE()
		{
			eHeld = false;
			eHeldTime = 0f;
			eRepeatTime = 0f;
		}

		private static void RotateOnce(int direction)
		{
			ShipBuildModeManagerPatches.currentGhostYaw = ShipBuildModeManagerPatches.NormaliseYaw(ShipBuildModeManagerPatches.currentGhostYaw + (float)(ShipBuildModeManagerPatches.CurrentSnapDegrees * direction));
			ShipBuildModeManagerPatches.rawGhostYawAccumulator = ShipBuildModeManagerPatches.currentGhostYaw;
			ShipBuildModeManagerPatches.UpdateBuildModeTooltip();
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(ShipBuildModeManager __instance)
		{
			if (!__instance.InBuildMode || ConfigManager.RotationMode.Value != RotationControlMode.Keys)
			{
				ResetQ();
				ResetE();
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				ResetQ();
				ResetE();
				return;
			}
			Mouse current2 = Mouse.current;
			if (current2 != null && current2.leftButton.isPressed)
			{
				ResetQ();
				ResetE();
				if (((ButtonControl)current.qKey).wasPressedThisFrame)
				{
					ShipBuildModeManagerPatches.ChangeSnap(-1);
				}
				else if (((ButtonControl)current.eKey).wasPressedThisFrame)
				{
					ShipBuildModeManagerPatches.ChangeSnap(1);
				}
				return;
			}
			if (ShipBuildModeManagerPatches.CurrentSnapDegrees <= 0)
			{
				ResetQ();
				ResetE();
				bool flag = false;
				if (((ButtonControl)current.qKey).isPressed)
				{
					ShipBuildModeManagerPatches.currentGhostYaw = ShipBuildModeManagerPatches.NormaliseYaw(ShipBuildModeManagerPatches.currentGhostYaw - Time.deltaTime * 155f);
					flag = true;
				}
				if (((ButtonControl)current.eKey).isPressed)
				{
					ShipBuildModeManagerPatches.currentGhostYaw = ShipBuildModeManagerPatches.NormaliseYaw(ShipBuildModeManagerPatches.currentGhostYaw + Time.deltaTime * 155f);
					flag = true;
				}
				if (flag)
				{
					ShipBuildModeManagerPatches.rawGhostYawAccumulator = ShipBuildModeManagerPatches.currentGhostYaw;
					ShipBuildModeManagerPatches.UpdateBuildModeTooltip();
				}
				return;
			}
			if (((ButtonControl)current.qKey).wasPressedThisFrame)
			{
				RotateOnce(-1);
				qHeld = true;
				qHeldTime = 0f;
				qRepeatTime = 0f;
			}
			else if (((ButtonControl)current.qKey).isPressed)
			{
				if (!qHeld)
				{
					qHeld = true;
					qHeldTime = 0f;
					qRepeatTime = 0f;
				}
				qHeldTime += Time.deltaTime;
				if (qHeldTime >= 0.4f)
				{
					qRepeatTime += Time.deltaTime;
					while (qRepeatTime >= 0.08f)
					{
						qRepeatTime -= 0.08f;
						RotateOnce(-1);
					}
				}
			}
			else
			{
				ResetQ();
			}
			if (((ButtonControl)current.eKey).wasPressedThisFrame)
			{
				RotateOnce(1);
				eHeld = true;
				eHeldTime = 0f;
				eRepeatTime = 0f;
			}
			else if (((ButtonControl)current.eKey).isPressed)
			{
				if (!eHeld)
				{
					eHeld = true;
					eHeldTime = 0f;
					eRepeatTime = 0f;
				}
				eHeldTime += Time.deltaTime;
				if (eHeldTime >= 0.4f)
				{
					eRepeatTime += Time.deltaTime;
					while (eRepeatTime >= 0.08f)
					{
						eRepeatTime -= 0.08f;
						RotateOnce(1);
					}
				}
			}
			else
			{
				ResetE();
			}
		}
	}
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	internal class ShipBuildModeManagerMouseRotationPatches
	{
		private static float GetRotationMultiplier()
		{
			int currentSnapDegrees = ShipBuildModeManagerPatches.CurrentSnapDegrees;
			if (1 == 0)
			{
			}
			float result = currentSnapDegrees switch
			{
				0 => 0.2f, 
				5 => 0.2f, 
				15 => 0.16f, 
				30 => 0.13f, 
				45 => 0.11f, 
				_ => 0.2f, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(ShipBuildModeManager __instance)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.InBuildMode || ConfigManager.RotationMode.Value != 0)
			{
				return;
			}
			Mouse current = Mouse.current;
			Keyboard current2 = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (current2 != null)
			{
				if (((ButtonControl)current2.qKey).wasPressedThisFrame)
				{
					ShipBuildModeManagerPatches.ChangeSnap(-1);
					return;
				}
				if (((ButtonControl)current2.eKey).wasPressedThisFrame)
				{
					ShipBuildModeManagerPatches.ChangeSnap(1);
					return;
				}
			}
			if (ShipBuildModeManagerPatches.IsRotateHeld())
			{
				float num = ShipBuildModeManagerPatches.CurrentSnapDegrees;
				float currentGhostYaw = ShipBuildModeManagerPatches.currentGhostYaw;
				ShipBuildModeManagerPatches.rawGhostYawAccumulator += ((InputControl<Vector2>)(object)((Pointer)current).delta).ReadValue().x * GetRotationMultiplier();
				ShipBuildModeManagerPatches.currentGhostYaw = ((num <= 0f) ? ShipBuildModeManagerPatches.NormaliseYaw(ShipBuildModeManagerPatches.rawGhostYawAccumulator) : ShipBuildModeManagerPatches.NormaliseYaw(Mathf.Round(ShipBuildModeManagerPatches.rawGhostYawAccumulator / num) * num));
				if (!Mathf.Approximately(currentGhostYaw, ShipBuildModeManagerPatches.currentGhostYaw))
				{
					ShipBuildModeManagerPatches.consumedLeftClickAction = true;
					ShipBuildModeManagerPatches.UpdateBuildModeTooltip();
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	internal class ShipBuildModeManagerPatches
	{
		[CompilerGenerated]
		private sealed class <EnterBuildModeTranspiler>d__26 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private IEnumerator<CodeInstruction> <>s__1;

			private CodeInstruction <instruction>5__2;

			private float <value>5__3;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnterBuildModeTranspiler>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 2u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<instruction>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Expected O, but got Unknown
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>s__1 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Callvirt, (object)configValueGetter);
						<>1__state = 2;
						return true;
					case 2:
						<>1__state = -3;
						break;
					case 3:
						<>1__state = -3;
						<instruction>5__2 = null;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<instruction>5__2 = <>s__1.Current;
						if (<instruction>5__2.opcode == OpCodes.Ldc_R4)
						{
							object operand = <instruction>5__2.operand;
							if (operand is float)
							{
								<value>5__3 = (float)operand;
								if (<value>5__3 == 4f || <value>5__3 == 5f)
								{
									<>2__current = new CodeInstruction(OpCodes.Ldsfld, (object)selectionRangeField);
									<>1__state = 1;
									return true;
								}
							}
						}
						<>2__current = <instruction>5__2;
						<>1__state = 3;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<EnterBuildModeTranspiler>d__26 <EnterBuildModeTranspiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<EnterBuildModeTranspiler>d__ = this;
				}
				else
				{
					<EnterBuildModeTranspiler>d__ = new <EnterBuildModeTranspiler>d__26(0);
				}
				<EnterBuildModeTranspiler>d__.instructions = <>3__instructions;
				return <EnterBuildModeTranspiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <UpdateTranspiler>d__27 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private IEnumerator<CodeInstruction> <>s__1;

			private CodeInstruction <instruction>5__2;

			private float <value>5__3;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <UpdateTranspiler>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 2u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<instruction>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>s__1 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Callvirt, (object)configValueGetter);
						<>1__state = 2;
						return true;
					case 2:
						<>1__state = -3;
						break;
					case 3:
						<>1__state = -3;
						<instruction>5__2 = null;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<instruction>5__2 = <>s__1.Current;
						if (<instruction>5__2.opcode == OpCodes.Ldc_R4)
						{
							object operand = <instruction>5__2.operand;
							if (operand is float)
							{
								<value>5__3 = (float)operand;
								if (<value>5__3 == 4f)
								{
									<>2__current = new CodeInstruction(OpCodes.Ldsfld, (object)placementRangeField);
									<>1__state = 1;
									return true;
								}
							}
						}
						<>2__current = <instruction>5__2;
						<>1__state = 3;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<UpdateTranspiler>d__27 <UpdateTranspiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<UpdateTranspiler>d__ = this;
				}
				else
				{
					<UpdateTranspiler>d__ = new <UpdateTranspiler>d__27(0);
				}
				<UpdateTranspiler>d__.instructions = <>3__instructions;
				return <UpdateTranspiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private static readonly FieldRef<ShipBuildModeManager, bool> canConfirmPosition = AccessTools.FieldRefAccess<ShipBuildModeManager, bool>("CanConfirmPosition");

		private static readonly FieldRef<ShipBuildModeManager, PlaceableShipObject> placingObject = AccessTools.FieldRefAccess<ShipBuildModeManager, PlaceableShipObject>("placingObject");

		private static readonly FieldRef<ShipBuildModeManager, float> timeSincePlacingObject = AccessTools.FieldRefAccess<ShipBuildModeManager, float>("timeSincePlacingObject");

		private static readonly FieldInfo selectionRangeField = AccessTools.Field(typeof(ConfigManager), "SelectionRange");

		private static readonly FieldInfo placementRangeField = AccessTools.Field(typeof(ConfigManager), "PlacementRange");

		private static readonly MethodInfo configValueGetter = AccessTools.PropertyGetter(typeof(ConfigEntry<float>), "Value");

		private static readonly MethodInfo playerMeetsConditionsToBuildMethod = AccessTools.Method(typeof(ShipBuildModeManager), "PlayerMeetsConditionsToBuild", new Type[1] { typeof(bool) }, (Type[])null);

		internal static readonly int[] snapSteps = new int[5] { 0, 5, 15, 30, 45 };

		internal static float currentGhostYaw;

		internal static float rawGhostYawAccumulator;

		internal static float defaultGhostYaw;

		internal static bool wasInBuildMode;

		internal static bool consumedLeftClickAction;

		internal static bool snapInitialised;

		internal static int currentSnapIndex;

		internal const float MouseRotateHoldDelay = 0.04f;

		internal static float mouseLeftHeldTime;

		internal static int CurrentSnapDegrees => snapSteps[currentSnapIndex];

		internal static bool IsRotateHeld()
		{
			return ConfigManager.RotationMode.Value == RotationControlMode.Mouse && (Object)(object)ShipBuildModeManager.Instance != (Object)null && ShipBuildModeManager.Instance.InBuildMode && Mouse.current != null && Mouse.current.leftButton.isPressed && mouseLeftHeldTime >= 0.04f;
		}

		internal static void ChangeSnap(int direction)
		{
			currentSnapIndex = Mathf.Clamp(currentSnapIndex + direction, 0, snapSteps.Length - 1);
			if (CurrentSnapDegrees > 0)
			{
				currentGhostYaw = NormaliseYaw(Mathf.Round(currentGhostYaw / (float)CurrentSnapDegrees) * (float)CurrentSnapDegrees);
			}
			rawGhostYawAccumulator = currentGhostYaw;
			consumedLeftClickAction = true;
			UpdateBuildModeTooltip();
		}

		internal static void UpdateBuildModeTooltip()
		{
			if (!((Object)(object)HUDManager.Instance == (Object)null))
			{
				string text = CurrentSnapDegrees + "°";
				string text2 = NormaliseYaw(currentGhostYaw).ToString("0.#");
				string text3 = ((ConfigManager.RotationMode.Value != 0) ? ("Place [L.Click]     Cancel [Esc]\nRotate Left [Q]     Rotate Right [E]\nDecrease [Hold L.Click + Q]     Snap [" + text + "]     Increase [Hold L.Click + E]") : ("Place [L.Click]     Cancel [Esc]\nRotate [Hold L.Click + Move Mouse]\nDecrease [Q]     Snap [" + text + "]     Increase [E]"));
				if (ConfigManager.ShowCurrentRotation.Value)
				{
					text3 = text3 + "\n[" + text2 + "° / 360°]";
				}
				((TMP_Text)HUDManager.Instance.buildModeControlTip).text = text3;
			}
		}

		internal static float NormaliseYaw(float yaw)
		{
			return Mathf.Repeat(yaw, 360f);
		}

		internal static int GetSnapIndex(int snapDegrees)
		{
			for (int i = 0; i < snapSteps.Length; i++)
			{
				if (snapSteps[i] == snapDegrees)
				{
					return i;
				}
			}
			return 1;
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ShipBuildModeManager __instance, ref int ___placementMask, ref int ___placementMaskAndBlockers)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0049: 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_0052: 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_00c4: 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_00cd: 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_0084: 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)
			Material val = new Material(__instance.ghostObjectGreen);
			Material val2 = new Material(__instance.ghostObjectRed);
			Color val3 = default(Color);
			if (ColorUtility.TryParseHtmlString(ConfigManager.PlaceableGhostColour.Value, ref val3))
			{
				if (val.HasProperty("_BaseColor"))
				{
					Color color = val.GetColor("_BaseColor");
					val3.a = color.a;
					val.SetColor("_BaseColor", val3);
				}
				if (val.HasProperty("_EmissiveColor"))
				{
					val.SetColor("_EmissiveColor", val3);
				}
				__instance.ghostObjectGreen = val;
			}
			Color val4 = default(Color);
			if (ColorUtility.TryParseHtmlString(ConfigManager.BlockedGhostColour.Value, ref val4))
			{
				if (val2.HasProperty("_BaseColor"))
				{
					Color color2 = val2.GetColor("_BaseColor");
					val4.a = color2.a;
					val2.SetColor("_BaseColor", val4);
				}
				if (val2.HasProperty("_EmissiveColor"))
				{
					val2.SetColor("_EmissiveColor", val4);
				}
				__instance.ghostObjectRed = val2;
			}
			if (!snapInitialised)
			{
				currentSnapIndex = GetSnapIndex((int)ConfigManager.DefaultRotationSnap.Value);
				snapInitialised = true;
			}
			___placementMask = LayerMask.GetMask(new string[2] { "Room", "Colliders" });
			___placementMaskAndBlockers = LayerMask.GetMask(Array.Empty<string>());
		}

		[HarmonyPatch("EnterBuildMode")]
		[HarmonyPrefix]
		private static bool EnterBuildModePrefix(ShipBuildModeManager __instance)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null && val.inTerminalMenu)
			{
				return false;
			}
			if (__instance.InBuildMode)
			{
				return false;
			}
			if (BuildModeBoundsRegistry.ShouldBlockNewBuildModeEntry(__instance))
			{
				return false;
			}
			return true;
		}

		[IteratorStateMachine(typeof(<EnterBuildModeTranspiler>d__26))]
		[HarmonyPatch("EnterBuildMode")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> EnterBuildModeTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnterBuildModeTranspiler>d__26(-2)
			{
				<>3__instructions = instructions
			};
		}

		[IteratorStateMachine(typeof(<UpdateTranspiler>d__27))]
		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdateTranspiler>d__27(-2)
			{
				<>3__instructions = instructions
			};
		}

		[HarmonyPatch("CreateGhostObjectAndHighlight")]
		[HarmonyPostfix]
		private static void CreateGhostObjectAndHighlightPostfix(ShipBuildModeManager __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.InBuildMode)
			{
				PlaceableShipObject val = placingObject.Invoke(__instance);
				if ((Object)(object)val != (Object)null)
				{
					val.AllowPlacementOnWalls = true;
					val.AllowPlacementOnCounters = true;
				}
				defaultGhostYaw = NormaliseYaw(__instance.ghostObject.eulerAngles.y);
				currentGhostYaw = defaultGhostYaw;
				rawGhostYawAccumulator = defaultGhostYaw;
				wasInBuildMode = true;
				consumedLeftClickAction = false;
				mouseLeftHeldTime = 0f;
				UpdateBuildModeTooltip();
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(ShipBuildModeManager __instance)
		{
			//IL_0041: 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_0127: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.InBuildMode)
			{
				wasInBuildMode = false;
				consumedLeftClickAction = false;
				mouseLeftHeldTime = 0f;
				return;
			}
			if (!wasInBuildMode)
			{
				defaultGhostYaw = NormaliseYaw(__instance.ghostObject.eulerAngles.y);
				currentGhostYaw = defaultGhostYaw;
				rawGhostYawAccumulator = defaultGhostYaw;
				wasInBuildMode = true;
				consumedLeftClickAction = false;
				mouseLeftHeldTime = 0f;
				UpdateBuildModeTooltip();
			}
			Mouse current = Mouse.current;
			if (current == null || !current.leftButton.isPressed)
			{
				mouseLeftHeldTime = 0f;
			}
			else if (current.leftButton.wasPressedThisFrame)
			{
				consumedLeftClickAction = false;
				mouseLeftHeldTime = 0f;
			}
			else
			{
				mouseLeftHeldTime += Time.deltaTime;
			}
			Keyboard current2 = Keyboard.current;
			if (current2 != null && ((ButtonControl)current2.escapeKey).wasPressedThisFrame)
			{
				__instance.CancelBuildMode(true);
				return;
			}
			Vector3 eulerAngles = __instance.ghostObject.eulerAngles;
			__instance.ghostObject.rotation = Quaternion.Euler(eulerAngles.x, currentGhostYaw, eulerAngles.z);
			bool flag = canConfirmPosition.Invoke(__instance);
			((Renderer)__instance.ghostObjectRenderer).sharedMaterial = (flag ? __instance.ghostObjectGreen : __instance.ghostObjectRed);
			if (current == null || !current.leftButton.wasReleasedThisFrame)
			{
				return;
			}
			if (consumedLeftClickAction)
			{
				consumedLeftClickAction = false;
			}
			else if (!(timeSincePlacingObject.Invoke(__instance) <= 1f) && (bool)playerMeetsConditionsToBuildMethod.Invoke(__instance, new object[1] { false }))
			{
				if (!canConfirmPosition.Invoke(__instance))
				{
					HUDManager.Instance.UIAudio.PlayOneShot(__instance.denyPlacementSFX);
					return;
				}
				PlaceableShipObject val = placingObject.Invoke(__instance);
				timeSincePlacingObject.Invoke(__instance) = 0f;
				__instance.PlaceShipObject(__instance.ghostObject.position, __instance.ghostObject.eulerAngles, val, true);
				__instance.CancelBuildMode(false);
				__instance.PlaceShipObjectServerRpc(__instance.ghostObject.position, __instance.ghostObject.eulerAngles, NetworkObjectReference.op_Implicit(((Component)val.parentObject).GetComponent<NetworkObject>()), (int)GameNetworkManager.Instance.localPlayerController.playerClientId);
				wasInBuildMode = false;
				consumedLeftClickAction = false;
			}
		}
	}
	internal class StartMatchLeverPatches
	{
		[HarmonyPatch(typeof(StartMatchLever), "StartGame")]
		[HarmonyPrefix]
		private static void StartGamePrefix()
		{
			ShipBuildModeManagerAPIPatches.roundStateBuildBlocked = true;
			if ((Object)(object)ShipBuildModeManager.Instance != (Object)null && ShipBuildModeManager.Instance.InBuildMode)
			{
				ShipBuildModeManager.Instance.CancelBuildMode(true);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatches
	{
		[HarmonyPatch("ShipHasLeft")]
		[HarmonyPrefix]
		private static void ShipHasLeftPrefix()
		{
			ShipBuildModeManagerAPIPatches.roundStateBuildBlocked = true;
			if ((Object)(object)ShipBuildModeManager.Instance != (Object)null && ShipBuildModeManager.Instance.InBuildMode)
			{
				ShipBuildModeManager.Instance.CancelBuildMode(true);
			}
		}

		[HarmonyPatch("EndOfGameClientRpc")]
		[HarmonyPostfix]
		private static void EndOfGameClientRpcPostfix()
		{
			ShipBuildModeManagerAPIPatches.roundStateBuildBlocked = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnLocalDisconnect")]
		[HarmonyPatch("OnDestroy")]
		private static void ResetFurnitureCache()
		{
			ShipBuildModeManagerAPIPatches.roundStateBuildBlocked = false;
			ShipFurnitureSurfaceReparent.Clear();
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundUnlockableReparentPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("LoadShipGrabbableItems")]
		private static void AfterLoadShipGrabbableItems(StartOfRound __instance)
		{
			if (ConfigManager.ReparentItemsToUnlockableSurfaces.Value && ((NetworkBehaviour)__instance).IsServer)
			{
				ShipFurnitureSurfaceReparent.Rebuild();
				ShipFurnitureSurfaceReparent.RelinkAll(useGroundedOffset: false);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SyncShipUnlockablesClientRpc")]
		private static void AfterSyncShipUnlockablesClientRpc(StartOfRound __instance)
		{
			if (ConfigManager.ReparentItemsToUnlockableSurfaces.Value && !((NetworkBehaviour)__instance).IsServer)
			{
				NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
				if (!((Object)(object)networkManager == (Object)null) && networkManager.IsListening && (networkManager.IsClient || networkManager.IsHost))
				{
					ShipFurnitureSurfaceReparent.Rebuild();
					ShipFurnitureSurfaceReparent.RelinkAll(useGroundedOffset: true);
				}
			}
		}
	}
}
namespace BasedDecorPlacement.PatchesAPI
{
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	internal class ShipBuildModeManagerAPIPatches
	{
		[CompilerGenerated]
		private sealed class <UpdateTranspiler>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private IEnumerator<CodeInstruction> <>s__1;

			private CodeInstruction <instruction>5__2;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <UpdateTranspiler>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 1u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>s__1 = null;
				<instruction>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>s__1 = instructions.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					case 2:
						<>1__state = -3;
						<instruction>5__2 = null;
						break;
					}
					if (<>s__1.MoveNext())
					{
						<instruction>5__2 = <>s__1.Current;
						if (CodeInstructionExtensions.Calls(<instruction>5__2, boundsContainsMethod))
						{
							<>2__current = new CodeInstruction(OpCodes.Call, (object)buildModeRoomMethod);
							<>1__state = 1;
							return true;
						}
						<>2__current = <instruction>5__2;
						<>1__state = 2;
						return true;
					}
					<>m__Finally1();
					<>s__1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>s__1 != null)
				{
					<>s__1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<UpdateTranspiler>d__4 <UpdateTranspiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<UpdateTranspiler>d__ = this;
				}
				else
				{
					<UpdateTranspiler>d__ = new <UpdateTranspiler>d__4(0);
				}
				<UpdateTranspiler>d__.instructions = <>3__instructions;
				return <UpdateTranspiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		private static readonly MethodInfo boundsContainsMethod = AccessTools.Method(typeof(Bounds), "Contains", new Type[1] { typeof(Vector3) }, (Type[])null);

		private static readonly MethodInfo buildModeRoomMethod = AccessTools.Method(typeof(BuildModeBoundsRegistry), "IsInBuildModeRoom", new Type[2]
		{
			typeof(Bounds).MakeByRefType(),
			typeof(Vector3)
		}, (Type[])null);

		internal static bool roundStateBuildBlocked;

		[HarmonyPatch("PlayerMeetsConditionsToBuild")]
		[HarmonyPrefix]
		private static bool PlayerMeetsConditionsToBuildPrefix(ShipBuildModeManager __instance, ref bool __result, PlaceableShipObject ___placingObject)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: 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)
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (roundStateBuildBlocked)
			{
				__result = false;
				return false;
			}
			if (__instance.InBuildMode && ((Object)(object)___placingObject == (Object)null || ___placingObject.inUse || StartOfRound.Instance.unlockablesList.unlockables[___placingObject.unlockableID].inStorage))
			{
				__result = false;
				return false;
			}
			if (localPlayerController.isTypingChat)
			{
				__result = false;
				return false;
			}
			if (localPlayerController.isPlayerDead || localPlayerController.inSpecialInteractAnimation || localPlayerController.activatingItem)
			{
				__result = false;
				return false;
			}
			if (localPlayerController.disablingJetpackControls || localPlayerController.jetpackControls)
			{
				__result = false;
				return false;
			}
			if (!localPlayerController.isInHangarShipRoom && !BuildModeBoundsRegistry.IsInBuildModeRoom(((Component)localPlayerController).transform.position) && !BuildModeBoundsRegistry.ShouldIgnoreBuildModeRoomCheck(__instance))
			{
				__result = false;
				return false;
			}
			if (StartOfRound.Instance.fearLevel > 0.4f)
			{
				__result = false;
				return false;
			}
			AnimatorStateInfo currentAnimatorStateInfo = StartOfRound.Instance.shipAnimator.GetCurrentAnimatorStateInfo(0);
			if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).tagHash != Animator.StringToHash("ShipIdle"))
			{
				__result = false;
				return false;
			}
			if (!StartOfRound.Instance.inShipPhase && !StartOfRound.Instance.shipHasLanded)
			{
				__result = false;
				return false;
			}
			__result = true;
			return false;
		}

		[IteratorStateMachine(typeof(<UpdateTranspiler>d__4))]
		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdateTranspiler>d__4(-2)
			{
				<>3__instructions = instructions
			};
		}
	}
}
namespace BasedDecorPlacement.API
{
	public static class BuildModeBoundsRegistry
	{
		private const float GraceDuration = 0.35f;

		private static readonly HashSet<Collider> buildModeBounds = new HashSet<Collider>();

		private static float buildModeGraceUntil;

		public static void RegisterBuildModeBounds(Collider collider)
		{
			if (!((Object)(object)collider == (Object)null))
			{
				buildModeBounds.Add(collider);
			}
		}

		public static void UnregisterBuildModeBounds(Collider collider)
		{
			if (!((Object)(object)collider == (Object)null))
			{
				buildModeBounds.Remove(collider);
			}
		}

		public static bool IsInBuildModeRoom(ref Bounds bounds, Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			if (((Bounds)(ref bounds)).Contains(position))
			{
				return true;
			}
			foreach (Collider buildModeBound in buildModeBounds)
			{
				if ((Object)(object)buildModeBound == (Object)null || !buildModeBound.enabled || !((Component)buildModeBound).gameObject.activeInHierarchy || !(buildModeBound.ClosestPoint(position) == position))
				{
					continue;
				}
				return true;
			}
			return false;
		}

		public static bool IsInBuildModeRoom(Vector3 position)
		{
			//IL_002a: 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_0032: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null)
			{
				Bounds bounds = instance.shipInnerRoomBounds.bounds;
				if (((Bounds)(ref bounds)).Contains(position))
				{
					return true;
				}
			}
			foreach (Collider buildModeBound in buildModeBounds)
			{
				if ((Object)(object)buildModeBound == (Object)null || !buildModeBound.enabled || !((Component)buildModeBound).gameObject.activeInHierarchy || !(buildModeBound.ClosestPoint(position) == position))
				{
					continue;
				}
				return true;
			}
			return false;
		}

		public static void BeginTeleportBuildModeGrace(PlayerControllerB player, Vector3 destination)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			ShipBuildModeManager instance = ShipBuildModeManager.Instance;
			if (!((Object)(object)player != (Object)(object)val) && !((Object)(object)instance == (Object)null) && instance.InBuildMode && IsInBuildModeRoom(destination))
			{
				float num = Time.realtimeSinceStartup + 0.35f;
				if (num > buildModeGraceUntil)
				{
					buildModeGraceUntil = num;
				}
			}
		}

		public static bool ShouldIgnoreBuildModeRoomCheck(ShipBuildModeManager buildModeManager)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)buildModeManager == (Object)null || (Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!buildModeManager.InBuildMode)
			{
				return false;
			}
			if (val.isInHangarShipRoom)
			{
				return false;
			}
			return Time.realtimeSinceStartup < buildModeGraceUntil;
		}

		public static bool ShouldBlockNewBuildModeEntry(ShipBuildModeManager buildModeManager)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)buildModeManager == (Object)null || (Object)(object)val == (Object)null)
			{
				return false;
			}
			if (buildModeManager.InBuildMode)
			{
				return false;
			}
			if (val.isInHangarShipRoom)
			{
				return false;
			}
			return Time.realtimeSinceStartup < buildModeGraceUntil;
		}
	}
	public readonly struct PlaceableObjectsSurfaceRegistrationAPI
	{
		public readonly string OwnerGuid;

		public readonly Type SurfaceType;

		public readonly bool AllowAutomaticReparent;

		public PlaceableObjectsSurfaceRegistrationAPI(string ownerGuid, Type surfaceType, bool allowAutomaticReparent)
		{
			OwnerGuid = ownerGuid;
			SurfaceType = surfaceType;
			AllowAutomaticReparent = allowAutomaticReparent;
		}
	}
	public static class PlaceableObjectsSurfaceRegistry
	{
		private static readonly List<PlaceableObjectsSurfaceRegistrationAPI> registrations = new List<PlaceableObjectsSurfaceRegistrationAPI>();

		private static readonly HashSet<GrabbableObject> ignoredItems = new HashSet<GrabbableObject>();

		public static void Register<TSurface>(string ownerGuid, bool allowAutomaticReparent) where TSurface : PlaceableObjectsSurface
		{
			for (int i = 0; i < registrations.Count; i++)
			{
				PlaceableObjectsSurfaceRegistrationAPI placeableObjectsSurfaceRegistrationAPI = registrations[i];
				if (placeableObjectsSurfaceRegistrationAPI.OwnerGuid == ownerGuid && placeableObjectsSurfaceRegistrationAPI.SurfaceType == typeof(TSurface))
				{
					return;
				}
			}
			registrations.Add(new PlaceableObjectsSurfaceRegistrationAPI(ownerGuid, typeof(TSurface), allowAutomaticReparent));
		}

		public static bool TryGet(PlaceableObjectsSurface surface, out PlaceableObjectsSurfaceRegistrationAPI registration)
		{
			for (int i = 0; i < registrations.Count; i++)
			{
				PlaceableObjectsSurfaceRegistrationAPI placeableObjectsSurfaceRegistrationAPI = registrations[i];
				if (placeableObjectsSurfaceRegistrationAPI.SurfaceType.IsInstanceOfType(surface))
				{
					registration = placeableObjectsSurfaceRegistrationAPI;
					return true;
				}
			}
			registration = default(PlaceableObjectsSurfaceRegistrationAPI);
			return false;
		}

		public static void Clear()
		{
			registrations.Clear();
			ignoredItems.Clear();
		}

		public static void Ignore(GrabbableObject item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				ignoredItems.Add(item);
			}
		}

		public static void Allow(GrabbableObject item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				ignoredItems.Remove(item);
			}
		}

		public static bool IsIgnored(GrabbableObject item)
		{
			return (Object)(object)item != (Object)null && ignoredItems.Contains(item);
		}
	}
}