Decompiled source of FurnitureLock v1.4.2

BepInEx/plugins/FurnitureLock.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FurnitureLock.Config;
using FurnitureLock.Dependency;
using FurnitureLock.Patches;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("mattymatty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyInformationalVersion("1.4.2+001c9eeb9d605e2aaea04176b8f7b7fc88f33073")]
[assembly: AssemblyProduct("FurnitureLock")]
[assembly: AssemblyTitle("FurnitureLock - Plugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.2.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 FurnitureLock
{
	[BepInPlugin("mattymatty.FurnitureLock", "FurnitureLock", "1.4.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class FurnitureLock : BaseUnityPlugin
	{
		internal static class PluginConfig
		{
			internal static readonly Dictionary<UnlockableItem, UnlockableConfig> UnlockableConfigs = new Dictionary<UnlockableItem, UnlockableConfig>();

			internal static void Init()
			{
				ConfigFile config = ((BaseUnityPlugin)INSTANCE).Config;
				if (LethalConfigProxy.Enabled)
				{
					LethalConfigProxy.AddButton("Cleanup", "Clear old entries", "remove unused entries in the config file\n(IF RUN FROM MENU WILL DELETE ALL ITEMS!!)", "Clean&Save", CleanAndSave);
					LethalConfigProxy.AddButton("Bulk Actions", "Copy All", "copy position and rotation of all the furniture in the lobby\n(THIS WILL OVERWRITE ALL VALUES!!)", "Copy All", CopyAll);
					LethalConfigProxy.AddButton("Bulk Actions", "Lock All", "mark all the furniture as locked\n(THIS WILL PULL ALL THE FURNITURE OUT OF STORAGE)", "Lock All", LockAll);
					LethalConfigProxy.AddButton("Bulk Actions", "Unlock All", "mark all the furniture as unlocked", "Unlock All", UnlockAll);
				}
			}

			internal static void CleanAndSave()
			{
				ConfigFile config = ((BaseUnityPlugin)INSTANCE).Config;
				PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null);
				dictionary.Clear();
				config.Save();
			}

			internal static void CopyAll()
			{
				ConfigFile config = ((BaseUnityPlugin)INSTANCE).Config;
				foreach (UnlockableConfig value in UnlockableConfigs.Values)
				{
					if (value.IsValid)
					{
						value.CopyValues();
					}
				}
				config.Save();
			}

			internal static void LockAll()
			{
				ConfigFile config = ((BaseUnityPlugin)INSTANCE).Config;
				foreach (UnlockableConfig value in UnlockableConfigs.Values)
				{
					if (value.IsValid)
					{
						value.Locked = true;
						value.LockedConfig.Value = true;
					}
				}
				config.Save();
			}

			internal static void UnlockAll()
			{
				ConfigFile config = ((BaseUnityPlugin)INSTANCE).Config;
				foreach (UnlockableConfig value in UnlockableConfigs.Values)
				{
					if (value.IsValid)
					{
						value.Locked = false;
						value.LockedConfig.Value = false;
					}
				}
				config.Save();
			}
		}

		public const string GUID = "mattymatty.FurnitureLock";

		public const string NAME = "FurnitureLock";

		public const string VERSION = "1.4.2";

		internal static ManualLogSource Log;

		internal static readonly List<Hook> Hooks = new List<Hook>();

		internal static readonly Harmony Harmony = new Harmony("mattymatty.FurnitureLock");

		public static FurnitureLock INSTANCE { get; private set; }

		private void Awake()
		{
			INSTANCE = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (LobbyCompatibilityChecker.Enabled)
				{
					LobbyCompatibilityChecker.Init();
				}
				Log.LogInfo((object)"Initializing Configs");
				PluginConfig.Init();
				Log.LogInfo((object)"Patching Methods");
				ShipBuildModeManagerPatch.Init();
				StartOfRoundPatch.Init();
				Harmony.PatchAll(Assembly.GetExecutingAssembly());
				Log.LogInfo((object)"FurnitureLock v1.4.2 Loaded!");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Exception while initializing: \n" + ex));
			}
		}
	}
	public static class Utils
	{
		private static readonly MethodInfo BeginSendClientRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendClientRpc", (Type[])null, (Type[])null);

		private static readonly MethodInfo BeginSendServerRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendServerRpc", (Type[])null, (Type[])null);

		internal static bool TryGetRpcID(MethodInfo methodInfo, out uint rpcID)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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)
			Collection<Instruction> instructions = PatchManager.GetMethodPatcher((MethodBase)methodInfo).CopyOriginal().Definition.Body.Instructions;
			rpcID = 0u;
			for (int i = 0; i < instructions.Count; i++)
			{
				if (instructions[i].OpCode == OpCodes.Ldc_I4 && instructions[i - 1].OpCode == OpCodes.Ldarg_0)
				{
					rpcID = (uint)(int)instructions[i].Operand;
				}
				if (!(instructions[i].OpCode != OpCodes.Call))
				{
					object operand = instructions[i].Operand;
					MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
					if (val != null && (Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendClientRpc) || Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendServerRpc)))
					{
						FurnitureLock.Log.LogDebug((object)$"Rpc Id found for {methodInfo.Name}: {rpcID}U");
						return true;
					}
				}
			}
			FurnitureLock.Log.LogFatal((object)("Cannot find Rpc ID for " + methodInfo.Name));
			return false;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mattymatty.FurnitureLock";

		public const string PLUGIN_NAME = "FurnitureLock";

		public const string PLUGIN_VERSION = "1.4.2";
	}
}
namespace FurnitureLock.Patches
{
	[HarmonyPatch]
	internal class AutoParentToShipPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(AutoParentToShip), "Awake")]
		private static void AfterAwake(AutoParentToShip __instance)
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: 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_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_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: 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_0205: 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_007f: 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_0091: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00aa: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00d7: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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_011f: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			PlaceableShipObject componentInChildren = ((Component)__instance).GetComponentInChildren<PlaceableShipObject>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				UnlockableItem val = StartOfRound.Instance.unlockablesList.unlockables[componentInChildren.unlockableID];
				if (!FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val, out var value))
				{
					value = new UnlockableConfig(val, componentInChildren.unlockableID);
					FurnitureLock.PluginConfig.UnlockableConfigs.Add(val, value);
				}
				Quaternion val3;
				if (Object.op_Implicit((Object)(object)componentInChildren.parentObjectSecondary))
				{
					Quaternion rotation = ((Component)componentInChildren.parentObjectSecondary).transform.rotation;
					Quaternion rotation2 = ((Component)componentInChildren.parentObjectSecondary).transform.rotation;
					Quaternion rotation3 = ((Component)componentInChildren.mainMesh).transform.rotation;
					Quaternion val2 = rotation * Quaternion.Inverse(rotation2);
					UnlockableConfig unlockableConfig = value;
					val3 = val2 * rotation3;
					unlockableConfig.DefaultRotation = ((Quaternion)(ref val3)).eulerAngles;
					Vector3 position = componentInChildren.parentObjectSecondary.position;
					Vector3 val4 = ((Component)componentInChildren.parentObjectSecondary).transform.position - ((Component)componentInChildren.mainMesh).transform.position;
					Vector3 val5 = ((Component)componentInChildren.mainMesh).transform.position - ((Component)componentInChildren.placeObjectCollider).transform.position;
					value.DefaultPosition = position - val4 - val5;
				}
				else
				{
					Quaternion val6 = Quaternion.Euler(componentInChildren.parentObject.rotationOffset);
					Quaternion rotation4 = ((Component)componentInChildren.parentObject).transform.rotation;
					Quaternion rotation5 = ((Component)componentInChildren.mainMesh).transform.rotation;
					Quaternion val7 = val6 * Quaternion.Inverse(rotation4);
					UnlockableConfig unlockableConfig2 = value;
					val3 = val7 * rotation5;
					unlockableConfig2.DefaultRotation = ((Quaternion)(ref val3)).eulerAngles;
					Vector3 val8 = ((Component)componentInChildren.parentObject).transform.position - ((Component)componentInChildren.mainMesh).transform.position;
					Vector3 val9 = ((Component)componentInChildren.mainMesh).transform.position - ((Component)componentInChildren.placeObjectCollider).transform.position;
					value.DefaultPosition = StartOfRound.Instance.elevatorTransform.TransformPoint(componentInChildren.parentObject.positionOffset) - val8 - val9;
				}
				value.DefaultsInitialized = true;
				FurnitureLock.Log.LogDebug((object)$"{value} defaults are Pos:{value.DefaultPosition} Rot:{value.DefaultRotation}");
			}
		}
	}
	[HarmonyPatch(typeof(ShipBuildModeManager))]
	internal class ShipBuildModeManagerPatch
	{
		private static uint? _returnUnlockableFromStorageClientRpcID;

		internal static void Init()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "ReturnUnlockableFromStorageClientRpc", (Type[])null, (Type[])null);
			if (Utils.TryGetRpcID(methodInfo, out var rpcID))
			{
				_returnUnlockableFromStorageClientRpcID = rpcID;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("StoreObjectLocalClient")]
		[HarmonyPriority(0)]
		private static bool PreventStoreHost(ShipBuildModeManager __instance)
		{
			if (!((NetworkBehaviour)__instance).IsServer)
			{
				return true;
			}
			if ((double)__instance.timeSincePlacingObject <= 0.25 || !__instance.InBuildMode || !Object.op_Implicit((Object)(object)__instance.placingObject) || !StartOfRound.Instance.unlockablesList.unlockables[__instance.placingObject.unlockableID].canBeStored)
			{
				return true;
			}
			PlaceableShipObject placingObject = __instance.placingObject;
			if ((Object)(object)placingObject == (Object)null)
			{
				return true;
			}
			UnlockableItem val = StartOfRound.Instance.unlockablesList.unlockables[placingObject.unlockableID];
			if (!FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val, out var value))
			{
				return true;
			}
			if (!value.Locked)
			{
				return true;
			}
			FurnitureLock.Log.LogDebug((object)("Prevented Store for " + val.unlockableName));
			__instance.CancelBuildMode(false);
			((Component)placingObject).GetComponent<AudioSource>().PlayOneShot(placingObject.placeObjectSFX);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("StoreObjectServerRpc")]
		[HarmonyPriority(0)]
		private static bool PreventStore(ShipBuildModeManager __instance, NetworkObjectReference objectRef, int playerWhoStored)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_00b9: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00f0: 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)
			NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
			if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return true;
			}
			NetworkObject val = default(NetworkObject);
			if (!((NetworkObjectReference)(ref objectRef)).TryGet(ref val, (NetworkManager)null))
			{
				return true;
			}
			PlaceableShipObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<PlaceableShipObject>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return true;
			}
			UnlockableItem val2 = StartOfRound.Instance.unlockablesList.unlockables[componentInChildren.unlockableID];
			if (!FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val2, out var value))
			{
				return true;
			}
			if (!value.Locked)
			{
				return true;
			}
			FurnitureLock.Log.LogDebug((object)("Prevented Store for " + val2.unlockableName));
			if (_returnUnlockableFromStorageClientRpcID.HasValue)
			{
				uint value2 = _returnUnlockableFromStorageClientRpcID.Value;
				StartOfRound instance = StartOfRound.Instance;
				ClientRpcParams val3 = default(ClientRpcParams);
				val3.Send = new ClientRpcSendParams
				{
					TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>((ulong)playerWhoStored)
				};
				ClientRpcParams val4 = val3;
				FastBufferWriter val5 = ((NetworkBehaviour)instance).__beginSendClientRpc(value2, val4, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val5, componentInChildren.unlockableID);
				((NetworkBehaviour)instance).__endSendClientRpc(ref val5, value2, val4, (RpcDelivery)0);
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch("PlaceShipObjectServerRpc")]
		[HarmonyPriority(0)]
		private static void OnMoveFurniture(ShipBuildModeManager __instance, ref Vector3 newPosition, ref Vector3 newRotation, NetworkObjectReference objectRef, ref int playerWhoMoved)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
			NetworkObject val = default(NetworkObject);
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening || (int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost) || !((NetworkObjectReference)(ref objectRef)).TryGet(ref val, (NetworkManager)null))
			{
				return;
			}
			PlaceableShipObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<PlaceableShipObject>();
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				UnlockableItem val2 = StartOfRound.Instance.unlockablesList.unlockables[componentInChildren.unlockableID];
				if (!val2.inStorage && FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val2, out var value) && value.Locked && value.IsValid)
				{
					FurnitureLock.Log.LogDebug((object)$"{val2.unlockableName} forced to pos:{value.Position} rot:{value.Rotation}");
					newPosition = value.Position;
					newRotation = value.Rotation;
					playerWhoMoved = -1;
				}
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		private static bool _isShipResetting;

		internal static void Init()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(StartOfRound), "EndPlayersFiredSequenceClientRpc", (Type[])null, (Type[])null);
			FurnitureLock.Hooks.Add(new Hook((MethodBase)methodInfo, (Delegate)new Action<Action<StartOfRound>, StartOfRound>(OnEjectSequence)));
			MethodInfo methodInfo2 = AccessTools.Method(typeof(StartOfRound), "LoadUnlockables", (Type[])null, (Type[])null);
			FurnitureLock.Hooks.Add(new Hook((MethodBase)methodInfo2, (Delegate)new Action<Action<StartOfRound>, StartOfRound>(OnLoadUnlockables)));
		}

		private static void OnEjectSequence(Action<StartOfRound> original, StartOfRound self)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			_isShipResetting = true;
			try
			{
				original(self);
				if (!((NetworkBehaviour)self).IsServer)
				{
					return;
				}
				NetworkManager networkManager = ((NetworkBehaviour)self).NetworkManager;
				if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening || (int)((NetworkBehaviour)self).__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
				{
					return;
				}
				foreach (UnlockableItem unlockable in self.unlockablesList.unlockables)
				{
					if (FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(unlockable, out var value) && value.AlreadyUnlocked && !unlockable.hasBeenUnlockedByPlayer)
					{
						self.UnlockShipObject(value.UnlockableID);
					}
				}
				ApplyDefaults(self, skipMoved: false, silent: true);
			}
			finally
			{
				_isShipResetting = false;
			}
		}

		private static void OnLoadUnlockables(Action<StartOfRound> original, StartOfRound self)
		{
			_isShipResetting = true;
			try
			{
				bool flag = !ES3.KeyExists("UnlockedShipObjects", GameNetworkManager.Instance.currentSaveFileName);
				original(self);
				for (int i = 0; i < self.unlockablesList.unlockables.Count; i++)
				{
					UnlockableItem val = self.unlockablesList.unlockables[i];
					if (!FurnitureLock.PluginConfig.UnlockableConfigs.ContainsKey(val))
					{
						try
						{
							FurnitureLock.PluginConfig.UnlockableConfigs[val] = new UnlockableConfig(val, i);
						}
						catch (Exception arg)
						{
							FurnitureLock.Log.LogError((object)$"Exception registering {val.unlockableName}: {arg}");
						}
					}
				}
				if (!((NetworkBehaviour)self).IsServer)
				{
					return;
				}
				if (flag)
				{
					foreach (UnlockableItem unlockable in self.unlockablesList.unlockables)
					{
						if (FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(unlockable, out var value) && value.AlreadyUnlocked && !unlockable.hasBeenUnlockedByPlayer)
						{
							self.UnlockShipObject(value.UnlockableID);
							value.ApplyValues(null, placementSound: false, localOnly: true);
						}
					}
				}
				ApplyDefaults(self, skipMoved: true, silent: true, localOnly: true);
			}
			finally
			{
				_isShipResetting = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "SpawnUnlockable")]
		private static void AfterUnlockableSpawn(StartOfRound __instance, int unlockableIndex)
		{
			if (!((NetworkBehaviour)__instance).IsServer || _isShipResetting)
			{
				return;
			}
			UnlockableItem val = __instance.unlockablesList.unlockables[unlockableIndex];
			if (!__instance.SpawnedShipUnlockables.TryGetValue(unlockableIndex, out var value) || !FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val, out var value2))
			{
				return;
			}
			GameNetworkManager instance = GameNetworkManager.Instance;
			if (ES3.KeyExists("ShipUnlockMoved_" + val.unlockableName, instance.currentSaveFileName))
			{
				FurnitureLock.Log.LogDebug((object)$"{val.unlockableName} was moved. locked? {value2.Locked}");
				if (!value2.Locked)
				{
					return;
				}
			}
			value2.ApplyValues(value, placementSound: false, (Object)(object)instance.localPlayerController == (Object)null);
		}

		private static void ApplyDefaults(StartOfRound startOfRound, bool skipMoved, bool silent = false, bool localOnly = false)
		{
			PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>();
			PlaceableShipObject[] array2 = array;
			foreach (PlaceableShipObject val in array2)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				UnlockableItem val2 = startOfRound.unlockablesList.unlockables[val.unlockableID];
				try
				{
					GameObject gameObject = ((Component)val.parentObject).gameObject;
					if (val2.unlockableType != 0 && val2.IsPlaceable && FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(val2, out var value) && (!skipMoved || !val2.hasBeenMoved || value.Locked))
					{
						value.ApplyValues(gameObject, placementSound: false, silent || localOnly);
					}
				}
				catch (Exception arg)
				{
					FurnitureLock.Log.LogError((object)$"Error defaulting {val2.unlockableName}:\n{arg}");
				}
			}
			foreach (UnlockableItem unlockable in startOfRound.unlockablesList.unlockables)
			{
				if (unlockable.unlockableType != 0 && unlockable.IsPlaceable && FurnitureLock.PluginConfig.UnlockableConfigs.TryGetValue(unlockable, out var value2) && value2.Locked && unlockable.inStorage)
				{
					startOfRound.ReturnUnlockableFromStorageServerRpc(value2.UnlockableID);
				}
			}
			if (silent && !localOnly)
			{
				StartOfRound.Instance.SyncShipUnlockablesServerRpc();
			}
		}
	}
}
namespace FurnitureLock.Dependency
{
	public static class LethalConfigProxy
	{
		private static bool? _enabled;

