Decompiled source of Homestead v1.2.3

Homestead.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Homestead")]
[assembly: AssemblyDescription("Player-facing construction tools, native blueprints, blueprint trading, build camera controls, placement helpers, and Dvergr circlet QoL for Valheim.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("Homestead")]
[assembly: AssemblyCopyright("Copyright 2026 sighsorry")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.2.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		private readonly string <Name>k__BackingField;

		public string Name => <Name>k__BackingField;

		public ExtensionMarkerAttribute(string name)
		{
			<Name>k__BackingField = name;
		}
	}
}
namespace Homestead
{
	internal static class AzuCraftyBoxesCompat
	{
		private const string PluginGuid = "Azumatt.AzuCraftyBoxes";

		private const string ApiTypeName = "AzuCraftyBoxes.API";

		private const string PluginTypeName = "AzuCraftyBoxes.AzuCraftyBoxesPlugin";

		private const string MiscFunctionsTypeName = "AzuCraftyBoxes.Util.Functions.MiscFunctions";

		private const string BoxesTypeName = "AzuCraftyBoxes.Util.Functions.Boxes";

		private const float FallbackRange = 20f;

		private static readonly HashSet<string> ProtectedContainerPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "piece_chest_wood_blueprint", "piece_chest_barrel_blueprint_store_price", "piece_chest_blueprint_store_purchase", "piece_chest_blackmetal_blueprint_store_payout" };

		private static bool _initialized;

		private static ManualLogSource? _logger;

		private static Type? _apiType;

		private static Type? _pluginType;

		private static Type? _miscFunctionsType;

		private static Type? _boxesType;

		private static Type? _queryFrameType;

		private static MethodInfo? _getNearbyContainersDefinition;

		private static MethodInfo? _canItemBePulled;

		private static MethodInfo? _apiRemoveContainer;

		private static MethodInfo? _boxesRemoveContainer;

		private static MethodInfo? _shouldPrevent;

		private static MethodInfo? _checkAndDecrement;

		private static FieldInfo? _rangeField;

		internal static bool IsLoaded
		{
			get
			{
				EnsureInitialized();
				if (_apiType != null)
				{
					return InvokeStaticBool(_apiType.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public), fallback: true);
				}
				return false;
			}
		}

		internal static void Initialize(ManualLogSource logger, Harmony harmony)
		{
			_logger = logger;
			EnsureInitialized();
			TryPatchPullFilter(harmony);
		}

		internal static int PullMissingMaterials(Component source, IReadOnlyList<ZoneBlueprintRequirement> missingRequirements, Action<ZoneBlueprintRequirement, int> acceptPulledMaterial)
		{
			if ((Object)(object)source == (Object)null || missingRequirements.Count == 0 || acceptPulledMaterial == null)
			{
				return 0;
			}
			EnsureInitialized();
			if (!IsUsable())
			{
				return 0;
			}
			if (InvokeStaticBool(_shouldPrevent, fallback: false))
			{
				return 0;
			}
			IEnumerable nearbyContainers = GetNearbyContainers(source, GetPullRange());
			if (nearbyContainers == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ZoneBlueprintRequirement item in missingRequirements.Where((ZoneBlueprintRequirement requirement) => requirement.Amount > 0))
			{
				int num2 = item.Amount;
				foreach (object item2 in nearbyContainers)
				{
					if (num2 <= 0)
					{
						break;
					}
					string text = InvokeString(item2, "GetPrefabName");
					if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, "piece_chest_wood_blueprint", StringComparison.OrdinalIgnoreCase) && !ZoneBlueprintStoreChestPrefab.IsStorePrefabName(text) && CanItemBePulled(text, item.PrefabName))
					{
						int amount = InvokeInt(item2, "ItemCount", item.ItemName);
						int num3 = Mathf.Max(0, CheckAndDecrement(amount));
						int num4 = Mathf.Min(num2, num3);
						if (num4 > 0)
						{
							InvokeVoid(item2, "RemoveItem", item.ItemName, num4);
							InvokeVoid(item2, "Save");
							acceptPulledMaterial(item, num4);
							num2 -= num4;
							num += num4;
						}
					}
				}
			}
			return num;
		}

		internal static void RemoveContainer(Container? container, string source)
		{
			if (!Object.op_Implicit((Object)(object)container))
			{
				return;
			}
			EnsureInitialized();
			int num = (int)(0u | (InvokeStaticVoid(_apiRemoveContainer, container) ? 1u : 0u) | (InvokeStaticVoid(_boxesRemoveContainer, container) ? 1u : 0u)) | (RemoveContainerFromAzuSets(container) ? 1 : 0);
			InvalidateNearbyContainerCache();
			if (num != 0)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogDebug((object)("Removed Homestead container from AzuCraftyBoxes registry/cache (" + source + "): " + NormalizePrefabName(((Object)container).name ?? "")));
				}
			}
		}

		private static void EnsureInitialized()
		{
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			if (!Chainloader.PluginInfos.TryGetValue("Azumatt.AzuCraftyBoxes", out var value))
			{
				return;
			}
			Assembly assembly = ((object)value.Instance)?.GetType().Assembly;
			if (assembly == null)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogDebug((object)"AzuCraftyBoxes is installed, but its plugin instance is not available.");
				}
				return;
			}
			_apiType = assembly.GetType("AzuCraftyBoxes.API", throwOnError: false);
			_pluginType = assembly.GetType("AzuCraftyBoxes.AzuCraftyBoxesPlugin", throwOnError: false);
			_miscFunctionsType = assembly.GetType("AzuCraftyBoxes.Util.Functions.MiscFunctions", throwOnError: false);
			_boxesType = assembly.GetType("AzuCraftyBoxes.Util.Functions.Boxes", throwOnError: false);
			_queryFrameType = _boxesType?.GetNestedType("QueryFrame", BindingFlags.Public | BindingFlags.NonPublic);
			_getNearbyContainersDefinition = _apiType?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => method.Name == "GetNearbyContainers" && method.IsGenericMethodDefinition);
			_canItemBePulled = _apiType?.GetMethod("CanItemBePulled", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
			{
				typeof(string),
				typeof(string)
			}, null);
			_apiRemoveContainer = _apiType?.GetMethod("RemoveContainer", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Container) }, null);
			_boxesRemoveContainer = _boxesType?.GetMethod("RemoveContainer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Container) }, null);
			_shouldPrevent = _miscFunctionsType?.GetMethod("ShouldPrevent", BindingFlags.Static | BindingFlags.NonPublic);
			_checkAndDecrement = _boxesType?.GetMethod("CheckAndDecrement", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_rangeField = _pluginType?.GetField("mRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private static void TryPatchPullFilter(Harmony harmony)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			EnsureInitialized();
			if (_boxesType == null)
			{
				return;
			}
			MethodInfo methodInfo = _boxesType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo methodInfo2)
			{
				if (methodInfo2.Name != "CanItemBePulled")
				{
					return false;
				}
				ParameterInfo[] parameters = methodInfo2.GetParameters();
				return parameters.Length >= 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string);
			});
			MethodInfo method = typeof(AzuCraftyBoxesCompat).GetMethod("CanItemBePulledPrefix", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo == null || method == null)
			{
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogDebug((object)"AzuCraftyBoxes CanItemBePulled patch target is not available.");
				}
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource? logger2 = _logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)"AzuCraftyBoxes pull filter patched for Homestead blueprint containers.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource? logger3 = _logger;
				if (logger3 != null)
				{
					logger3.LogDebug((object)("Could not patch AzuCraftyBoxes pull filter: " + ex.Message));
				}
			}
		}

		private static bool CanItemBePulledPrefix(string container, ref bool __result)
		{
			if (!IsProtectedContainerPrefab(container))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool IsProtectedContainerPrefab(string? prefabName)
		{
			string text = prefabName ?? "";
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			return ProtectedContainerPrefabs.Contains(NormalizePrefabName(text));
		}

		private static string NormalizePrefabName(string prefabName)
		{
			for (int i = 0; i < prefabName.Length; i++)
			{
				char c = prefabName[i];
				if (c == '(' || c == ' ')
				{
					return prefabName.Substring(0, i);
				}
			}
			return prefabName;
		}

		private static bool InvokeStaticVoid(MethodInfo? method, Container container)
		{
			try
			{
				method?.Invoke(null, new object[1] { container });
				return method != null;
			}
			catch
			{
				return false;
			}
		}

		private static bool RemoveContainerFromAzuSets(Container container)
		{
			return (byte)(0u | (RemoveContainerFromSet("Containers", container) ? 1u : 0u) | (RemoveContainerFromSet("ContainersToAdd", container) ? 1u : 0u) | (RemoveContainerFromSet("ContainersToRemove", container) ? 1u : 0u)) != 0;
		}

		private static bool RemoveContainerFromSet(string fieldName, Container container)
		{
			try
			{
				object obj = _boxesType?.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
				object obj2 = (obj?.GetType().GetMethod("Remove", new Type[1] { typeof(Container) }))?.Invoke(obj, new object[1] { container });
				bool flag = default(bool);
				int num;
				if (obj2 is bool)
				{
					flag = (bool)obj2;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static void InvalidateNearbyContainerCache()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_queryFrameType?.GetField("FrameId", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, -1);
				_queryFrameType?.GetField("Nearby", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, null);
				ClearListField(_boxesType, "_cachedAll");
				ClearListField(_boxesType, "_scratchNearby");
				_boxesType?.GetField("_lastQueryTime", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, float.NegativeInfinity);
				_boxesType?.GetField("_lastQueryRange", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, -1f);
				_boxesType?.GetField("_lastQueryPos", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(null, Vector3.positiveInfinity);
			}
			catch
			{
			}
		}

		private static void ClearListField(Type? type, string fieldName)
		{
			try
			{
				if (type?.GetField(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) is IList list)
				{
					list.Clear();
				}
			}
			catch
			{
			}
		}

		private static bool IsUsable()
		{
			if (_apiType != null && _getNearbyContainersDefinition != null)
			{
				return _canItemBePulled != null;
			}
			return false;
		}

		private static IEnumerable? GetNearbyContainers(Component source, float range)
		{
			try
			{
				return _getNearbyContainersDefinition.MakeGenericMethod(((object)source).GetType()).Invoke(null, new object[2] { source, range }) as IEnumerable;
			}
			catch
			{
				return null;
			}
		}

		private static float GetPullRange()
		{
			try
			{
				object obj = _rangeField?.GetValue(null);
				object obj2 = obj?.GetType().GetProperty("Value")?.GetValue(obj, null);
				if (obj2 != null)
				{
					return Mathf.Max(1f, Convert.ToSingle(obj2, CultureInfo.InvariantCulture));
				}
			}
			catch
			{
			}
			return 20f;
		}

		private static bool CanItemBePulled(string containerPrefab, string itemPrefab)
		{
			try
			{
				object obj = _canItemBePulled?.Invoke(null, new object[2] { containerPrefab, itemPrefab });
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static int CheckAndDecrement(int amount)
		{
			try
			{
				return (_checkAndDecrement?.Invoke(null, new object[1] { amount }) is int num) ? num : amount;
			}
			catch
			{
				return amount;
			}
		}

		private static string InvokeString(object target, string methodName)
		{
			try
			{
				return (target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, Array.Empty<object>()) as string) ?? "";
			}
			catch
			{
				return "";
			}
		}

		private static int InvokeInt(object target, string methodName, params object[] args)
		{
			try
			{
				return (target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, args) is int num) ? num : 0;
			}
			catch
			{
				return 0;
			}
		}

		private static void InvokeVoid(object target, string methodName, params object[] args)
		{
			try
			{
				target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public)?.Invoke(target, args);
			}
			catch
			{
			}
		}

		private static bool InvokeStaticBool(MethodInfo? method, bool fallback)
		{
			try
			{
				return (method?.Invoke(null, Array.Empty<object>()) is bool flag) ? flag : fallback;
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal static class AzuExtendedPlayerInventoryCompat
	{
		private const string PluginGuid = "Azumatt.AzuExtendedPlayerInventory";

		private const string CustomEquipVisualsTypeName = "AzuEPI.Game.PlayerPreview.CustomEquipVisuals";

		private static readonly BindingFlags StaticFieldFlags = BindingFlags.Static | BindingFlags.NonPublic;

		private static readonly BindingFlags InstanceFieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool _initialized;

		private static bool _loaded;

		private static FieldInfo? _statesField;

		public static bool IsLoaded
		{
			get
			{
				EnsureInitialized();
				return _loaded;
			}
		}

		public static bool TryGetCustomEquippedItem(Player player, Func<ItemData?, bool> predicate, out ItemData? item)
		{
			item = null;
			if (!IsLoaded || !Object.op_Implicit((Object)(object)player))
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_equipped && allItem != ((Humanoid)player).m_helmetItem && allItem != ((Humanoid)player).m_chestItem && allItem != ((Humanoid)player).m_legItem && allItem != ((Humanoid)player).m_shoulderItem && allItem != ((Humanoid)player).m_utilityItem && allItem != ((Humanoid)player).m_trinketItem && predicate(allItem))
				{
					item = allItem;
					return true;
				}
			}
			return false;
		}

		public static bool TryGetCustomEquipVisualRoots(VisEquipment visEquipment, ItemData item, List<GameObject> roots)
		{
			roots.Clear();
			if (!IsLoaded || !Object.op_Implicit((Object)(object)visEquipment) || item == null || _statesField == null)
			{
				return false;
			}
			try
			{
				if (!(_statesField.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(visEquipment))
				{
					return false;
				}
				object obj = dictionary[visEquipment];
				if (obj == null)
				{
					return false;
				}
				if (!(obj.GetType().GetField("Equipped", InstanceFieldFlags)?.GetValue(obj) is IDictionary dictionary2))
				{
					return false;
				}
				foreach (DictionaryEntry item2 in dictionary2)
				{
					object value = item2.Value;
					if (value == null)
					{
						continue;
					}
					Type type = value.GetType();
					if (type.GetField("Item", InstanceFieldFlags)?.GetValue(value) != item || !(type.GetField("Instances", InstanceFieldFlags)?.GetValue(value) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item3 in enumerable)
					{
						GameObject val = (GameObject)((item3 is GameObject) ? item3 : null);
						if (val != null && Object.op_Implicit((Object)(object)val))
						{
							roots.Add(val);
						}
					}
				}
			}
			catch
			{
				roots.Clear();
			}
			return roots.Count > 0;
		}

		public static void ResetForWorldSession()
		{
			if (!_loaded)
			{
				_initialized = false;
				_statesField = null;
			}
		}

		private static void EnsureInitialized()
		{
			if (!_initialized)
			{
				_initialized = true;
				if (Chainloader.PluginInfos.TryGetValue("Azumatt.AzuExtendedPlayerInventory", out var value))
				{
					_statesField = ((((object)value.Instance)?.GetType().Assembly)?.GetType("AzuEPI.Game.PlayerPreview.CustomEquipVisuals", throwOnError: false))?.GetField("_states", StaticFieldFlags);
					_loaded = true;
				}
			}
		}
	}
	internal static class BlueprintTerrainContactSampler
	{
		public static List<TerrainWorldContact> CaptureWorldContacts(IEnumerable<TerrainContactSource> sources, float tolerance)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<long, TerrainWorldContact> dictionary = new Dictionary<long, TerrainWorldContact>();
			foreach (TerrainContactSource source in sources)
			{
				if (Object.op_Implicit((Object)(object)source.Prefab) && !((Object)(object)source.Prefab.GetComponent<WearNTear>() == (Object)null) && HomesteadTerrainSupport.TryGetWearNTearBounds(source.Prefab, source.Position, source.Rotation, source.Scale, out var bounds))
				{
					AddLowestBoundsFootprintContacts(bounds, dictionary);
				}
			}
			List<TerrainWorldContact> list = new List<TerrainWorldContact>();
			foreach (TerrainWorldContact item in from contact in dictionary.Values
				orderby contact.WorldZ, contact.WorldX
				select contact)
			{
				if (HomesteadTerrainSupport.TryGetTerrainHeight(item.WorldX, item.WorldZ, out var height) && !(Mathf.Abs(height - item.WorldY) > tolerance))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static List<ZoneBlueprintTerrainContact> ToBlueprintContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable<TerrainWorldContact> contacts)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return (from contact in contacts.Select(delegate(TerrainWorldContact contact)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0008: Unknown result type (might be due to invalid IL or missing references)
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_001d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0024: Unknown result type (might be due to invalid IL or missing references)
					//IL_0035: Unknown result type (might be due to invalid IL or missing references)
					//IL_0046: Unknown result type (might be due to invalid IL or missing references)
					Vector3 val = inverseAnchorRotation * (contact.ToVector3() - anchor);
					return new ZoneBlueprintTerrainContact
					{
						LocalX = Round(val.x),
						LocalY = Round(val.y),
						LocalZ = Round(val.z)
					};
				})
				orderby contact.LocalZ, contact.LocalX
				select contact).ToList();
		}

		private static void AddLowestBoundsFootprintContacts(Bounds bounds, Dictionary<long, TerrainWorldContact> lowestByCell)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			float y = ((Bounds)(ref bounds)).min.y;
			int num = Mathf.FloorToInt(((Bounds)(ref bounds)).min.x);
			int num2 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.x);
			int num3 = Mathf.FloorToInt(((Bounds)(ref bounds)).min.z);
			int num4 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.z);
			for (int i = num; i <= num2; i++)
			{
				for (int j = num3; j <= num4; j++)
				{
					long key = PackCell(i, j);
					TerrainWorldContact value = new TerrainWorldContact(i, j, y);
					if (!lowestByCell.TryGetValue(key, out var value2) || value.WorldY < value2.WorldY)
					{
						lowestByCell[key] = value;
					}
				}
			}
		}

		private static long PackCell(int x, int z)
		{
			return ((long)x << 32) ^ (uint)z;
		}

		private static float Round(float value)
		{
			return Mathf.Round(value * 1000f) / 1000f;
		}
	}
	internal readonly struct TerrainContactSource
	{
		public GameObject Prefab { get; }

		public Vector3 Position { get; }

		public Quaternion Rotation { get; }

		public Vector3 Scale { get; }

		public TerrainContactSource(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Prefab = prefab;
			Position = position;
			Rotation = rotation;
			Scale = scale;
		}
	}
	internal readonly struct TerrainWorldContact
	{
		public float WorldX { get; }

		public float WorldZ { get; }

		public float WorldY { get; }

		public TerrainWorldContact(int cellX, int cellZ, float worldY)
		{
			WorldX = cellX;
			WorldZ = cellZ;
			WorldY = worldY;
		}

		public Vector3 ToVector3()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(WorldX, WorldY, WorldZ);
		}
	}
	internal sealed class HomesteadCommandResult
	{
		public bool Success { get; set; }

		public string Message { get; set; } = "";

		public static HomesteadCommandResult Ok(string message)
		{
			return new HomesteadCommandResult
			{
				Success = true,
				Message = message
			};
		}

		public static HomesteadCommandResult Fail(string message)
		{
			return new HomesteadCommandResult
			{
				Success = false,
				Message = message
			};
		}
	}
	internal static class GeneralConfig
	{
		private static ConfigEntry<HomesteadPlugin.Toggle> _serverConfigLocked;

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			_serverConfigLocked = plugin.config("01 - General", "Lock Configuration", HomesteadPlugin.Toggle.On, new ConfigDescription("If on, the server controls synced settings.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000
				}
			}));
			HomesteadPlugin.ConfigSync.AddLockingConfigEntry<HomesteadPlugin.Toggle>(_serverConfigLocked);
		}
	}
	internal static class AreaRepairConfig
	{
		private static ConfigEntry<float> _baseRadius;

		private static ConfigEntry<float> _comfortRadiusScale;

		public static float BaseRadius => Mathf.Clamp(_baseRadius.Value, 0f, 10f);

		public static float ComfortRadiusScale => Mathf.Clamp(_comfortRadiusScale.Value, 0f, 10f);

		public static bool Enabled
		{
			get
			{
				if (!(BaseRadius > 0f))
				{
					return ComfortRadiusScale > 0f;
				}
				return true;
			}
		}

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			_baseRadius = plugin.config("01 - General", "Area Repair Base Radius", 0f, new ConfigDescription("Base radius in meters for Homestead area repair. This part does not require cozy comfort. Set both area repair radius values to 0 to disable area repair.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 990
				}
			}));
			_comfortRadiusScale = plugin.config("01 - General", "Area Repair Comfort Radius Scale", 4f, new ConfigDescription("Extra area repair radius scale in meters multiplied by the cube root of your current comfort level while you are cozy. Set both area repair radius values to 0 to disable area repair.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 980
				}
			}));
		}
	}
	internal static class ClientConfig
	{
		private static ConfigEntry<float> _statusHudX;

		private static ConfigEntry<float> _statusHudY;

		private static ConfigEntry<int> _statusHudFontSize;

		public static Vector2 StatusHudPosition => new Vector2(Mathf.Clamp(_statusHudX.Value, 0f, 3000f), 0f - Mathf.Clamp(_statusHudY.Value, 0f, 3000f));

		public static int StatusHudFontSize => Mathf.Clamp(_statusHudFontSize.Value, 10, 64);

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			_statusHudX = plugin.config("02 - Client", "Status HUD X Offset", 28f, new ConfigDescription("Client-only X offset in pixels from the top-left corner for the unified status HUD.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>()), synchronizedSetting: false);
			_statusHudY = plugin.config("02 - Client", "Status HUD Y Offset", 116f, new ConfigDescription("Client-only Y offset in pixels from the top-left corner for the unified status HUD.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3000f), Array.Empty<object>()), synchronizedSetting: false);
			_statusHudFontSize = plugin.config("02 - Client", "Status HUD Font Size", 18, new ConfigDescription("Client-only font size for the unified status HUD. HUD width and height are calculated from this value.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 64), Array.Empty<object>()), synchronizedSetting: false);
		}
	}
	internal readonly struct BlueprintNetworkSettings
	{
		public int MaxUploadBytes { get; }

		public int MaxIconBytes { get; }

		public BlueprintNetworkSettings(int maxUploadBytes, int maxIconBytes)
		{
			MaxUploadBytes = maxUploadBytes;
			MaxIconBytes = maxIconBytes;
		}
	}
	internal readonly struct BlueprintStoreSettings
	{
		public int ListingDays { get; }

		public int AutoDelistMaxPurchases { get; }

		public int MaxListingsPerSteamId { get; }

		public BlueprintStoreIdentityMode IdentityMode { get; }

		public BlueprintStoreSettings(int listingDays, int autoDelistMaxPurchases, int maxListingsPerSteamId, BlueprintStoreIdentityMode identityMode)
		{
			ListingDays = listingDays;
			AutoDelistMaxPurchases = autoDelistMaxPurchases;
			MaxListingsPerSteamId = maxListingsPerSteamId;
			IdentityMode = identityMode;
		}
	}
	internal static class BlueprintConfig
	{
		public const int BlueprintChestRows = 40;

		private const int FixedMaxIconKb = 500;

		private const float FixedStorePanelScale = 1.8f;

		private static ConfigEntry<BlueprintTerrainSupportMode> _terrainSupport = null;

		private static ConfigEntry<KeyboardShortcut> _chestConfirmHotkey = null;

		private static ConfigEntry<BlueprintAzuCraftyBoxesPullMode> _azuCraftyBoxesPullMode = null;

		private static ConfigEntry<float> _terrainSupportContactTolerance = null;

		private static ConfigEntry<float> _terrainSupportFeatherWidth = null;

		private static ConfigEntry<int> _maxUploadKb = null;

		private static ConfigEntry<int> _storeListingDays = null;

		private static ConfigEntry<int> _storeAutoDelistMaxPurchases = null;

		private static ConfigEntry<int> _storeMaxListingsPerSteamId = null;

		private static ConfigEntry<BlueprintStoreIdentityMode> _storeIdentityMode = null;

		private static ConfigEntry<int> _chestTimeoutMinutes = null;

		private static ConfigEntry<int> _chestMapIconSize = null;

		private static ConfigEntry<int> _maxActiveChestsPerPlayer = null;

		private static ConfigEntry<float> _storeLargePanelX = null;

		private static ConfigEntry<float> _storeLargePanelY = null;

		private static ConfigEntry<float> _storeFormPanelX = null;

		private static ConfigEntry<float> _storeFormPanelY = null;

		private static ConfigEntry<HomesteadPlugin.Toggle> _storeAnonymousNotifications = null;

		private static ConfigEntry<BlueprintStoreNotificationMode> _storeNotificationMode = null;

		private static ConfigEntry<float> _storeNotificationButtonX = null;

		private static ConfigEntry<float> _storeNotificationButtonY = null;

		private static ConfigEntry<KeyboardShortcut> _storeListModifierKey = null;

		private static ConfigEntry<KeyboardShortcut> _storeBackHotkey = null;

		private static ConfigEntry<float> _areaSaveMaxSide = null;

		private static ConfigEntry<float> _areaSaveDefaultWidth = null;

		private static ConfigEntry<float> _areaSaveDefaultDepth = null;

		private static ConfigEntry<BlueprintAreaSaveCreatorMode> _areaSaveCreatorMode = null;

		private static ConfigEntry<float> _areaDismantleMaxSide = null;

		private static ConfigEntry<float> _areaDismantleDefaultWidth = null;

		private static ConfigEntry<float> _areaDismantleDefaultDepth = null;

		private static ConfigEntry<string> _areaDismantlePrefabBlacklist = null;

		private static ConfigEntry<KeyboardShortcut> _areaToolUniformScaleModifierKey = null;

		private static ConfigEntry<KeyboardShortcut> _areaToolDepthModifierKey = null;

		private static ConfigEntry<KeyboardShortcut> _areaToolWidthModifierKey = null;

		private static ConfigEntry<Color> _previewGhostColor = null;

		private static readonly HashSet<string> BuiltInAreaDismantleProtectedPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "piece_chest_wood_blueprint", "piece_chest_barrel_blueprint_store_price", "piece_chest_blueprint_store_purchase", "piece_chest_blackmetal_blueprint_store_payout" };

		public static KeyboardShortcut ChestConfirmHotkey => _chestConfirmHotkey.Value;

		public static bool AzuCraftyBoxesPullOnConfirm => _azuCraftyBoxesPullMode.Value != BlueprintAzuCraftyBoxesPullMode.Off;

		public static bool AzuCraftyBoxesPullOnOpen => _azuCraftyBoxesPullMode.Value == BlueprintAzuCraftyBoxesPullMode.OpenAndConfirm;

		public static float TerrainSupportContactTolerance => Mathf.Clamp(_terrainSupportContactTolerance.Value, 0.01f, 2f);

		public static float TerrainSupportFeatherWidth => Mathf.Clamp(_terrainSupportFeatherWidth.Value, 0f, 64f);

		public static int MaxUploadKb => Mathf.Clamp(_maxUploadKb.Value, 64, 16384);

		public static int MaxUploadBytes => MaxUploadKb * 1024;

		public static int MaxIconBytes => 512000;

		public static BlueprintNetworkSettings NetworkSettings => new BlueprintNetworkSettings(MaxUploadBytes, MaxIconBytes);

		public static int StoreListingDays => Mathf.Clamp(_storeListingDays.Value, 0, 365);

		public static int StoreAutoDelistMaxPurchases => Mathf.Clamp(_storeAutoDelistMaxPurchases.Value, 0, 100000);

		public static int StoreMaxListingsPerSteamId => Mathf.Clamp(_storeMaxListingsPerSteamId.Value, 1, 200);

		public static BlueprintStoreIdentityMode StoreIdentityMode => _storeIdentityMode.Value;

		public static BlueprintStoreSettings StoreSettings => new BlueprintStoreSettings(StoreListingDays, StoreAutoDelistMaxPurchases, StoreMaxListingsPerSteamId, StoreIdentityMode);

		public static int ChestTimeoutMinutes => Mathf.Clamp(_chestTimeoutMinutes.Value, 0, 60);

		public static int ChestMapIconSize => Mathf.Clamp(_chestMapIconSize.Value, 0, 10);

		public static int MaxActiveChestsPerPlayer => Mathf.Clamp(_maxActiveChestsPerPlayer.Value, 0, 50);

		public static float StoreLargePanelScale => 1.8f;

		public static Vector2 StoreLargePanelOffset => new Vector2(Mathf.Clamp(_storeLargePanelX.Value, -2000f, 2000f), Mathf.Clamp(_storeLargePanelY.Value, -2000f, 2000f));

		public static float StoreFormPanelScale => 1.8f;

		public static Vector2 StoreFormPanelOffset => new Vector2(Mathf.Clamp(_storeFormPanelX.Value, -2000f, 2000f), Mathf.Clamp(_storeFormPanelY.Value, -2000f, 2000f));

		public static int StoreNotificationPollSeconds
		{
			get
			{
				if (!StoreNotificationsEnabled)
				{
					return 0;
				}
				return 900;
			}
		}

		public static BlueprintStoreNotificationMode StoreNotificationMode => _storeNotificationMode.Value;

		public static bool StoreNotificationsEnabled => StoreNotificationMode != BlueprintStoreNotificationMode.Off;

		public static bool StoreNotificationAutoOpen => StoreNotificationMode == BlueprintStoreNotificationMode.AutoOpenPanel;

		public static bool StoreAnonymousNotifications => _storeAnonymousNotifications.Value.IsOn();

		public static bool StoreNotificationButtonEnabled => StoreNotificationsEnabled;

		public static Vector2 StoreNotificationButtonOffset => new Vector2(Mathf.Clamp(_storeNotificationButtonX.Value, -3000f, 3000f), Mathf.Clamp(_storeNotificationButtonY.Value, -3000f, 3000f));

		public static KeyboardShortcut StoreListModifierKey => _storeListModifierKey.Value;

		public static string StoreListModifierLabel => ConfigValueHelpers.FormatShortcut(StoreListModifierKey);

		public static KeyboardShortcut StoreBackHotkey => _storeBackHotkey.Value;

		public static string StoreBackHotkeyLabel => ConfigValueHelpers.FormatShortcut(StoreBackHotkey);

		public static Color StoreListingPreviewColor => PreviewGhostColor;

		public static Color StorePurchasePreviewColor => PreviewGhostColor;

		public static float AreaSaveMaxSide => Mathf.Clamp(_areaSaveMaxSide.Value, 2f, 256f);

		public static float AreaSaveDefaultWidth => Mathf.Clamp(_areaSaveDefaultWidth.Value, 2f, AreaSaveMaxSide);

		public static float AreaSaveDefaultDepth => Mathf.Clamp(_areaSaveDefaultDepth.Value, 2f, AreaSaveMaxSide);

		public static BlueprintAreaSaveCreatorMode AreaSaveCreatorMode => _areaSaveCreatorMode.Value;

		public static string AreaSaveEligibleTargetLabel => AreaSaveCreatorMode switch
		{
			BlueprintAreaSaveCreatorMode.AllCreators => "WearNTear", 
			BlueprintAreaSaveCreatorMode.OwnedAndCreatorless => "owned or creatorless WearNTear", 
			_ => "owned WearNTear", 
		};

		public static Color AreaSaveBoundaryColor => new Color(1f, 0.9f, 0.2f, 0.9f);

		public static float AreaDismantleMaxSide => Mathf.Clamp(_areaDismantleMaxSide.Value, 1f, 128f);

		public static float AreaDismantleDefaultWidth => Mathf.Clamp(_areaDismantleDefaultWidth.Value, 1f, AreaDismantleMaxSide);

		public static float AreaDismantleDefaultDepth => Mathf.Clamp(_areaDismantleDefaultDepth.Value, 1f, AreaDismantleMaxSide);

		public static Color AreaDismantleBoundaryColor => new Color(1f, 0.3f, 0.12f, 0.9f);

		public static HashSet<string> AreaDismantlePrefabBlacklist => ConfigValueHelpers.SplitPrefabList(_areaDismantlePrefabBlacklist.Value);

		public static KeyboardShortcut AreaToolUniformScaleModifierKey => _areaToolUniformScaleModifierKey.Value;

		public static string AreaToolUniformScaleModifierLabel => ConfigValueHelpers.FormatShortcut(AreaToolUniformScaleModifierKey);

		public static string AreaToolUniformScaleInputLabel
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				KeyboardShortcut areaToolUniformScaleModifierKey = AreaToolUniformScaleModifierKey;
				if ((int)((KeyboardShortcut)(ref areaToolUniformScaleModifierKey)).MainKey != 0)
				{
					return AreaToolUniformScaleModifierLabel + "+Wheel";
				}
				return "";
			}
		}

		public static KeyboardShortcut AreaToolDepthModifierKey => _areaToolDepthModifierKey.Value;

		public static string AreaToolDepthModifierLabel => ConfigValueHelpers.FormatShortcut(AreaToolDepthModifierKey);

		public static string AreaToolDepthInputLabel
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				KeyboardShortcut areaToolDepthModifierKey = AreaToolDepthModifierKey;
				if ((int)((KeyboardShortcut)(ref areaToolDepthModifierKey)).MainKey != 0)
				{
					return AreaToolDepthModifierLabel + "+Wheel";
				}
				return "";
			}
		}

		public static KeyboardShortcut AreaToolWidthModifierKey => _areaToolWidthModifierKey.Value;

		public static string AreaToolWidthModifierLabel => ConfigValueHelpers.FormatShortcut(AreaToolWidthModifierKey);

		public static string AreaToolWidthInputLabel
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				KeyboardShortcut areaToolWidthModifierKey = AreaToolWidthModifierKey;
				if ((int)((KeyboardShortcut)(ref areaToolWidthModifierKey)).MainKey != 0)
				{
					return AreaToolWidthModifierLabel + "+Wheel";
				}
				return "";
			}
		}

		public static Color PreviewGhostColor => ClampPreviewColor(_previewGhostColor.Value);

		public static void SetStoreLargePanelOffset(Vector2 offset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			_storeLargePanelX.Value = Mathf.Clamp(offset.x, -2000f, 2000f);
			_storeLargePanelY.Value = Mathf.Clamp(offset.y, -2000f, 2000f);
		}

		public static void SetStoreFormPanelOffset(Vector2 offset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			_storeFormPanelX.Value = Mathf.Clamp(offset.x, -2000f, 2000f);
			_storeFormPanelY.Value = Mathf.Clamp(offset.y, -2000f, 2000f);
		}

		public static void SetStoreNotificationButtonOffset(Vector2 offset)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			_storeNotificationButtonX.Value = Mathf.Clamp(offset.x, -3000f, 3000f);
			_storeNotificationButtonY.Value = Mathf.Clamp(offset.y, -3000f, 3000f);
		}

		public static bool IsStoreListModifierHeld()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ConfigValueHelpers.IsShortcutHeld(StoreListModifierKey, allowUnbound: true);
		}

		public static bool IsStoreBackHotkeyDown()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ConfigValueHelpers.IsShortcutDown(StoreBackHotkey);
		}

		public static bool AreaSaveAllowsCreator(long playerId, long creator)
		{
			if (creator == playerId)
			{
				return true;
			}
			return AreaSaveCreatorMode switch
			{
				BlueprintAreaSaveCreatorMode.AllCreators => true, 
				BlueprintAreaSaveCreatorMode.OwnedAndCreatorless => creator == 0, 
				_ => false, 
			};
		}

		public static bool IsAreaToolUniformScaleModifierHeld()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut areaToolUniformScaleModifierKey = AreaToolUniformScaleModifierKey;
			if ((int)((KeyboardShortcut)(ref areaToolUniformScaleModifierKey)).MainKey != 0)
			{
				return ConfigValueHelpers.IsShortcutHeld(AreaToolUniformScaleModifierKey, allowUnbound: false);
			}
			return false;
		}

		public static bool IsAreaToolDepthModifierHeld()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ConfigValueHelpers.IsShortcutHeld(AreaToolDepthModifierKey, allowUnbound: false);
		}

		public static bool IsAreaToolWidthModifierHeld()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ConfigValueHelpers.IsShortcutHeld(AreaToolWidthModifierKey, allowUnbound: false);
		}

		public static bool ShouldApplyTerrainSupport(Player player)
		{
			return _terrainSupport.Value switch
			{
				BlueprintTerrainSupportMode.On => true, 
				BlueprintTerrainSupportMode.AdminDebug => IsAdminDebugPlayer(player), 
				_ => false, 
			};
		}

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Expected O, but got Unknown
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Expected O, but got Unknown
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Expected O, but got Unknown
			//IL_0433: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Expected O, but got Unknown
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Expected O, but got Unknown
			//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Expected O, but got Unknown
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0528: Expected O, but got Unknown
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Expected O, but got Unknown
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Expected O, but got Unknown
			//IL_05eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Expected O, but got Unknown
			//IL_0639: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Expected O, but got Unknown
			//IL_065e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0687: Unknown result type (might be due to invalid IL or missing references)
			//IL_0692: Expected O, but got Unknown
			//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e0: Expected O, but got Unknown
			//IL_070e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0719: Expected O, but got Unknown
			//IL_0747: Unknown result type (might be due to invalid IL or missing references)
			//IL_0752: Expected O, but got Unknown
			//IL_079c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a7: Expected O, but got Unknown
			//IL_07d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e0: Expected O, but got Unknown
			//IL_080e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0819: Expected O, but got Unknown
			//IL_0858: Unknown result type (might be due to invalid IL or missing references)
			//IL_0882: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0909: Unknown result type (might be due to invalid IL or missing references)
			//IL_0914: Expected O, but got Unknown
			_areaSaveMaxSide = plugin.config("06 - Area Tools", "Area Save Max Side Length", 64f, new ConfigDescription("Server-synced maximum side length in meters for the hammer Area Save blueprint rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 256f), Array.Empty<object>()));
			_terrainSupport = plugin.config("07 - Blueprint", "Terrain Support", BlueprintTerrainSupportMode.Off, new ConfigDescription("Controls native blueprint terrain support. Off only places WearNTear. On restores saved terrain support contacts for everyone. AdminDebug restores terrain support only when the placing player is admin and has debug/no-cost build enabled.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 930
				}
			}));
			_chestConfirmHotkey = plugin.config<KeyboardShortcut>("07 - Blueprint", "Blueprint Chest Confirm Hotkey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Client-only hotkey for confirming a Homestead blueprint chest. The default is Alt+E.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000
				}
			}), synchronizedSetting: false);
			_azuCraftyBoxesPullMode = plugin.config("07 - Blueprint", "AzuCraftyBoxes Pull Mode", BlueprintAzuCraftyBoxesPullMode.ConfirmOnly, new ConfigDescription("If AzuCraftyBoxes is installed, pulls missing blueprint materials from nearby allowed containers. ConfirmOnly pulls when confirming the blueprint. OpenAndConfirm also pulls before opening the blueprint chest.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 940
				}
			}));
			_terrainSupportContactTolerance = plugin.config("07 - Blueprint", "Blueprint Terrain Support Contact Tolerance", 0.5f, new ConfigDescription("How close terrain must be to the lowest WearNTear bottom at a 1m x/z cell to be saved as a blueprint terrain support contact.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 920
				}
			}));
			_terrainSupportFeatherWidth = plugin.config("07 - Blueprint", "Blueprint Terrain Support Feather Width", 6f, new ConfigDescription("Meters around blueprint terrain support contact footprints that blend back to native terrain. Set to 0 to only change exact contact cells.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 64f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 910
				}
			}));
			_maxUploadKb = plugin.config("07 - Blueprint", "Max Blueprint Upload KB", 2048, new ConfigDescription("Server-synced maximum uncompressed blueprint text size for a client blueprint upload. This is checked before blueprint parsing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 16384), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 950
				}
			}));
			_storeListingDays = plugin.config("08 - Blueprint Store", "Blueprint Store Listing Days", 0, new ConfigDescription("How many days a blueprint store listing stays visible from the time it is listed before the server can automatically hide it. Set to 0 to disable automatic delisting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 365), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000
				}
			}));
			_storeAutoDelistMaxPurchases = plugin.config("08 - Blueprint Store", "Blueprint Store Auto Delist Max Purchases", 0, new ConfigDescription("Only listings with this many purchases or fewer are automatically hidden after Blueprint Store Listing Days. Default 0 means only listings with no purchases are auto-delisted.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 990
				}
			}));
			_storeMaxListingsPerSteamId = plugin.config("08 - Blueprint Store", "Blueprint Store Max Listings Per SteamID", 10, new ConfigDescription("Server-synced maximum active blueprint store listings allowed for one SteamID/platform identity.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 980
				}
			}));
			_storeIdentityMode = plugin.config("08 - Blueprint Store", "Blueprint Store Identity Mode", BlueprintStoreIdentityMode.PlayerId, new ConfigDescription("Controls how Blueprint Store ownership and offer buyer permissions are matched. PlayerId treats each Valheim character separately. SteamId treats every character on the same Steam/platform account as the same store identity.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 960
				}
			}));
			_chestTimeoutMinutes = plugin.config("07 - Blueprint", "Blueprint Chest Timeout Minutes", 30, new ConfigDescription("Minutes since last interaction before empty Homestead blueprint/build/store chests are removed. Set to 0 to disable automatic chest cleanup. A chest is kept while it has visible items, absorbed materials, price items, purchase deposits, or payout contents.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 970
				}
			}));
			_chestMapIconSize = plugin.config("07 - Blueprint", "Blueprint Chest Map Icon Size", 1, new ConfigDescription("Client-only icon size for your Homestead blueprint/build/store chests on the large map. Set to 0 to hide these map icons.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 990
				}
			}), synchronizedSetting: false);
			_maxActiveChestsPerPlayer = plugin.config("07 - Blueprint", "Max Active Blueprint Chests Per SteamID", 5, new ConfigDescription("Maximum active Homestead blueprint/build/store chests per Steam/platform identity. Set to 0 to disable this limit. If a platform identity cannot be resolved, Homestead falls back to the Valheim playerID.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 960
				}
			}));
			_storeLargePanelX = plugin.config("08 - Blueprint Store", "Blueprint Store Large Panel X Offset", 0f, new ConfigDescription("Hidden client-only X offset from screen center for the Blueprint Store listing and offers panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2000f, 2000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeLargePanelY = plugin.config("08 - Blueprint Store", "Blueprint Store Large Panel Y Offset", 0f, new ConfigDescription("Hidden client-only Y offset from screen center for the Blueprint Store listing and offers panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2000f, 2000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeFormPanelX = plugin.config("08 - Blueprint Store", "Blueprint Store Form Panel X Offset", 0f, new ConfigDescription("Hidden client-only X offset from screen center for Blueprint Store form panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2000f, 2000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeFormPanelY = plugin.config("08 - Blueprint Store", "Blueprint Store Form Panel Y Offset", 0f, new ConfigDescription("Hidden client-only Y offset from screen center for Blueprint Store form panels. Use the in-game panel drag instead of editing this manually.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2000f, 2000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeNotificationMode = plugin.config("08 - Blueprint Store", "Blueprint Store Notification Mode", BlueprintStoreNotificationMode.BadgeOnly, new ConfigDescription("Client-only display mode for Blueprint Store notifications. Off hides the notification button and disables fallback polling. BadgeOnly keeps the button and unread count visible without opening the panel automatically. AutoOpenPanel opens the notification panel when a new unread notification arrives.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 950
				}
			}), synchronizedSetting: false);
			_storeAnonymousNotifications = plugin.config("08 - Blueprint Store", "Blueprint Store Anonymous Notifications", HomesteadPlugin.Toggle.Off, new ConfigDescription("Server-synced toggle for hiding player names in Blueprint Store notification messages. When on, notifications say Anonymous instead of the buyer, seller, or offer creator name.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 970
				}
			}));
			_storeNotificationButtonX = plugin.config("08 - Blueprint Store", "Blueprint Store Notification Button X Offset", -333f, new ConfigDescription("Hidden client-only default/current X offset for the floating Blueprint Store notification button from the top-right screen anchor. Dragging the in-game button also updates this value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3000f, 3000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeNotificationButtonY = plugin.config("08 - Blueprint Store", "Blueprint Store Notification Button Y Offset", -55f, new ConfigDescription("Hidden client-only default/current Y offset for the floating Blueprint Store notification button from the top-right screen anchor. Dragging the in-game button also updates this value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3000f, 3000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}), synchronizedSetting: false);
			_storeListModifierKey = plugin.config<KeyboardShortcut>("08 - Blueprint Store", "Blueprint Store List Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), new ConfigDescription("Client-only modifier key held while left-clicking a blueprint in the Homestead build tab to place its Blueprint Store price chest. Set to None to use left-click without a modifier.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 940
				}
			}), synchronizedSetting: false);
			_storeBackHotkey = plugin.config<KeyboardShortcut>("08 - Blueprint Store", "Blueprint Store Back Hotkey", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), new ConfigDescription("Client-only hotkey for returning from Blueprint Store sub-panels such as the offers view. Player-facing labels use one-based mouse button names, so Unity Mouse0 is shown as Mouse1.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 930
				}
			}), synchronizedSetting: false);
			_areaSaveDefaultWidth = plugin.config("06 - Area Tools", "Area Save Default Width", 8f, new ConfigDescription("Client-only default Area Save rectangle width. This is clamped by the server max side length.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 256f), Array.Empty<object>()), synchronizedSetting: false);
			_areaSaveDefaultDepth = plugin.config("06 - Area Tools", "Area Save Default Depth", 8f, new ConfigDescription("Client-only default Area Save rectangle depth. Set a different value from width to start as a rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 256f), Array.Empty<object>()), synchronizedSetting: false);
			_areaSaveCreatorMode = plugin.config("06 - Area Tools", "Area Save Creator Mode", BlueprintAreaSaveCreatorMode.OwnedAndCreatorless, "Controls which WearNTear objects the Area Save tool can select. AllCreators saves your own, creator=0, and other creators' WearNTear. OwnedAndCreatorless saves your own plus creator=0 WearNTear. OwnedOnly saves only WearNTear with your playerID.");
			_areaDismantleMaxSide = plugin.config("06 - Area Tools", "Area Dismantle Max Side Length", 8f, new ConfigDescription("Server-synced maximum side length in meters for the hammer Area Dismantle rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 128f), Array.Empty<object>()));
			_areaDismantleDefaultWidth = plugin.config("06 - Area Tools", "Area Dismantle Default Width", 4f, new ConfigDescription("Client-only default Area Dismantle rectangle width. This is clamped by the server max side length.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 128f), Array.Empty<object>()), synchronizedSetting: false);
			_areaDismantleDefaultDepth = plugin.config("06 - Area Tools", "Area Dismantle Default Depth", 4f, new ConfigDescription("Client-only default Area Dismantle rectangle depth. Set a different value from width to start as a rectangle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 128f), Array.Empty<object>()), synchronizedSetting: false);
			_areaDismantlePrefabBlacklist = plugin.config("06 - Area Tools", "Area Dismantle Prefab Blacklist", "piece_stuward", "Comma-separated additional prefab names that Area Dismantle will never dismantle. Homestead blueprint/store chests are always protected internally.");
			PruneBuiltInAreaDismantleBlacklistEntries();
			_areaToolUniformScaleModifierKey = plugin.config<KeyboardShortcut>("06 - Area Tools", "Area Tool Uniform Scale Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), "Client-only modifier key held while using the mouse wheel to resize both the width and depth of Area Save and Area Dismantle rectangles. Set to None to disable uniform wheel resizing.", synchronizedSetting: false);
			_areaToolDepthModifierKey = plugin.config<KeyboardShortcut>("06 - Area Tools", "Area Tool Depth Modifier Key", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), "Client-only modifier key held while using the mouse wheel to resize only the depth of Area Save and Area Dismantle rectangles. Set to None to disable depth-only wheel resizing.", synchronizedSetting: false);
			_areaToolWidthModifierKey = plugin.config<KeyboardShortcut>("06 - Area Tools", "Area Tool Width Modifier Key", new KeyboardShortcut((KeyCode)327, Array.Empty<KeyCode>()), "Client-only modifier key held while using the mouse wheel to resize only the width of Area Save and Area Dismantle rectangles. Set to None to disable width-only wheel resizing.", synchronizedSetting: false);
			_previewGhostColor = plugin.config<Color>("07 - Blueprint", "Preview Ghost Color", new Color(1f, 1f, 1f, 0.25f), new ConfigDescription("Client-only color for unfinished blueprint preview pieces.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 980
				}
			}), synchronizedSetting: false);
		}

		private static bool IsAdminDebugPlayer(Player player)
		{
			if ((Object)(object)player != (Object)null && player.NoCostCheat())
			{
				return IsAdminPlayer(player);
			}
			return false;
		}

		private static bool IsAdminPlayer(Player player)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				return ZNet.instance.LocalPlayerIsAdminOrHost();
			}
			if (ZDOMan.instance == null)
			{
				return false;
			}
			long playerID = player.GetPlayerID();
			if (playerID == 0L)
			{
				return false;
			}
			foreach (ZNetPeer peer in ZNet.instance.m_peers)
			{
				if (peer == null || !peer.IsReady() || ((ZDOID)(ref peer.m_characterID)).IsNone())
				{
					continue;
				}
				ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
				if (zDO != null && zDO.GetLong(ZDOVars.s_playerID, 0L) == playerID)
				{
					ZRpc rpc = peer.m_rpc;
					object obj;
					if (rpc == null)
					{
						obj = null;
					}
					else
					{
						ISocket socket = rpc.m_socket;
						obj = ((socket != null) ? socket.GetHostName() : null);
					}
					if (obj == null)
					{
						obj = "";
					}
					string text = (string)obj;
					return text.Length > 0 && ZNet.instance.IsAdmin(text);
				}
			}
			return false;
		}

		private static void PruneBuiltInAreaDismantleBlacklistEntries()
		{
			List<string> list = (from entry in (_areaDismantlePrefabBlacklist.Value ?? "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select entry.Trim() into entry
				where !string.IsNullOrWhiteSpace(entry)
				select entry).ToList();
			List<string> list2 = list.Where((string entry) => !BuiltInAreaDismantleProtectedPrefabs.Contains(entry)).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
			if (list2.Count != list.Count || !list2.SequenceEqual<string>(list, StringComparer.OrdinalIgnoreCase))
			{
				_areaDismantlePrefabBlacklist.Value = string.Join(",", list2);
			}
		}

		private static Color ClampPreviewColor(Color value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Color val = value;
			val.r = Mathf.Clamp01(val.r);
			val.g = Mathf.Clamp01(val.g);
			val.b = Mathf.Clamp01(val.b);
			val.a = Mathf.Clamp01(val.a);
			return val;
		}
	}
	internal static class BuildCameraConfig
	{
		private static ConfigEntry<HomesteadPlugin.Toggle> _enabled;

		private static ConfigEntry<float> _resourcePickupRange;

		private static ConfigEntry<float> _resourcePickupRangePerComfortLevel;

		private static ConfigEntry<float> _maxPlaceDistance;

		private static ConfigEntry<float> _maxPlaceDistancePerComfortLevel;

		private static ConfigEntry<float> _baseDistanceFromAvatar;

		private static ConfigEntry<float> _distancePerComfortLevel;

		private static ConfigEntry<float> _moveSpeedMultiplier;

		private static ConfigEntry<KeyboardShortcut> _toggleHotkey;

		private static ConfigEntry<KeyboardShortcut> _lookAtLockHotkey;

		private static ConfigEntry<int> _minimumComfortLevel;

		private static ConfigEntry<float> _helmetLightOffsetForward;

		private static ConfigEntry<float> _helmetLightOffsetUp;

		public static bool Enabled => _enabled.Value.IsOn();

		public static float ResourcePickupRange => Mathf.Clamp(_resourcePickupRange.Value, 0f, 100f);

		public static float ResourcePickupRangePerComfortLevel => Mathf.Clamp(_resourcePickupRangePerComfortLevel.Value, 0f, 10f);

		public static float MaxPlaceDistance => Mathf.Clamp(_maxPlaceDistance.Value, 5f, 100f);

		public static float MaxPlaceDistancePerComfortLevel => Mathf.Clamp(_maxPlaceDistancePerComfortLevel.Value, 0f, 10f);

		public static float BaseDistanceFromAvatar => Mathf.Clamp(_baseDistanceFromAvatar.Value, 1f, 500f);

		public static float DistancePerComfortLevel => Mathf.Clamp(_distancePerComfortLevel.Value, 0f, 50f);

		public static float MoveSpeedMultiplier => Mathf.Clamp(_moveSpeedMultiplier.Value, 0.1f, 20f);

		public static KeyboardShortcut ToggleHotkey => _toggleHotkey.Value;

		public static KeyboardShortcut LookAtLockHotkey => _lookAtLockHotkey.Value;

		public static int MinimumComfortLevel => Mathf.Clamp(_minimumComfortLevel.Value, 0, 30);

		public static float HelmetLightOffsetForward => Mathf.Clamp(_helmetLightOffsetForward.Value, -5f, 5f);

		public static float HelmetLightOffsetUp => Mathf.Clamp(_helmetLightOffsetUp.Value, -5f, 5f);

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Expected O, but got Unknown
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Expected O, but got Unknown
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Expected O, but got Unknown
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Expected O, but got Unknown
			_enabled = plugin.config("05 - Build Camera", "Enabled", HomesteadPlugin.Toggle.On, new ConfigDescription("If on, Homestead includes BuildCameraCHE-style free build camera mode. Disable this if the standalone BuildCameraCHE mod is installed.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000
				}
			}));
			_minimumComfortLevel = plugin.config("05 - Build Camera", "Restriction Mode Minimum Comfort Level", 1, new ConfigDescription("Minimum comfort level required to enter and stay in build camera mode. Set to 0 to disable the comfort restriction.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 990
				}
			}));
			_baseDistanceFromAvatar = plugin.config("05 - Build Camera", "Base Camera Distance From Avatar", 32f, new ConfigDescription("Base distance in meters that the build camera can move away from your player avatar before comfort scaling is added.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 500f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 980
				}
			}));
			_distancePerComfortLevel = plugin.config("05 - Build Camera", "Camera Distance Per Comfort Level", 3f, new ConfigDescription("Extra build camera distance in meters added for each current comfort level. Set to 0 to use a fixed camera distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 970
				}
			}));
			_maxPlaceDistance = plugin.config("05 - Build Camera", "Max Place Distance", 5f, new ConfigDescription("Base Player.m_maxPlaceDistance in meters while build camera mode is active. Valheim default is 5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 960
				}
			}));
			_maxPlaceDistancePerComfortLevel = plugin.config("05 - Build Camera", "Max Place Distance Per Comfort Level", 2f, new ConfigDescription("Extra Player.m_maxPlaceDistance in meters added for each current comfort level while build camera mode is active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 950
				}
			}));
			_resourcePickupRange = plugin.config("05 - Build Camera", "Resource Pickup Range", 2f, new ConfigDescription("Base distance in meters from which build camera mode can pick up resources on the ground. Valheim default is 2.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 940
				}
			}));
			_resourcePickupRangePerComfortLevel = plugin.config("05 - Build Camera", "Resource Pickup Range Per Comfort Level", 0.5f, new ConfigDescription("Extra build camera resource pickup range in meters added for each current comfort level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 930
				}
			}));
			_moveSpeedMultiplier = plugin.config("05 - Build Camera", "Camera Move Speed Multiplier", 3f, new ConfigDescription("Multiplies build camera panning speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 920
				}
			}));
			_toggleHotkey = plugin.config<KeyboardShortcut>("05 - Build Camera", "Toggle Build Camera Hotkey", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), new ConfigDescription("Client-only hotkey that toggles build camera mode while a build tool is equipped.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 910
				}
			}), synchronizedSetting: false);
			_lookAtLockHotkey = plugin.config<KeyboardShortcut>("05 - Build Camera", "Look At Lock Hotkey", new KeyboardShortcut((KeyCode)113, Array.Empty<KeyCode>()), new ConfigDescription("Client-only hotkey that toggles build camera look-at lock while build camera mode is active.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 900
				}
			}), synchronizedSetting: false);
			_helmetLightOffsetForward = plugin.config("02 - Client", "Dvergr Circlet Light Forward Offset", 0.65f, new ConfigDescription("Client-only Dvergr circlet light offset along the build camera forward axis.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()), synchronizedSetting: false);
			_helmetLightOffsetUp = plugin.config("02 - Client", "Dvergr Circlet Light Up Offset", -0.08f, new ConfigDescription("Client-only Dvergr circlet light offset along the build camera up axis.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()), synchronizedSetting: false);
		}
	}
	internal static class PlacementControlConfig
	{
		private static ConfigEntry<KeyboardShortcut> _gridSnapToggleHotkey;

		private static ConfigEntry<float> _gridSnapSize;

		private static ConfigEntry<HomesteadPlugin.Toggle> _placementAdjustEnabled;

		private static ConfigEntry<float> _placementAdjustHeightStep;

		private static ConfigEntry<float> _placementAdjustHorizontalStep;

		private static ConfigEntry<float> _placementRotationStep;

		private static ConfigEntry<float> _placementXAxisRotation;

		private static ConfigEntry<float> _placementZAxisRotation;

		public static KeyboardShortcut GridSnapToggleHotkey => _gridSnapToggleHotkey.Value;

		public static float GridSnapSize => Mathf.Round(Mathf.Clamp(_gridSnapSize.Value, 0.05f, 1f) * 20f) / 20f;

		public static bool PlacementAdjustEnabled => _placementAdjustEnabled.Value.IsOn();

		public static float HeightStep => Mathf.Clamp(_placementAdjustHeightStep.Value, 0.01f, 10f);

		public static float HorizontalStep => Mathf.Clamp(_placementAdjustHorizontalStep.Value, 0.01f, 10f);

		public static float RotationStep => RoundHalfDegree(Mathf.Clamp(_placementRotationStep.Value, 0.5f, 90f));

		public static float XAxisRotation => RoundHalfDegree(Mathf.Clamp(_placementXAxisRotation.Value, -180f, 180f));

		public static float ZAxisRotation => RoundHalfDegree(Mathf.Clamp(_placementZAxisRotation.Value, -180f, 180f));

		public static bool HasPlacementAxisRotation
		{
			get
			{
				if (!(Mathf.Abs(XAxisRotation) > 0.001f))
				{
					return Mathf.Abs(ZAxisRotation) > 0.001f;
				}
				return true;
			}
		}

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			_gridSnapToggleHotkey = plugin.config<KeyboardShortcut>("04 - Placement Controls", "Grid Snap Toggle Hotkey", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "Client-only hotkey that toggles grid snapping on or off while placing build pieces. The default is G.", synchronizedSetting: false);
			_gridSnapSize = plugin.config("04 - Placement Controls", "Grid Size", 0.5f, new ConfigDescription("Client-only grid spacing in meters. Values are clamped and rounded to 0.05m steps between 0.05 and 1.0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()), synchronizedSetting: false);
			_placementAdjustEnabled = plugin.config("04 - Placement Controls", "Position Adjust", HomesteadPlugin.Toggle.On, "If on, hammer pieces, Homestead blueprints, and area tools can be nudged directly with PgUp/PgDn and arrow keys without a modifier key.", synchronizedSetting: false);
			_placementAdjustHeightStep = plugin.config("04 - Placement Controls", "Position Height Step", 0.5f, new ConfigDescription("Client-only vertical offset step in meters for PgUp/PgDn while adjusting placement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>()), synchronizedSetting: false);
			_placementAdjustHorizontalStep = plugin.config("04 - Placement Controls", "Position Horizontal Step", 0.5f, new ConfigDescription("Client-only horizontal offset step in meters for arrow keys while adjusting placement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>()), synchronizedSetting: false);
			_placementRotationStep = plugin.config("04 - Placement Controls", "Rotation Step", 22.5f, new ConfigDescription("Client-only rotation step in degrees shared by Area Save, Area Dismantle, blueprint yaw rotation, and ordinary hammer placement. While ComfyGizmo is loaded, ordinary hammer placement and its random rotation correction are left to ComfyGizmo; area and blueprint rotation remain unchanged. Values are rounded to 0.5 degree steps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 90f), Array.Empty<object>()), synchronizedSetting: false);
			_placementXAxisRotation = plugin.config("04 - Placement Controls", "X Axis Rotation", 0f, new ConfigDescription("Client-only default X-axis rotation in degrees applied to ordinary hammer build piece previews and final placement. Ignored while ComfyGizmo is loaded. Terrain tools and Homestead area tools are ignored. Values are rounded to 0.5 degree steps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()), synchronizedSetting: false);
			_placementZAxisRotation = plugin.config("04 - Placement Controls", "Z Axis Rotation", 0f, new ConfigDescription("Client-only default Z-axis rotation in degrees applied to ordinary hammer build piece previews and final placement. Ignored while ComfyGizmo is loaded. Terrain tools and Homestead area tools are ignored. Values are rounded to 0.5 degree steps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()), synchronizedSetting: false);
		}

		private static float RoundHalfDegree(float value)
		{
			return Mathf.Round(value * 2f) / 2f;
		}
	}
	internal static class DvergrCircletConfig
	{
		public const float MaxDurability = 100f;

		public const float PerItemMinMultiplier = 1f;

		private static ConfigEntry<HomesteadPlugin.Toggle> _extensionEnabled;

		private static ConfigEntry<float> _fuelMinutes;

		private static ConfigEntry<string> _repairStation;

		private static ConfigEntry<float> _perItemMaxIntensityMultiplier;

		private static ConfigEntry<float> _perItemMaxRangeMultiplier;

		private static ConfigEntry<float> _perItemAdjustmentStep;

		private static ConfigEntry<KeyboardShortcut> _toggleLightHotkey;

		private static ConfigEntry<KeyboardShortcut> _adjustmentModifierKey;

		public static bool ExtensionEnabled => _extensionEnabled.Value.IsOn();

		public static float FuelSeconds => Mathf.Max(1f, _fuelMinutes.Value) * 60f;

		public static string RepairStation
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(_repairStation.Value))
				{
					return _repairStation.Value.Trim();
				}
				return "forge";
			}
		}

		public static float PerItemMaxIntensityMultiplier => Mathf.Max(1f, Mathf.Clamp(_perItemMaxIntensityMultiplier.Value, 1f, 3f));

		public static float PerItemMaxRangeMultiplier => Mathf.Max(1f, Mathf.Clamp(_perItemMaxRangeMultiplier.Value, 1f, 3f));

		public static float PerItemAdjustmentStep => Mathf.Clamp(_perItemAdjustmentStep.Value, 0.05f, 1f);

		public static KeyboardShortcut ToggleLightHotkey => _toggleLightHotkey.Value;

		public static KeyboardShortcut AdjustmentModifierKey => _adjustmentModifierKey.Value;

		public static string AdjustmentModifierLabel => ConfigValueHelpers.FormatShortcut(AdjustmentModifierKey);

		public static void Bind(HomesteadPlugin plugin)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			_extensionEnabled = plugin.config("03 - Dvergr Circlet", "Enabled", HomesteadPlugin.Toggle.On, new ConfigDescription("If on, Homestead gives the Dvergr circlet per-item configurable light range, light intensity, durability drain while lit, and custom repair station support. If Circlet Extended is installed, Homestead leaves circlet handling to that mod.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000
				}
			}));
			_repairStation = plugin.config("03 - Dvergr Circlet", "Repair Station", "forge", new ConfigDescription("Crafting station required to repair the Dvergr circlet. Use the prefab name like forge, workbench, blackforge, or the localized station token like $piece_forge.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 990
				}
			}));
			_fuelMinutes = plugin.config("03 - Dvergr Circlet", "Base Fuel Minutes", 60f, new ConfigDescription("How many minutes a full Dvergr circlet lasts at 1.0 light intensity and 1.0 light range. Higher intensity and range drain proportionally faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 980
				}
			}));
			_perItemMaxIntensityMultiplier = plugin.config("03 - Dvergr Circlet", "Maximum Intensity Multiplier", 2f, new ConfigDescription("Highest brightness multiplier a player can set on an individual Dvergr circlet with hotkeys.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 970
				}
			}));
			_perItemMaxRangeMultiplier = plugin.config("03 - Dvergr Circlet", "Maximum Range Multiplier", 2f, new ConfigDescription("Highest range multiplier a player can set on an individual Dvergr circlet with hotkeys.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 960
				}
			}));
			_perItemAdjustmentStep = plugin.config("03 - Dvergr Circlet", "Adjustment Step", 0.25f, new ConfigDescription("Client-only brightness/range multiplier step used by Dvergr circlet hotkeys. 0.25 means 25% per key press.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 950
				}
			}), synchronizedSetting: false);
			_adjustmentModifierKey = plugin.config<KeyboardShortcut>("03 - Dvergr Circlet", "Adjustment Modifier Key", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), new ConfigDescription("Client-only modifier held while using fixed arrow keys to adjust the equipped Dvergr circlet. Up/Down changes brightness, Right/Left changes range. Set to None to use arrow keys without a modifier.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 940
				}
			}), synchronizedSetting: false);
			_toggleLightHotkey = plugin.config<KeyboardShortcut>("03 - Dvergr Circlet", "Toggle Light Hotkey", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), new ConfigDescription("Client-only hotkey that toggles the equipped Dvergr circlet light on or off.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 930
				}
			}), synchronizedSetting: false);
		}
	}
	internal static class ConfigValueHelpers
	{
		public static HashSet<string> SplitPrefabList(string value)
		{
			return (from item in (value ?? "").Split(new char[4] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)
				select item.Trim() into item
				where item.Length > 0
				select item).ToHashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		public static bool IsShortcutHeld(KeyboardShortcut shortcut, bool allowUnbound)
		{
			//IL_0002: 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)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return allowUnbound;
			}
			if (IsModifierKeyHeld(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierKeyHeld);
			}
			return false;
		}

		public static bool IsShortcutDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierKeyHeld))
			{
				return IsKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey);
			}
			return false;
		}

		public static string FormatShortcut(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return "None";
			}
			List<string> list = (from text in ((KeyboardShortcut)(ref shortcut)).Modifiers.Where((KeyCode key) => (int)key > 0).Select(FormatKeyCode)
				where !string.IsNullOrWhiteSpace(text)
				select text).ToList();
			list.Add(FormatKeyCode(((KeyboardShortcut)(ref shortcut)).MainKey));
			if (list.Count != 0)
			{
				return string.Join("+", list);
			}
			return "None";
		}

		private unsafe static string FormatKeyCode(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected I4, but got Unknown
			if ((int)key == 0)
			{
				return "";
			}
			string text = (key - 323) switch
			{
				0 => "Mouse1", 
				1 => "Mouse2", 
				2 => "Mouse3", 
				3 => "Mouse4", 
				4 => "Mouse5", 
				5 => "Mouse6", 
				6 => "Mouse7", 
				_ => "", 
			};
			if (text.Length > 0)
			{
				return text;
			}
			return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().Replace("LeftControl", "Ctrl").Replace("RightControl", "Ctrl")
				.Replace("LeftShift", "Shift")
				.Replace("RightShift", "Shift")
				.Replace("LeftAlt", "Alt")
				.Replace("RightAlt", "Alt");
		}

		private static bool IsModifierKeyHeld(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected I4, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected I4, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				switch (key - 303)
				{
				default:
					return (key - 323) switch
					{
						0 => Input.GetMouseButton(0), 
						1 => Input.GetMouseButton(1), 
						2 => Input.GetMouseButton(2), 
						3 => Input.GetMouseButton(3), 
						4 => Input.GetMouseButton(4), 
						5 => Input.GetMouseButton(5), 
						6 => Input.GetMouseButton(6), 
						_ => Input.GetKey(key), 
					};
				case 2:
				case 3:
					return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305);
				case 0:
				case 1:
					return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				case 4:
				case 5:
					return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
				}
			}
			return false;
		}

		private static bool IsKeyDown(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected I4, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			return (key - 323) switch
			{
				0 => Input.GetMouseButtonDown(0), 
				1 => Input.GetMouseButtonDown(1), 
				2 => Input.GetMouseButtonDown(2), 
				3 => Input.GetMouseButtonDown(3), 
				4 => Input.GetMouseButtonDown(4), 
				5 => Input.GetMouseButtonDown(5), 
				6 => Input.GetMouseButtonDown(6), 
				_ => Input.GetKeyDown(key), 
			};
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		[UsedImplicitly]
		public int? Order;

		[UsedImplicitly]
		public bool? Browsable;

		[UsedImplicitly]
		public string? Category;

		[UsedImplicitly]
		public Action<ConfigEntryBase>? CustomDrawer;
	}
	internal static class HomesteadFeatureBootstrap
	{
		private static Player? _lastLocalPlayer;

		public static void Initialize(ManualLogSource logger, Harmony harmony)
		{
			HomesteadInputBlockers.Initialize(logger);
			ZoneSessionResetRegistry.Initialize(logger);
			ZoneBlueprintCommands.Initialize(logger);
			ZoneBlueprintSaveTool.Initialize(logger);
			ZoneAreaDismantleTool.Initialize(logger);
			ZoneBlueprintPlacementTool.Initialize(logger);
			ZoneBlueprintChestVfx.Initialize(logger);
			ZoneBlueprintPlanChestPrefab.Initialize(logger);
			ZoneBlueprintChestZdoRegistry.Initialize(logger);
			ZoneBlueprintChestMapPins.Initialize(logger);
			ZoneBlueprintChestCommands.Initialize(logger);
			ZoneBlueprintStore.Initialize(logger);
			ZoneAreaRepair.Initialize(logger);
			ZoneBuildCamera.Initialize(logger);
			ZoneGridSnap.Initialize(logger);
			ZonePlacementAdjust.Initialize(logger);
			ZoneDvergrCirclet.Initialize(logger);
			RegisterSessionResetters();
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			ZoneBuildCameraFirstPersonCompat.Initialize(logger, harmony);
			VeiledRecipesCompat.Initialize(logger);
			AzuCraftyBoxesCompat.Initialize(logger, harmony);
			ZoneWorldEditTerrainCompat.Initialize(logger, harmony);
		}

		private static void RegisterSessionResetters()
		{
			ZoneSessionResetRegistry.Register("Blueprint RPC queue", ZoneBlueprintNetworkPayload.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Blueprint plan ghost cleanup", ZoneBlueprintCommands.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Area dismantle tool", ZoneAreaDismantleTool.Deactivate);
			ZoneSessionResetRegistry.Register("Blueprint placement tool", ZoneBlueprintPlacementTool.Deactivate);
			ZoneSessionResetRegistry.Register("Blueprint menu", ZoneBlueprintSaveToolMenu.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Blueprint visual descriptors", ZoneBlueprintPreviewBuilder.ClearCache);
			ZoneSessionResetRegistry.Register("Blueprint plan RPC", ZoneBlueprintPlanRpc.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Blueprint store", ZoneBlueprintStore.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Build camera", ZoneBuildCamera.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("ContentsWithin preview", ZoneContentsWithinBlueprintChestPreview.ResetForWorldSession);
			ZoneSessionResetRegistry.Register("Dvergr circlet", ZoneDvergrCirclet.ResetForWorldSession);
		}

		public static void Update()
		{
			ZoneBlueprintNetworkPayload.Update();
			ZoneBlueprintChestZdoRegistry.Update();
			ZoneBlueprintCommands.Update();
			ZoneBlueprintChestCommands.RegisterRpcs();
			ZoneBlueprintChestVfx.Update();
			ZoneAreaDismantleTool.RegisterRpcs();
			ZoneBlueprintSaveToolMenu.Update();
			ZoneBlueprintPlanRpc.Update();
			ZoneBlueprintStore.Update();
			ZoneBuildCamera.Update();
			ZoneGridSnap.Update();
			ZoneDvergrCirclet.Update();
			VeiledRecipesCompat.Update();
			ZoneWorldEditTerrainCompat.Update();
		}

		public static void Shutdown()
		{
			ZoneSessionResetRegistry.ResetForWorldSession("shutdown");
			ZoneBuildCameraFirstPersonCompat.Shutdown();
			ZoneBlueprintChestMapPins.Shutdown();
			ZoneBlueprintChestZdoRegistry.Shutdown();
			ZoneBlueprintStoreDraftRepository.Flush(force: true);
		}

		public static void OnLocalPlayerSet()
		{
			ZoneBuildCamera.DisableBuildMode();
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)localPlayer == (Object)(object)_lastLocalPlayer))
			{
				_lastLocalPlayer = localPlayer;
				ZoneSessionResetRegistry.ResetForWorldSession("local player changed");
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
	internal static class HomesteadPlayerSetLocalPlayerPatch
	{
		private static void Postfix()
		{
			HomesteadFeatureBootstrap.OnLocalPlayerSet();
		}
	}
	internal static class HomesteadInputBlockers
	{
		private static ManualLogSource? _logger;

		private static bool _useTextInputFallback;

		private static bool _loggedTextInputFallback;

		internal static void Initialize(ManualLogSource logger)
		{
			_logger = logger;
		}

		internal static bool IsTextInputVisible()
		{
			if (!_useTextInputFallback)
			{
				try
				{
					return TextInput.IsVisible() || IsFocusedInputField();
				}
				catch (Exception ex)
				{
					_useTextInputFallback = true;
					LogTextInputFallback(ex);
				}
			}
			if (!IsValheimTextInputVisible())
			{
				return IsFocusedInputField();
			}
			return true;
		}

		internal static bool IsCommonGameplayInputBlocked()
		{
			if (!Console.IsVisible() && !IsTextInputVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
			{
				return Minimap.IsOpen();
			}
			return true;
		}

		private static bool IsValheimTextInputVisible()
		{
			TextInput instance = TextInput.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				return instance.m_visibleFrame;
			}
			return false;
		}

		private static bool IsFocusedInputField()
		{
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				return false;
			}
			GameObject currentSelectedGameObject = current.currentSelectedGameObject;
			if (!Object.op_Implicit((Object)(object)currentSelectedGameObject))
			{
				return false;
			}
			InputField val = currentSelectedGameObject.GetComponent<InputField>() ?? currentSelectedGameObject.GetComponentInParent<InputField>();
			if ((Object)(object)val != (Object)null && val.isFocused)
			{
				return true;
			}
			TMP_InputField val2 = currentSelectedGameObject.GetComponent<TMP_InputField>() ?? currentSelectedGameObject.GetComponentInParent<TMP_InputField>();
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.isFocused;
			}
			return false;
		}

		private static void LogTextInputFallback(Exception ex)
		{
			if (!_loggedTextInputFallback)
			{
				_loggedTextInputFallback = true;
				ManualLogSource? logger = _logger;
				if (logger != null)
				{
					logger.LogWar