		public static bool Enabled
		{
			get
			{
				bool valueOrDefault = _enabled.GetValueOrDefault();
				if (!_enabled.HasValue)
				{
					valueOrDefault = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");
					_enabled = valueOrDefault;
				}
				return _enabled.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<string> entry, bool requiresRestart = false)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(entry, new TextInputFieldOptions
			{
				RequiresRestart = requiresRestart,
				Name = GetPrettyConfigName<string>(entry)
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<bool> entry, bool requiresRestart = false)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(entry, new BoolCheckBoxOptions
			{
				RequiresRestart = requiresRestart,
				Name = GetPrettyConfigName<bool>(entry)
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<float> entry, bool requiresRestart = false)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(entry, new FloatInputFieldOptions
			{
				RequiresRestart = requiresRestart,
				Name = GetPrettyConfigName<float>(entry)
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<int> entry, bool requiresRestart = false)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(entry, new IntInputFieldOptions
			{
				RequiresRestart = requiresRestart,
				Name = GetPrettyConfigName<int>(entry)
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddButton(string section, string name, string description, string buttonText, Action callback)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem(section, name, description, buttonText, (GenericButtonHandler)delegate
			{
				callback?.Invoke();
			}));
		}

		private static string GetPrettyConfigName<T>(ConfigEntry<T> entry)
		{
			return CultureInfo.InvariantCulture.TextInfo.ToTitleCase(((ConfigEntryBase)entry).Definition.Key.Replace("_", " "));
		}
	}
	public static class LobbyCompatibilityChecker
	{
		private static bool? _enabled;

		public static bool Enabled
		{
			get
			{
				bool valueOrDefault = _enabled.GetValueOrDefault();
				if (!_enabled.HasValue)
				{
					valueOrDefault = Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility");
					_enabled = valueOrDefault;
				}
				return _enabled.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Init()
		{
			PluginHelper.RegisterPlugin("mattymatty.FurnitureLock", Version.Parse("1.4.2"), (CompatibilityLevel)1, (VersionStrictness)2);
		}
	}
}
namespace FurnitureLock.Config
{
	public class UnlockableConfig
	{
		private bool _stored;

		private Vector3? _position;

		private Vector3? _rotation;

		internal readonly ConfigEntry<string> PositionConfig;

		internal readonly ConfigEntry<string> RotationConfig;

		internal readonly ConfigEntry<bool> LockedConfig;

		internal readonly ConfigEntry<bool> AlreadyUnlockedConfig;

		internal readonly ConfigEntry<bool> StoredConfig;

		public bool DefaultsInitialized { get; internal set; }

		public bool IsValid
		{
			get
			{
				if (Unlockable.unlockableType == 0)
				{
					return false;
				}
				if (!Unlockable.IsPlaceable)
				{
					return false;
				}
				if (!_position.HasValue && !DefaultsInitialized)
				{
					return false;
				}
				if (!_rotation.HasValue && !DefaultsInitialized)
				{
					return false;
				}
				return true;
			}
		}

		public UnlockableItem Unlockable { get; }

		public int UnlockableID { get; }

		public bool IsPlaceable { get; }

		public Vector3 Position
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				return (Vector3)(((??)_position) ?? DefaultPosition);
			}
			private set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_position = value;
			}
		}

		public Vector3 Rotation
		{
			get
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				return (Vector3)(((??)_rotation) ?? DefaultRotation);
			}
			private set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_rotation = value;
			}
		}

		public Vector3 DefaultPosition { get; internal set; }

		public Vector3 DefaultRotation { get; internal set; }

		public bool Locked { get; internal set; }

		public bool AlreadyUnlocked { get; internal set; }

		public bool Stored
		{
			get
			{
				if (_stored)
				{
					return !Locked;
				}
				return false;
			}
			private set
			{
				_stored = value;
			}
		}

		public UnlockableConfig(UnlockableItem unlockable, int unlockableID)
		{
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			Unlockable = unlockable;
			UnlockableID = unlockableID;
			IsPlaceable = true;
			FurnitureLock.Log.LogInfo((object)("Registering " + unlockable.unlockableName));
			string unlockableName = unlockable.unlockableName;
			string text = Regex.Replace(unlockableName, "[\\n\\t\\\\\\'\\[\\]]", "").Trim();
			ConfigFile config = ((BaseUnityPlugin)FurnitureLock.INSTANCE).Config;
			if (Unlockable.unlockableType == 0)
			{
				IsPlaceable = false;
			}
			if (!Unlockable.IsPlaceable)
			{
				IsPlaceable = false;
			}
			if (IsPlaceable)
			{
				PositionConfig = config.Bind<string>(text, "position", "default", "default position of the Furniture piece.");
				RotationConfig = config.Bind<string>(text, "rotation", "default", "default rotation of the Furniture piece.");
				LockedConfig = config.Bind<bool>(text, "locked", false, "if true the furniture piece will not be movable");
				if (unlockable.canBeStored)
				{
					StoredConfig = config.Bind<bool>(text, "spawn_stored", false, "if true the furniture piece will be stored immediately upon spawn");
				}
			}
			if (!unlockable.alreadyUnlocked)
			{
				AlreadyUnlockedConfig = config.Bind<bool>(text, "start_unlocked", false, "if true the furniture piece will be unlocked on a new save");
			}
			if (LethalConfigProxy.Enabled)
			{
				if (IsPlaceable)
				{
					LethalConfigProxy.AddConfig(PositionConfig);
					LethalConfigProxy.AddConfig(RotationConfig);
					LethalConfigProxy.AddConfig(LockedConfig);
					if (unlockable.canBeStored)
					{
						LethalConfigProxy.AddConfig(StoredConfig);
					}
				}
				if (!unlockable.alreadyUnlocked)
				{
					LethalConfigProxy.AddConfig(AlreadyUnlockedConfig);
				}
				if (IsPlaceable)
				{
					LethalConfigProxy.AddButton(text, "Set Values", "copy current position and rotation to config", "Copy", CopyValues);
					LethalConfigProxy.AddButton(text, "Apply values", "apply current config values", "Apply", delegate
					{
						ApplyValues();
					});
				}
			}
			if (IsPlaceable)
			{
				OnPositionConfigOnSettingChanged();
				PositionConfig.SettingChanged += delegate
				{
					OnPositionConfigOnSettingChanged();
				};
				OnRotationConfigOnSettingChanged();
				RotationConfig.SettingChanged += delegate
				{
					OnRotationConfigOnSettingChanged();
				};
				Locked = LockedConfig.Value;
				LockedConfig.SettingChanged += delegate
				{
					OnLockedConfigOnSettingChanged();
				};
				if (unlockable.canBeStored)
				{
					OnStoredConfigOnSettingChanged();
					StoredConfig.SettingChanged += delegate
					{
						OnStoredConfigOnSettingChanged();
					};
				}
			}
			if (!unlockable.alreadyUnlocked)
			{
				OnAlreadyUnlockedConfigOnSettingChanged();
				AlreadyUnlockedConfig.SettingChanged += delegate
				{
					OnAlreadyUnlockedConfigOnSettingChanged();
				};
			}
			else
			{
				AlreadyUnlocked = true;
			}
			FurnitureLock.Log.LogDebug((object)$"Placeable \"{unlockable.unlockableName}\" pos: {Position} rot: {Rotation} lock:{Locked} stored:{Stored}");
		}

		internal void CopyValues()
		{
			//IL_007c: 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_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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPlaceable)
			{
				FurnitureLock.Log.LogError((object)(Unlockable.unlockableName + " Cannot copy values from immovable furniture"));
				return;
			}
			if ((!Unlockable.alreadyUnlocked && !Unlockable.hasBeenUnlockedByPlayer) || Unlockable.inStorage)
			{
				FurnitureLock.Log.LogError((object)(Unlockable.unlockableName + " Cannot copy values from furniture that is not spawned"));
				return;
			}
			if (((Vector3)(ref Unlockable.placedPosition)).Equals(default(Vector3)) && ((Vector3)(ref Unlockable.placedRotation)).Equals(default(Vector3)))
			{
				if (!DefaultsInitialized)
				{
					FurnitureLock.Log.LogError((object)(Unlockable.unlockableName + " Cannot copy values from default or missing furniture"));
					return;
				}
				Unlockable.placedPosition = DefaultPosition;
				Unlockable.placedRotation = DefaultRotation;
			}
			Vector3 placedPosition = Unlockable.placedPosition;
			PositionConfig.Value = placedPosition.x.ToString(CultureInfo.InvariantCulture) + ", " + placedPosition.y.ToString(CultureInfo.InvariantCulture) + ", " + placedPosition.z.ToString(CultureInfo.InvariantCulture);
			Vector3 placedRotation = Unlockable.placedRotation;
			RotationConfig.Value = placedRotation.x.ToString(CultureInfo.InvariantCulture) + ", " + placedRotation.y.ToString(CultureInfo.InvariantCulture) + ", " + placedRotation.z.ToString(CultureInfo.InvariantCulture);
		}

		internal void ApplyValues(GameObject gameObject = null, bool placementSound = true, bool localOnly = false)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPlaceable)
			{
				return;
			}
			try
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				if (!((NetworkBehaviour)instance).IsServer)
				{
					FurnitureLock.Log.LogError((object)(Unlockable.unlockableName + " Only the Host can apply values!"));
					return;
				}
				if (!Object.op_Implicit((Object)(object)gameObject) && !StartOfRound.Instance.SpawnedShipUnlockables.TryGetValue(UnlockableID, out gameObject))
				{
					PlaceableShipObject[] array = Object.FindObjectsOfType<PlaceableShipObject>();
					PlaceableShipObject[] array2 = array;
					foreach (PlaceableShipObject val in array2)
					{
						if (val.unlockableID == UnlockableID)
						{
							gameObject = ((Component)val.parentObject).gameObject;
						}
					}
					if ((Object)(object)gameObject == (Object)null)
					{
						return;
					}
				}
				if ((!Stored || Locked) && Unlockable.inStorage)
				{
					instance.ReturnUnlockableFromStorageServerRpc(UnlockableID);
					FurnitureLock.Log.LogDebug((object)(Unlockable.unlockableName + " Forced out of storage"));
				}
				PlaceableShipObject componentInChildren = gameObject.GetComponentInChildren<PlaceableShipObject>();
				if (IsValid)
				{
					ShipBuildModeManager.Instance.PlaceShipObject(Position, Rotation, componentInChildren, placementSound);
					if (!localOnly)
					{
						ShipBuildModeManager.Instance.PlaceShipObjectServerRpc(Position, Rotation, NetworkObjectReference.op_Implicit(gameObject), (int)GameNetworkManager.Instance.localPlayerController.playerClientId);
					}
					FurnitureLock.Log.LogDebug((object)$"{Unlockable.unlockableName} moved to pos:{Position} rot:{Rotation}");
				}
				if (Stored && !Locked && !Unlockable.inStorage)
				{
					ShipBuildModeManager.Instance.StoreObjectServerRpc(NetworkObjectReference.op_Implicit(gameObject), -1);
					FurnitureLock.Log.LogDebug((object)(Unlockable.unlockableName + " Forced in storage"));
				}
			}
			catch (Exception arg)
			{
				FurnitureLock.Log.LogError((object)$"{Unlockable.unlockableName} crashed while moving:\n{arg}");
			}
		}

		private void OnPositionConfigOnSettingChanged()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string[] source = PositionConfig.Value.Split(',');
				float[] array = source.Select((string s) => float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
				Vector3 value = default(Vector3);
				((Vector3)(ref value))..ctor(array[0], array[1], array[2]);
				_position = value;
			}
			catch (Exception)
			{
				_position = null;
			}
		}

		private void OnRotationConfigOnSettingChanged()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string[] source = RotationConfig.Value.Split(',');
				float[] array = source.Select((string s) => float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
				Vector3 value = default(Vector3);
				((Vector3)(ref value))..ctor(array[0], array[1], array[2]);
				_rotation = value;
			}
			catch (Exception)
			{
				_rotation = null;
			}
		}

		private void OnLockedConfigOnSettingChanged()
		{
			Locked = LockedConfig.Value;
			if (Locked)
			{
				ApplyValues();
			}
		}

		private void OnStoredConfigOnSettingChanged()
		{
			Stored = StoredConfig.Value;
		}

		private void OnAlreadyUnlockedConfigOnSettingChanged()
		{
			AlreadyUnlocked = AlreadyUnlockedConfig.Value;
		}

		public override string ToString()
		{
			return $"{Unlockable.unlockableName}({UnlockableID})";
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}