Decompiled source of PlantEasily v2.1.0

Advize_PlantEasily.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Advize_PlantEasily")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Valheim Game Modification")]
[assembly: AssemblyCopyright("Copyright © Advize 2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5eaff7d4-7661-4152-a841-ed19ba3b36f4")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public string Description;

	public int? Order;
}
namespace Advize_PlantEasily
{
	internal enum GridSnappingStyle
	{
		Intelligent,
		Legacy
	}
	internal enum HarvestStyle
	{
		LikeResources,
		AllResources
	}
	internal enum CostDisplayStyle
	{
		TotalCount,
		FullCost
	}
	internal enum CostDisplayLocation
	{
		LeftSide,
		RightSide
	}
	internal static class ConfigEventHandlers
	{
		internal static void GridSizeChanged(object sender, EventArgs e)
		{
			GhostGrid.ResizeGrid();
		}

		internal static void KeybindsChanged(object sender, EventArgs e)
		{
			KeyHintPatches.UpdateKeyHintText();
		}

		internal static void GridSpacingChanged(object sender, EventArgs e)
		{
			PickableDB.InitPickableSpacingConfig();
		}

		internal static void GridColorChanged(object sender, EventArgs e)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)GhostGrid.DirectionRenderer))
			{
				GhostGrid.LineRenderers[0].startColor = ModContext.config.RowStartColor;
				GhostGrid.LineRenderers[0].endColor = ModContext.config.RowEndColor;
				GhostGrid.LineRenderers[1].startColor = ModContext.config.ColumnStartColor;
				GhostGrid.LineRenderers[1].endColor = ModContext.config.ColumnEndColor;
				GhostGrid.LineRenderers[2].startColor = ModContext.config.SnapStartColor;
				GhostGrid.LineRenderers[2].endColor = ModContext.config.SnapEndColor;
			}
		}
	}
	internal static class ConfigExtensions
	{
		private static readonly Dictionary<string, int> _sectionOrder = new Dictionary<string, int>();

		internal static ConfigEntry<T> BindInOrder<T>(this ConfigFile config, string section, string key, T defaultValue, string description, Action<ConfigurationManagerAttributes> manualAttributes = null, AcceptableValueBase acceptableValues = null)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			if (!_sectionOrder.TryGetValue(section, out var value))
			{
				value = 100;
			}
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Order = value
			};
			manualAttributes?.Invoke(configurationManagerAttributes);
			if (configurationManagerAttributes.Order == value)
			{
				_sectionOrder[section] = value - 1;
			}
			ConfigDescription val = new ConfigDescription(description, acceptableValues, new object[1] { configurationManagerAttributes });
			return config.Bind<T>(section, key, defaultValue, val);
		}
	}
	internal sealed class ModConfig
	{
		private readonly ConfigFile Config;

		private readonly ConfigEntry<KeyboardShortcut> enableModKey;

		private readonly ConfigEntry<KeyboardShortcut> enableSnappingKey;

		private readonly ConfigEntry<KeyboardShortcut> toggleAutoReplantKey;

		private readonly ConfigEntry<KeyboardShortcut> increaseXKey;

		private readonly ConfigEntry<KeyboardShortcut> increaseYKey;

		private readonly ConfigEntry<KeyboardShortcut> decreaseXKey;

		private readonly ConfigEntry<KeyboardShortcut> decreaseYKey;

		private readonly ConfigEntry<KeyboardShortcut> keyboardModifierKey;

		private readonly ConfigEntry<KeyboardShortcut> gamepadModifierKey;

		private readonly ConfigEntry<KeyboardShortcut> keyboardHarvestModifierKey;

		private readonly ConfigEntry<bool> preventPartialPlanting;

		private readonly ConfigEntry<bool> preventInvalidPlanting;

		private readonly ConfigEntry<bool> useStamina;

		private readonly ConfigEntry<bool> useDurability;

		private readonly ConfigEntry<bool> modActive;

		private readonly ConfigEntry<bool> snapActive;

		private readonly ConfigEntry<int> rows;

		private readonly ConfigEntry<int> columns;

		private readonly ConfigEntry<bool> randomizeRotation;

		private readonly ConfigEntry<bool> enableScatter;

		private readonly ConfigEntry<float> positionScatterRadius;

		private readonly ConfigEntry<float> rotationScatterAngle;

		private readonly ConfigEntry<bool> enableDebugMessages;

		private readonly ConfigEntry<bool> globallyAlignGridDirections;

		private readonly ConfigEntry<bool> minimizeGridSpacing;

		private readonly ConfigEntry<GridSnappingStyle> gridSnappingStyle;

		private readonly ConfigEntry<bool> forceAltPlacement;

		private readonly ConfigEntry<bool> preferCardinalSnapping;

		private readonly ConfigEntry<float> extraCropSpacing;

		private readonly ConfigEntry<float> extraSaplingSpacing;

		private readonly ConfigEntry<bool> enableBulkHarvest;

		private readonly ConfigEntry<HarvestStyle> harvestStyle;

		private readonly ConfigEntry<float> harvestRadius;

		private readonly ConfigEntry<bool> replantOnHarvest;

		private readonly ConfigEntry<int> maxConcurrentPlacements;

		private readonly ConfigEntry<int> ghostUpdateBatchSize;

		private readonly ConfigEntry<int> bulkPlantingBatchSize;

		private readonly ConfigEntry<bool> preventOverlappingPlacements;

		private readonly ConfigEntry<float> defaultGridSpacing;

		private readonly ConfigEntry<bool> showCost;

		private readonly ConfigEntry<CostDisplayStyle> costDisplayStyle;

		private readonly ConfigEntry<CostDisplayLocation> costDisplayLocation;

		private readonly ConfigEntry<bool> showHUDKeyHints;

		private readonly ConfigEntry<bool> showHoverKeyHints;

		private readonly ConfigEntry<bool> showHoverReplantHint;

		private readonly ConfigEntry<bool> showGhostsDuringPlacement;

		private readonly ConfigEntry<bool> showGridDirections;

		private readonly ConfigEntry<bool> showSnapDirection;

		private readonly ConfigEntry<bool> highlightRootPlacementGhost;

		private readonly ConfigEntry<Color> rootGhostHighlightColor;

		private readonly ConfigEntry<Color> rowStartColor;

		private readonly ConfigEntry<Color> rowEndColor;

		private readonly ConfigEntry<Color> columnStartColor;

		private readonly ConfigEntry<Color> columnEndColor;

		private readonly ConfigEntry<Color> snapStartColor;

		private readonly ConfigEntry<Color> snapEndColor;

		internal KeyboardShortcut EnableModKey => enableModKey.Value;

		internal KeyboardShortcut EnableSnappingKey => enableSnappingKey.Value;

		internal KeyboardShortcut ToggleAutoReplantKey => toggleAutoReplantKey.Value;

		internal KeyCode IncreaseXKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = increaseXKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode IncreaseYKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = increaseYKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode DecreaseXKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = decreaseXKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode DecreaseYKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = decreaseYKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode KeyboardModifierKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = keyboardModifierKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode GamepadModifierKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = gamepadModifierKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal KeyCode KeyboardHarvestModifierKey
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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)
				KeyboardShortcut value = keyboardHarvestModifierKey.Value;
				return ((KeyboardShortcut)(ref value)).MainKey;
			}
		}

		internal bool PreventPartialPlanting => preventPartialPlanting.Value;

		internal bool PreventInvalidPlanting => preventInvalidPlanting.Value;

		internal bool UseStamina => useStamina.Value;

		internal bool UseDurability => useDurability.Value;

		internal bool ModActive
		{
			get
			{
				return modActive.Value;
			}
			set
			{
				((ConfigEntryBase)modActive).BoxedValue = value;
			}
		}

		internal bool SnapActive
		{
			get
			{
				return snapActive.Value;
			}
			set
			{
				((ConfigEntryBase)snapActive).BoxedValue = value;
			}
		}

		internal int Rows
		{
			get
			{
				return Mathf.Max(rows.Value, 1);
			}
			set
			{
				((ConfigEntryBase)rows).BoxedValue = Mathf.Max(value, 1);
			}
		}

		internal int Columns
		{
			get
			{
				return Mathf.Max(columns.Value, 1);
			}
			set
			{
				((ConfigEntryBase)columns).BoxedValue = Mathf.Max(value, 1);
			}
		}

		internal bool RandomizeRotation => randomizeRotation.Value;

		internal bool EnableDebugMessages => enableDebugMessages.Value;

		internal bool GloballyAlignGridDirections => globallyAlignGridDirections.Value;

		internal bool MinimizeGridSpacing => minimizeGridSpacing.Value;

		internal GridSnappingStyle GridSnappingStyle => gridSnappingStyle.Value;

		internal bool ForceAltPlacement => forceAltPlacement.Value;

		internal bool PreferCardinalSnapping => preferCardinalSnapping.Value;

		internal float ExtraCropSpacing => extraCropSpacing.Value;

		internal float ExtraSaplingSpacing => extraSaplingSpacing.Value;

		internal bool EnableBulkHarvest => enableBulkHarvest.Value;

		internal HarvestStyle HarvestStyle => harvestStyle.Value;

		internal float HarvestRadius => harvestRadius.Value;

		internal bool ReplantOnHarvest
		{
			get
			{
				return replantOnHarvest.Value;
			}
			set
			{
				((ConfigEntryBase)replantOnHarvest).BoxedValue = value;
			}
		}

		internal int MaxConcurrentPlacements => maxConcurrentPlacements.Value;

		internal int GhostUpdateBatchSize => ghostUpdateBatchSize.Value;

		internal int BulkPlantingBatchSize => bulkPlantingBatchSize.Value;

		internal bool PreventOverlappingPlacements => preventOverlappingPlacements.Value;

		internal float DefaultGridSpacing => defaultGridSpacing.Value;

		internal bool ShowCost => showCost.Value;

		internal CostDisplayStyle CostDisplayStyle => costDisplayStyle.Value;

		internal CostDisplayLocation CostDisplayLocation => costDisplayLocation.Value;

		internal bool ShowHUDKeyHints => showHUDKeyHints.Value;

		internal bool ShowHoverKeyHints => showHoverKeyHints.Value;

		internal bool ShowHoverReplantHint => showHoverReplantHint.Value;

		internal bool ShowGhostsDuringPlacement => showGhostsDuringPlacement.Value;

		internal bool ShowGridDirections => showGridDirections.Value;

		internal bool ShowSnapDirection => showSnapDirection.Value;

		internal bool HighlightRootPlacementGhost => highlightRootPlacementGhost.Value;

		internal Color RootGhostHighlightColor => rootGhostHighlightColor.Value;

		internal Color RowStartColor => rowStartColor.Value;

		internal Color RowEndColor => rowEndColor.Value;

		internal Color ColumnStartColor => columnStartColor.Value;

		internal Color ColumnEndColor => columnEndColor.Value;

		internal Color SnapStartColor => snapStartColor.Value;

		internal Color SnapEndColor => snapEndColor.Value;

		internal ModConfig(ConfigFile configFile)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0919: Unknown result type (might be due to invalid IL or missing references)
			//IL_0940: Unknown result type (might be due to invalid IL or missing references)
			//IL_0967: Unknown result type (might be due to invalid IL or missing references)
			//IL_098e: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b5: Unknown result type (might be due to invalid IL or missing references)
			Config = configFile;
			configFile.SaveOnConfigSet = false;
			enableModKey = Config.BindInOrder<KeyboardShortcut>("Controls", "EnableModKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key to toggle on/off all mod features. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to toggle on/off all mod features.";
			});
			enableSnappingKey = Config.BindInOrder<KeyboardShortcut>("Controls", "EnableSnappingKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Key to toggle on/off piece snapping functionality. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to toggle on/off piece snapping functionality.";
			});
			toggleAutoReplantKey = Config.BindInOrder<KeyboardShortcut>("Controls", "ToggleAutoReplantKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Key to toggle on/off the [Harvesting]ReplantOnHarvest setting. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to toggle on/off the [Harvesting]ReplantOnHarvest setting.";
			});
			increaseXKey = Config.BindInOrder<KeyboardShortcut>("Controls", "IncreaseXKey", new KeyboardShortcut((KeyCode)275, Array.Empty<KeyCode>()), "Key to increase number of grid columns. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to increase number of grid columns.";
			});
			increaseYKey = Config.BindInOrder<KeyboardShortcut>("Controls", "IncreaseYKey", new KeyboardShortcut((KeyCode)273, Array.Empty<KeyCode>()), "Key to increase number of grid rows. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to increase number of grid rows.";
			});
			decreaseXKey = Config.BindInOrder<KeyboardShortcut>("Controls", "DecreaseXKey", new KeyboardShortcut((KeyCode)276, Array.Empty<KeyCode>()), "Key to decrease number of grid columns. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to decrease number of grid columns.";
			});
			decreaseYKey = Config.BindInOrder<KeyboardShortcut>("Controls", "DecreaseYKey", new KeyboardShortcut((KeyCode)274, Array.Empty<KeyCode>()), "Key to decrease number of grid rows. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Key to decrease number of grid rows.";
			});
			keyboardModifierKey = Config.BindInOrder<KeyboardShortcut>("Controls", "KeyboardModifierKey", new KeyboardShortcut((KeyCode)305, Array.Empty<KeyCode>()), "Modifier key when using keyboard controls. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Modifier key when using keyboard controls.";
			});
			gamepadModifierKey = Config.BindInOrder<KeyboardShortcut>("Controls", "GamepadModifierKey", new KeyboardShortcut((KeyCode)334, Array.Empty<KeyCode>()), "Modifier key when using gamepad controls. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Modifier key when using gamepad controls.";
			});
			keyboardHarvestModifierKey = Config.BindInOrder<KeyboardShortcut>("Controls", "KeyboardHarvestModifierKey", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "Modifier key to enable bulk harvest when using keyboard controls. See https://docs.unity3d.com/ScriptReference/KeyCode.html", delegate(ConfigurationManagerAttributes a)
			{
				a.Description = "Modifier key to enable bulk harvest when using keyboard controls.";
			});
			preventPartialPlanting = Config.BindInOrder("Difficulty", "PreventPartialPlanting", defaultValue: false, "Prevents placement of resources when any placement ghosts are invalid for any reason.");
			preventInvalidPlanting = Config.BindInOrder("Difficulty", "PreventInvalidPlanting", defaultValue: true, "Prevents plants from being placed where they will be unable to grow.");
			useStamina = Config.BindInOrder("Difficulty", "UseStamina", defaultValue: true, "Consume stamina for every piece placed.");
			useDurability = Config.BindInOrder("Difficulty", "UseDurability", defaultValue: true, "Decrease durability of cultivator for every piece placed.");
			modActive = Config.BindInOrder("General", "ModActive", defaultValue: true, "Enables all mod features.");
			snapActive = Config.BindInOrder("General", "SnapActive", defaultValue: true, "Enables grid snapping feature.");
			rows = Config.BindInOrder("General", "Rows", 2, "Number of rows for planting grid aka height.");
			columns = Config.BindInOrder("General", "Columns", 2, "Number of columns for planting grid aka width.");
			randomizeRotation = Config.BindInOrder("General", "RandomizeRotation", defaultValue: true, "Randomizes rotation of pieces once placed.");
			enableScatter = Config.BindInOrder("General", "EnableScatter", defaultValue: true, "Enables subtle randomization of placement to prevent grids from looking overly uniform. Controls both positional scatter and rotational tilt.");
			positionScatterRadius = Config.BindInOrder("General", "PositionScatterRadius", 0f, "Applies small random offsets to the X/Z position of placed pieces. Keep values low (0.01–0.05) to avoid visible grid distortion, especially in large grids.");
			rotationScatterAngle = Config.BindInOrder("General", "RotationScatterAngle", 0f, "Applies small random X/Z tilt to placed pieces. Recommended values: 1–3 degrees. Excessive tilt may interfere with crop growth or placement clearance.");
			enableDebugMessages = Config.BindInOrder("General", "EnableDebugMessages", defaultValue: false, "Enable mod debug messages in console.");
			globallyAlignGridDirections = Config.BindInOrder("Grid", "GloballyAlignGridDirections", defaultValue: true, "When set to true, new grid placements will have their column and row directions align with the global grid.");
			minimizeGridSpacing = Config.BindInOrder("Grid", "MinimizeGridSpacing", defaultValue: false, "Allows for tighter grids, but with varying spacing used between diverse/distinct plants. ");
			gridSnappingStyle = Config.BindInOrder("Grid", "GridSnappingStyle", GridSnappingStyle.Intelligent, "Determines grid snapping style. Intelligent will attempt to prevent a new grid from overlapping with an old one. Legacy will allow any orientation of new rows and columns.");
			forceAltPlacement = Config.BindInOrder("Grid", "ForceAltPlacement", defaultValue: false, "When enabled, alternate placement mode for the cultivator is always used. Alternate placement mode allows free rotation when snapping to a single piece.");
			preferCardinalSnapping = Config.BindInOrder("Grid", "PreferCardinalSnapping", defaultValue: false, "Prefer cardinal snap points over diagonal snap points when snapping to existing grids.");
			extraCropSpacing = Config.BindInOrder("Grid", "ExtraCropSpacing", 0f, "Adds extra spacing between crops. Accepts negative values to decrease spacing (not recommended).");
			extraSaplingSpacing = Config.BindInOrder("Grid", "ExtraSaplingSpacing", 0f, "Adds extra spacing between saplings. Accepts negative values to decrease spacing (not recommended).");
			enableBulkHarvest = Config.BindInOrder("Harvesting", "EnableBulkHarvest", defaultValue: true, "Enables the ability to harvest multiple resources at once.");
			harvestStyle = Config.BindInOrder("Harvesting", "HarvestStyle", HarvestStyle.AllResources, "Determines bulk harvest style. LikeResources only harvests resources of the type you've interacted with. AllResources harvests all eligible resources.");
			harvestRadius = Config.BindInOrder("Harvesting", "HarvestRadius", 3f, "Determines radius used to search for resources when bulk harvesting.");
			replantOnHarvest = Config.BindInOrder("Harvesting", "ReplantOnHarvest", defaultValue: false, "Enables automatic replanting of crops when harvested, provided you have the resources.");
			maxConcurrentPlacements = Config.BindInOrder("Performance", "MaxConcurrentPlacements", 500, "Maximum amount of pieces that can be placed at once with the cultivator.", null, (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 10000));
			ghostUpdateBatchSize = Config.BindInOrder("Performance", "GhostUpdateBatchSize", 20, "This value determines how many placement ghosts can update their positions, rotations, etc. per frame. Reducing this value will improve performance during placement and snapping.", null, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000));
			bulkPlantingBatchSize = Config.BindInOrder("Performance", "BulkPlantingBatchSize", 2, "This value determines how many concurrent pieces can be placed per frame. Increase to speed up planting. Reduce this value if the game hangs when placing too many pieces at once.", null, (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 10000));
			preventOverlappingPlacements = Config.BindInOrder("Pickables", "PreventOverlappingPlacements", defaultValue: true, "Prevents placement of pickable resources on top of colliding obstructions.");
			defaultGridSpacing = Config.BindInOrder("Pickables", "DefaultGridSpacing", 1f, "Determines default distance/spacing between pickable resources when planting.");
			showCost = Config.BindInOrder("UI", "ShowCost", defaultValue: true, "Update resource cost in build UI.");
			costDisplayStyle = Config.BindInOrder("UI", "CostDisplayStyle", CostDisplayStyle.TotalCount, "Determines display style of the ShowCost setting. TotalCount shows total number of pieces to be placed. FullCost shows combined resoure cost of all pieces.");
			costDisplayLocation = Config.BindInOrder("UI", "CostDisplayLocation", CostDisplayLocation.RightSide, "Determines whether to prepend or append text to the resource cost in build UI. LeftSide or RightSide will prepend or append respectively.");
			showHUDKeyHints = Config.BindInOrder("UI", "ShowHUDKeyHints", defaultValue: true, "Show KeyHints in build HUD.");
			showHoverKeyHints = Config.BindInOrder("UI", "ShowHoverKeyHints", defaultValue: true, "Show KeyHints in hover text.");
			showHoverReplantHint = Config.BindInOrder("UI", "ShowHoverReplantHint", defaultValue: true, "Show crop to be replanted upon harvest in hover text.");
			showGhostsDuringPlacement = Config.BindInOrder("UI", "ShowGhostsDuringPlacement", defaultValue: true, "Show silhouettes of placement ghosts during placement.");
			showGridDirections = Config.BindInOrder("UI", "ShowGridDirections", defaultValue: true, "Render lines indicating direction of rows and columns.");
			showSnapDirection = Config.BindInOrder("UI", "ShowSnapDirection", defaultValue: true, "Render a line from root placement ghost to the position it's snapping from.");
			highlightRootPlacementGhost = Config.BindInOrder("UI", "HighlightRootGhost", defaultValue: true, "Highlight the root placement ghost while bulk planting.");
			rootGhostHighlightColor = Config.BindInOrder<Color>("UI", "RootGhostHighlightColor", Color.green, "Highlight color for root placement ghost when [UI]HighlightRootGhost is enabled.");
			rowStartColor = Config.BindInOrder<Color>("UI", "RowStartColor", Color.blue, "Starting color for row direction when [UI]ShowGridDirections is enabled.");
			rowEndColor = Config.BindInOrder<Color>("UI", "RowEndColor", Color.cyan, "Ending color for row direction when [UI]ShowGridDirections is enabled.");
			columnStartColor = Config.BindInOrder<Color>("UI", "ColumnStartColor", Color.green, "Starting color for column direction when [UI]ShowGridDirections is enabled.");
			columnEndColor = Config.BindInOrder<Color>("UI", "ColumnEndColor", Color.yellow, "Ending color for column direction when [UI]ShowGridDirections is enabled.");
			snapStartColor = Config.BindInOrder<Color>("UI", "SnapStartColor", Color.red, "Starting color for snap direction when [UI]ShowGridDirections is enabled.");
			snapEndColor = Config.BindInOrder<Color>("UI", "SnapEndColor", Color.magenta, "Ending color for snap direction when [UI]ShowGridDirections is enabled.");
			configFile.Save();
			configFile.SaveOnConfigSet = true;
			rows.SettingChanged += ConfigEventHandlers.GridSizeChanged;
			columns.SettingChanged += ConfigEventHandlers.GridSizeChanged;
			maxConcurrentPlacements.SettingChanged += ConfigEventHandlers.GridSizeChanged;
			increaseXKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			increaseYKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			decreaseXKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			decreaseYKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			keyboardModifierKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			gamepadModifierKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			keyboardHarvestModifierKey.SettingChanged += ConfigEventHandlers.KeybindsChanged;
			showGridDirections.SettingChanged += delegate
			{
				GameObject directionRenderer = GhostGrid.DirectionRenderer;
				if (directionRenderer != null)
				{
					directionRenderer.SetActive(false);
				}
			};
			rowStartColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
			rowEndColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
			columnStartColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
			columnEndColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
			snapStartColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
			snapEndColor.SettingChanged += ConfigEventHandlers.GridColorChanged;
		}

		internal void BindPickableSpacingSettings()
		{
			Config.SaveOnConfigSet = false;
			Dictionary<string, float> dictionary = new Dictionary<string, float>
			{
				{ "Pickable_Dandelion", 0.75f },
				{ "Pickable_Fiddlehead", 1f },
				{ "Pickable_Mushroom", 0.5f },
				{ "Pickable_Mushroom_blue", 0.5f },
				{ "Pickable_Mushroom_yellow", 0.5f },
				{ "Pickable_SmokePuff", 1f },
				{ "Pickable_Thistle", 0.75f },
				{ "BlueberryBush", 1.5f },
				{ "RaspberryBush", 1.5f },
				{ "CloudberryBush", 1f }
			};
			foreach (PickableDB pickableRef in ModContext.PickableRefs)
			{
				float value;
				float num = (dictionary.TryGetValue(pickableRef.key, out value) ? value : DefaultGridSpacing);
				pickableRef.itemName = Localization.instance.Localize(pickableRef.Prefab.GetComponent<Pickable>().m_itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name);
				pickableRef.configEntry = Config.Bind<float>("Pickables", pickableRef.key + " GridSpacing", num, "Determines distance/spacing between " + pickableRef.itemName + " when planting.");
				pickableRef.configEntry.SettingChanged += ConfigEventHandlers.GridSpacingChanged;
			}
			dictionary.Clear();
			Config.Save();
			Config.SaveOnConfigSet = true;
		}

		internal bool TryGetScatterRadius(out float radius)
		{
			radius = positionScatterRadius.Value;
			if (enableScatter.Value)
			{
				return radius != 0f;
			}
			return false;
		}

		internal bool TryGetScatterAngle(out float angle)
		{
			angle = rotationScatterAngle.Value;
			if (enableScatter.Value)
			{
				return angle != 0f;
			}
			return false;
		}
	}
	internal sealed class PlacementController : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <BulkPlanting>d__9 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public PlacementController <>4__this;

			public GameObject piecePrefab;

			private Player <player>5__2;

			private int <count>5__3;

			private List<GameObject>.Enumerator <>7__wrap3;

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

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

			[DebuggerHidden]
			public <BulkPlanting>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<player>5__2 = null;
				<>7__wrap3 = default(List<GameObject>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					int num = <>1__state;
					PlacementController placementController = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						<player>5__2 = Player.m_localPlayer;
						placementController._isPlanting = true;
						<count>5__3 = 0;
						bool showGhostsDuringPlacement = ModContext.config.ShowGhostsDuringPlacement;
						foreach (GameObject extraGhost in GhostGrid.ExtraGhosts)
						{
							if (!showGhostsDuringPlacement || !GhostGrid.ValidExtraGhosts.Contains(extraGhost))
							{
								placementController.DisableRenderers(extraGhost);
							}
						}
						if (showGhostsDuringPlacement)
						{
							foreach (GameObject validExtraGhost in GhostGrid.ValidExtraGhosts)
							{
								MaterialMan.instance.SetValue<Color>(validExtraGhost, ShaderProps._Color, Color.gray);
							}
						}
						<>7__wrap3 = GhostGrid.ValidExtraGhosts.GetEnumerator();
						<>1__state = -3;
						break;
					}
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap3.MoveNext())
					{
						GameObject current3 = <>7__wrap3.Current;
						<count>5__3++;
						PlacePiece(<player>5__2, current3, piecePrefab);
						if (<count>5__3 % ModContext.config.BulkPlantingBatchSize == 0)
						{
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap3 = default(List<GameObject>.Enumerator);
					GhostGrid.ValidExtraGhosts.Clear();
					placementController._isPlanting = false;
					<player>5__2.SetupPlacementGhost();
					placementController.ReEnableRenderers();
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap3).Dispose();
			}

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

		private static PlacementController _instance;

		private readonly List<Renderer> _disabledRenderers = new List<Renderer>();

		private bool _isPlanting;

		internal static PlacementController Instance => _instance ?? (_instance = Initialize());

		internal static bool IsPlanting => Instance._isPlanting;

		private static PlacementController Initialize()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			GameObject val = new GameObject($"PlantEasily_PlacementController_{Guid.NewGuid()}")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			return val.AddComponent<PlacementController>();
		}

		internal void OnDestroy()
		{
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
		}

		[IteratorStateMachine(typeof(<BulkPlanting>d__9))]
		internal IEnumerator BulkPlanting(GameObject piecePrefab)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BulkPlanting>d__9(0)
			{
				<>4__this = this,
				piecePrefab = piecePrefab
			};
		}

		internal static void PlacePiece(Player player, GameObject go, GameObject piecePrefab)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = go.transform;
			Vector3 position = transform.position;
			if (ModContext.config.TryGetScatterRadius(out var radius))
			{
				position.x += Random.Range(0f - radius, radius);
				position.z += Random.Range(0f - radius, radius);
			}
			Quaternion val = (ModContext.config.RandomizeRotation ? Quaternion.Euler(0f, 22.5f * (float)Random.Range(0, 16), 0f) : transform.rotation);
			if (ModContext.config.TryGetScatterAngle(out var angle))
			{
				val *= Quaternion.Euler(Random.Range(0f - angle, angle), 0f, Random.Range(0f - angle, angle));
			}
			go.SetActive(false);
			TerrainModifier.SetTriggerOnPlaced(true);
			GameObject obj = Object.Instantiate<GameObject>(piecePrefab, position, val);
			TerrainModifier.SetTriggerOnPlaced(false);
			obj.GetComponent<Piece>().SetCreator(player.GetPlayerID());
			Game.instance.IncrementPlayerStat((PlayerStatType)2, 1f);
			((Character)player).RaiseSkill((SkillType)106, 1f);
		}

		private void DisableRenderers(GameObject go)
		{
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				val.enabled = false;
				_disabledRenderers.Add(val);
			}
		}

		private void ReEnableRenderers()
		{
			foreach (Renderer disabledRenderer in _disabledRenderers)
			{
				disabledRenderer.enabled = true;
			}
			_disabledRenderers.Clear();
		}
	}
	internal enum Status
	{
		Healthy,
		LackResources,
		NotCultivated,
		WrongBiome,
		NoSpace,
		NoSun,
		Invalid,
		NoAttachPiece,
		TooHot,
		TooCold
	}
	internal static class ModUtils
	{
		internal static bool HoldingCultivator
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				return ((localPlayer == null) ? null : ((Humanoid)localPlayer).GetRightItem()?.m_shared.m_name) == "$item_cultivator";
			}
		}

		internal static bool IsPlantOrPickable(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go.GetComponent<Plant>()))
			{
				return Object.op_Implicit((Object)(object)go.GetComponent<Pickable>());
			}
			return true;
		}

		internal static bool HasGrowSpace(Plant plant, Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Physics.OverlapSphere(position, plant.m_growRadius, Plant.m_spaceMask).Length == 0;
		}

		internal static bool PositionHasCollisions(Vector3 position)
		{
			//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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return Physics.CheckCapsule(position, position + Vector3.up * 0.1f, Mathf.Epsilon, CollisionScanner.CollisionMask);
		}

		internal static float GetPieceSpacing(GameObject go)
		{
			float num = 0f;
			bool flag = false;
			Plant component = go.GetComponent<Plant>();
			if (Object.op_Implicit((Object)(object)component))
			{
				GameObject[] grownPrefabs = component.m_grownPrefabs;
				List<GameObject> list = new List<GameObject>(1 + grownPrefabs.Length);
				list.Add(go);
				list.AddRange(grownPrefabs);
				List<GameObject> list2 = list;
				flag = list2.Any((GameObject x) => Object.op_Implicit((Object)(object)x.GetComponent<TreeBase>()));
				if (ModContext.config.MinimizeGridSpacing && !flag)
				{
					for (int i = 0; i < list2.Count; i++)
					{
						CapsuleCollider[] componentsInChildren = list2[i].GetComponentsInChildren<CapsuleCollider>();
						foreach (CapsuleCollider val in componentsInChildren)
						{
							num = Mathf.Max(num, val.radius);
						}
					}
				}
				num += (flag ? ModContext.config.ExtraSaplingSpacing : ModContext.config.ExtraCropSpacing);
			}
			return (flag ? (component.m_growRadius * 2.2f) : ((component?.m_growRadius * (ModContext.config.MinimizeGridSpacing ? 1.1f : 2f)) ?? PickableSnapRadius(go.GetComponent<Piece>()))) + num;
		}

		internal static HashSet<Interactable> FindResourcesInRadius(GameObject rootInteractable)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			HashSet<Interactable> hashSet = new HashSet<Interactable>();
			Transform root = rootInteractable.transform.root;
			Collider[] array = Physics.OverlapSphere(root.position, ModContext.config.HarvestRadius, CollisionScanner.CollisionMask);
			foreach (Collider val in array)
			{
				Pickable componentInParent = ((Component)val).GetComponentInParent<Pickable>();
				Beehive val2 = (Object.op_Implicit((Object)(object)componentInParent) ? null : ((Component)val).GetComponentInParent<Beehive>());
				if (Object.op_Implicit((Object)(object)componentInParent) || Object.op_Implicit((Object)(object)val2))
				{
					Transform root2 = (Object.op_Implicit((Object)(object)componentInParent) ? ((Component)componentInParent).gameObject : ((Component)val2).gameObject).transform.root;
					if (!((Object)(object)root2 == (Object)(object)root) && (ModContext.config.HarvestStyle != 0 || !(((Object)root2).name != ((Object)root).name)) && (!Object.op_Implicit((Object)(object)val2) || val2.GetHoneyLevel() >= 1))
					{
						Interactable val3 = (Interactable)(object)componentInParent;
						Interactable item = (Interactable)(((object)val3) ?? ((object)val2));
						hashSet.Add(item);
					}
				}
			}
			return hashSet;
		}

		private static float PickableSnapRadius(Piece p)
		{
			if (p == null || !(p.m_harvestRadius > 0f))
			{
				return ModContext.config.DefaultGridSpacing;
			}
			return p.m_harvestRadius;
		}
	}
	internal static class CollisionScanner
	{
		[CompilerGenerated]
		private sealed class <Scan>d__4 : IEnumerable<Transform>, IEnumerable, IEnumerator<Transform>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Transform <>2__current;

			private int <>l__initialThreadId;

			private Vector3 origin;

			public Vector3 <>3__origin;

			private float spacingRadius;

			public float <>3__spacingRadius;

			private int <count>5__2;

			private int <i>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<count>5__2 = Physics.OverlapSphereNonAlloc(origin, spacingRadius, _primary, CollisionMask);
					<i>5__3 = 0;
					break;
				case 1:
					<>1__state = -1;
					<i>5__3++;
					break;
				}
				if (<i>5__3 < <count>5__2)
				{
					<>2__current = ((Component)_primary[<i>5__3]).transform.root;
					<>1__state = 1;
					return true;
				}
				return false;
			}

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

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

			[DebuggerHidden]
			IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				<Scan>d__4 <Scan>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<Scan>d__ = this;
				}
				else
				{
					<Scan>d__ = new <Scan>d__4(0);
				}
				<Scan>d__.origin = <>3__origin;
				<Scan>d__.spacingRadius = <>3__spacingRadius;
				return <Scan>d__;
			}

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

		[CompilerGenerated]
		private sealed class <ScanNeighbours>d__5 : IEnumerable<Transform>, IEnumerable, IEnumerator<Transform>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Transform <>2__current;

			private int <>l__initialThreadId;

			private float expectedSpacing;

			public float <>3__expectedSpacing;

			private Transform primary;

			public Transform <>3__primary;

			private float <minSquared>5__2;

			private float <maxSquared>5__3;

			private int <neighbours>5__4;

			private Vector3 <origin>5__5;

			private int <i>5__6;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_0103;
				}
				<>1__state = -1;
				float num2 = Mathf.Max(expectedSpacing * 0.01f, 0.005f);
				float num3 = expectedSpacing - num2;
				float num4 = expectedSpacing + num2;
				<minSquared>5__2 = num3 * num3;
				<maxSquared>5__3 = num4 * num4;
				<neighbours>5__4 = Physics.OverlapSphereNonAlloc(primary.position, num4, _secondary, CollisionMask);
				<origin>5__5 = primary.position;
				<i>5__6 = 0;
				goto IL_0115;
				IL_0103:
				<i>5__6++;
				goto IL_0115;
				IL_0115:
				if (<i>5__6 < <neighbours>5__4)
				{
					Transform root = ((Component)_secondary[<i>5__6]).transform.root;
					if (!((Object)(object)root == (Object)(object)primary))
					{
						Vector3 val = root.position - <origin>5__5;
						float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
						if (sqrMagnitude >= <minSquared>5__2 && sqrMagnitude <= <maxSquared>5__3)
						{
							<>2__current = root;
							<>1__state = 1;
							return true;
						}
					}
					goto IL_0103;
				}
				return false;
			}

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

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

			[DebuggerHidden]
			IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
			{
				<ScanNeighbours>d__5 <ScanNeighbours>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ScanNeighbours>d__ = this;
				}
				else
				{
					<ScanNeighbours>d__ = new <ScanNeighbours>d__5(0);
				}
				<ScanNeighbours>d__.primary = <>3__primary;
				<ScanNeighbours>d__.expectedSpacing = <>3__expectedSpacing;
				return <ScanNeighbours>d__;
			}

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

		internal static readonly int CollisionMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "item" });

		private static readonly Collider[] _primary = (Collider[])(object)new Collider[50];

		private static readonly Collider[] _secondary = (Collider[])(object)new Collider[50];

		private const int MaxRawColliders = 50;

		[IteratorStateMachine(typeof(<Scan>d__4))]
		internal static IEnumerable<Transform> Scan(Vector3 origin, float spacingRadius)
		{
			//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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Scan>d__4(-2)
			{
				<>3__origin = origin,
				<>3__spacingRadius = spacingRadius
			};
		}

		[IteratorStateMachine(typeof(<ScanNeighbours>d__5))]
		internal static IEnumerable<Transform> ScanNeighbours(Transform primary, float expectedSpacing)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ScanNeighbours>d__5(-2)
			{
				<>3__primary = primary,
				<>3__expectedSpacing = expectedSpacing
			};
		}
	}
	internal sealed class GhostCache : MonoBehaviour
	{
		internal Piece piece;

		internal Plant plant;

		internal int lastUpdatedVersion = -1;

		public void Init()
		{
			piece = ((Component)this).GetComponent<Piece>();
			plant = ((Component)this).GetComponent<Plant>();
		}
	}
	internal static class GhostStatus
	{
		private static readonly Dictionary<Biome, Status> TemperatureBiomeStatus = new Dictionary<Biome, Status>
		{
			{
				(Biome)32,
				Status.TooHot
			},
			{
				(Biome)64,
				Status.TooCold
			},
			{
				(Biome)4,
				Status.TooCold
			}
		};

		internal static Status EvaluateStatus(GameObject ghost, Status baseStatus = Status.Healthy)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			Piece piece;
			Plant plant;
			if ((Object)(object)ghost == (Object)(object)PlacementState.PlacementGhost)
			{
				piece = PlacementState.Piece;
				plant = PlacementState.Plant;
			}
			else
			{
				GhostCache component = ghost.GetComponent<GhostCache>();
				piece = component.piece;
				plant = component.plant;
			}
			Vector3 position = ghost.transform.position;
			Heightmap val = Heightmap.FindHeightmap(position);
			if ((Object)(object)val == (Object)null)
			{
				return Status.Invalid;
			}
			if ((plant?.m_needCultivatedGround ?? piece.m_cultivatedGroundOnly) && !val.IsCultivated(position))
			{
				return Status.NotCultivated;
			}
			Biome val2 = plant?.m_biome ?? piece.m_onlyInBiome;
			Biome biome = val.GetBiome(position, 0.02f, false);
			if ((int)val2 != 0 && (biome & val2) == 0)
			{
				return Status.WrongBiome;
			}
			if (Object.op_Implicit((Object)(object)plant))
			{
				if (!ModUtils.HasGrowSpace(plant, position))
				{
					return Status.NoSpace;
				}
				if (plant.HaveRoof())
				{
					return Status.NoSun;
				}
				if (plant.m_attachDistance > 0f && !plant.GetClosestAttachPosRot(ref plant.m_attachPos, ref plant.m_attachRot, ref plant.m_attachNormal))
				{
					return Status.NoAttachPiece;
				}
				if (TemperatureBiomeStatus.TryGetValue(biome, out var value) && value switch
				{
					Status.TooHot => plant.m_tolerateHeat ? 1 : 0, 
					Status.TooCold => plant.m_tolerateCold ? 1 : 0, 
					_ => 1, 
				} == 0 && !ShieldGenerator.IsInsideShield(position))
				{
					return value;
				}
			}
			else if (ModContext.config.PreventOverlappingPlacements && ModUtils.PositionHasCollisions(position))
			{
				return Status.NoSpace;
			}
			return baseStatus;
		}
	}
	internal static class PlacementState
	{
		internal static Vector3 BasePosition;

		internal static Vector3 RowDirection;

		internal static Vector3 ColumnDirection;

		internal static Quaternion BaseRotation;

		internal static Quaternion FixedRotation;

		internal static bool AltPlacement;

		internal static GameObject PlacementGhost;

		internal static Piece Piece;

		internal static Plant Plant;

		internal static string LastSelectedPlantName = "";

		internal static Vector3 SnapDirection;

		internal static Vector3 SavedRowDirection;

		internal static Vector3 SavedColumnDirection;

		internal static Quaternion? SavedBaseRotation;

		internal static void SetReferences(GameObject rootGhost)
		{
			PlacementGhost = rootGhost;
			Plant = rootGhost.GetComponent<Plant>();
			Piece = rootGhost.GetComponent<Piece>();
			LastSelectedPlantName = null;
			if (!Object.op_Implicit((Object)(object)Plant))
			{
				return;
			}
			foreach (KeyValuePair<string, ReplantDB> item in ReplantDB.Registry)
			{
				if (item.Value.PlantName == ((Object)rootGhost).name)
				{
					LastSelectedPlantName = item.Key;
					break;
				}
			}
		}

		internal static void Update(Vector3 playerPosition)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			UpdateAltPlacementMode();
			UpdateBaseTransform();
			UpdateFixedRotation();
			UpdateGridDirectionsAndSnapping(playerPosition);
		}

		private static void UpdateAltPlacementMode()
		{
			if (ModContext.config.ForceAltPlacement)
			{
				AltPlacement = true;
				return;
			}
			if (ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive())
			{
				AltPlacement = Player.m_localPlayer.m_altPlace;
				return;
			}
			bool button = ZInput.GetButton("AltPlace");
			bool flag = ZInput.GetButton("JoyAltPlace") && !ZInput.GetButton("JoyRotate");
			AltPlacement = button || flag;
		}

		private static void UpdateBaseTransform()
		{
			//IL_000a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			BasePosition = PlacementGhost.transform.position;
			BaseRotation = PlacementGhost.transform.rotation;
		}

		private static void UpdateFixedRotation()
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			FixedRotation = BaseRotation;
			Vector3 eulerAngles = ((Quaternion)(ref FixedRotation)).eulerAngles;
			eulerAngles.y = Mathf.Round(eulerAngles.y / 90f) * 90f;
			((Quaternion)(ref FixedRotation)).eulerAngles = eulerAngles;
		}

		private static void UpdateGridDirectionsAndSnapping(Vector3 playerPosition)
		{
			//IL_0002: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			float pieceSpacing = ModUtils.GetPieceSpacing(PlacementGhost);
			ResetGridDirections();
			if (ModContext.config.SnapActive)
			{
				if (SnapSystem.FindSnapPoints(pieceSpacing))
				{
					return;
				}
				ResetGridDirections();
			}
			RowDirection = BaseRotation * RowDirection * pieceSpacing;
			ColumnDirection = BaseRotation * ColumnDirection * pieceSpacing;
			void ResetGridDirections()
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: 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_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				RowDirection = (ModContext.config.GloballyAlignGridDirections ? Vector3.forward : Utils.DirectionXZ(BasePosition - playerPosition));
				ColumnDirection = Vector3.Cross(Vector3.up, RowDirection);
			}
		}
	}
	internal static class GhostGrid
	{
		internal static readonly List<GameObject> ExtraGhosts = new List<GameObject>();

		internal static readonly List<GameObject> ValidExtraGhosts = new List<GameObject>();

		internal static readonly List<Status> GhostPlacementStatus = new List<Status>();

		internal static GameObject DirectionRenderer;

		internal static List<LineRenderer> LineRenderers = new List<LineRenderer>();

		private static readonly int ghostLayer = LayerMask.NameToLayer("ghost");

		private static int _gridVersion;

		private static int _ghostUpdateIndex;

		private static Vector3 _lastBasePosition;

		private static Quaternion _lastBaseRotation;

		private static Quaternion _lastEffectiveRotation;

		private static int _lastRows;

		private static int _lastColumns;

		private static string _lastPieceName;

		private static bool _preservePool;

		private static int MaxActiveGhosts => Mathf.Min(ModContext.config.Rows * ModContext.config.Columns - 1, ModContext.config.MaxConcurrentPlacements - 1);

		private static int TotalCells => 1 + MaxActiveGhosts;

		private static int ActualRows => (TotalCells + ModContext.config.Columns - 1) / ModContext.config.Columns;

		private static int ActualColumns => Mathf.Min(ModContext.config.Columns, TotalCells);

		internal static void ResizeGrid()
		{
			_preservePool = true;
			GhostPlacementStatus.Clear();
		}

		internal static void BuildGrid(GameObject rootGhost)
		{
			GrowPoolIfNeeded(rootGhost);
			GhostPlacementStatus.Clear();
			InitializeGhosts(rootGhost);
			DeactivateExcessGhosts();
		}

		internal static void PrepareGhostPool(GameObject currentPlacementGhost)
		{
			GameObject directionRenderer = DirectionRenderer;
			if (directionRenderer != null)
			{
				directionRenderer.SetActive(false);
			}
			DetectPieceChange(currentPlacementGhost);
			if (!ShouldPreservePool())
			{
				DestroyExtraGhosts();
			}
		}

		private static void GrowPoolIfNeeded(GameObject rootGhost)
		{
			int i = ExtraGhosts.Count;
			string name = ((Object)rootGhost).name;
			for (; i < MaxActiveGhosts && i < ModContext.config.MaxConcurrentPlacements - 1; i++)
			{
				ZNetView.m_forceDisableInit = true;
				GameObject val = Object.Instantiate<GameObject>(rootGhost);
				val.AddComponent<GhostCache>().Init();
				ZNetView.m_forceDisableInit = false;
				((Object)val).name = name;
				Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>();
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					((Component)componentsInChildren[j]).gameObject.layer = ghostLayer;
				}
				ExtraGhosts.Add(val);
			}
		}

		private static void InitializeGhosts(GameObject rootGhost)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = rootGhost.transform;
			int num = 0;
			for (int i = 0; i < ModContext.config.Rows; i++)
			{
				for (int j = 0; j < ModContext.config.Columns; j++)
				{
					if (i == 0 && j == 0)
					{
						PlacementState.SetReferences(rootGhost);
						GhostPlacementStatus.Add(Status.Healthy);
						continue;
					}
					if (num >= MaxActiveGhosts)
					{
						return;
					}
					GameObject obj = ExtraGhosts[num++];
					obj.SetActive(true);
					Transform transform2 = obj.transform;
					transform2.position = transform.position;
					transform2.localScale = transform.localScale;
					GhostPlacementStatus.Add(Status.Healthy);
				}
			}
		}

		private static void DeactivateExcessGhosts()
		{
			for (int i = MaxActiveGhosts; i < ExtraGhosts.Count; i++)
			{
				ExtraGhosts[i].SetActive(false);
			}
		}

		private static void DetectPieceChange(GameObject currentPlacementGhost)
		{
			if (Object.op_Implicit((Object)(object)currentPlacementGhost))
			{
				string name = ((Object)currentPlacementGhost).name;
				if (string.IsNullOrEmpty(_lastPieceName))
				{
					_lastPieceName = name;
				}
				else if (name == _lastPieceName)
				{
					_preservePool = true;
				}
				else
				{
					_lastPieceName = name;
				}
			}
		}

		private static bool ShouldPreservePool()
		{
			if (!_preservePool || !ModContext.config.ModActive)
			{
				return false;
			}
			_preservePool = false;
			return true;
		}

		private static void DestroyExtraGhosts()
		{
			foreach (GameObject extraGhost in ExtraGhosts)
			{
				Object.Destroy((Object)(object)extraGhost);
			}
			ExtraGhosts.Clear();
		}

		internal static void Update(Player player)
		{
			UpdateVisibility();
			if (ModContext.config.ShowGridDirections)
			{
				ShowGridDirections();
			}
			if (!Object.op_Implicit((Object)(object)PlacementState.PlacementGhost))
			{
				return;
			}
			Piece piece = PlacementState.Piece;
			int amount = piece.m_resources[0].m_amount;
			UpdateGridVersion();
			UpdateGhost(player, piece, 0, 0, 0);
			int num = 1 + MaxActiveGhosts;
			int num2 = Mathf.Min(ModContext.config.GhostUpdateBatchSize, num);
			for (int i = 0; i < num2; i++)
			{
				int num3 = _ghostUpdateIndex % num;
				_ghostUpdateIndex++;
				int num4 = num3 / ModContext.config.Columns;
				int column = num3 % ModContext.config.Columns;
				if (num4 < ModContext.config.Rows)
				{
					UpdatePieceCost(piece, num3, amount);
					UpdateGhost(player, piece, num4, column, num3);
				}
			}
			UpdatePieceCost(piece, 0, amount);
		}

		private static void UpdatePieceCost(Piece piece, int ghostIndex, int baseCost)
		{
			piece.m_resources[0].m_amount = baseCost * (ghostIndex + 1);
		}

		private static void UpdateVisibility()
		{
			bool flag = Object.op_Implicit((Object)(object)PlacementState.PlacementGhost) && PlacementState.PlacementGhost.activeSelf;
			for (int i = 0; i < ExtraGhosts.Count; i++)
			{
				bool flag2 = flag && i < MaxActiveGhosts;
				if (ExtraGhosts[i].activeSelf != flag2)
				{
					ExtraGhosts[i].SetActive(flag2);
				}
			}
		}

		private static void ShowGridDirections()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			DirectionRenderer.SetActive(PlacementState.PlacementGhost.activeSelf);
			Vector3 val = PlacementState.BasePosition + Vector3.up * 0.5f;
			LineRenderers[0].SetPositions((Vector3[])(object)new Vector3[2]
			{
				val,
				val + PlacementState.RowDirection * (float)(ActualRows - 1)
			});
			LineRenderers[1].SetPositions((Vector3[])(object)new Vector3[2]
			{
				val,
				val + PlacementState.ColumnDirection * (float)(ActualColumns - 1)
			});
			((Component)LineRenderers[2]).gameObject.SetActive(ModContext.config.ShowSnapDirection);
			LineRenderers[2].SetPositions((Vector3[])(object)new Vector3[2]
			{
				val,
				val + PlacementState.SnapDirection * ((Vector3)(ref PlacementState.RowDirection)).magnitude
			});
		}

		private static void UpdateGridVersion()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			Vector3 val = PlacementState.BasePosition - _lastBasePosition;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				_lastBasePosition = PlacementState.BasePosition;
				flag = true;
			}
			if (Quaternion.Angle(PlacementState.BaseRotation, _lastBaseRotation) > 1f)
			{
				_lastBaseRotation = PlacementState.BaseRotation;
				flag = true;
			}
			Quaternion lastEffectiveRotation = (Quaternion)(((??)PlacementState.SavedBaseRotation) ?? PlacementState.BaseRotation);
			if (Quaternion.Angle((Quaternion)(((??)PlacementState.SavedBaseRotation) ?? PlacementState.BaseRotation), _lastEffectiveRotation) > 0.1f)
			{
				_lastEffectiveRotation = lastEffectiveRotation;
				flag = true;
			}
			if (ModContext.config.Rows != _lastRows || ModContext.config.Columns != _lastColumns)
			{
				_lastRows = ModContext.config.Rows;
				_lastColumns = ModContext.config.Columns;
				flag = true;
			}
			if (flag)
			{
				_gridVersion++;
			}
		}

		private static void UpdateGhost(Player player, Piece piece, int row, int column, int index)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			GameObject ghostObject = GetGhostObject(index);
			GhostCache ghostCache = GetGhostCache(ghostObject);
			bool flag = ghostCache != null;
			if (!flag || ghostCache.lastUpdatedVersion != _gridVersion)
			{
				UpdateGhostTransform(ghostObject, GetGhostPosition(row, column, index));
				UpdateGhostStatus(player, piece, ghostObject, index);
				if (flag)
				{
					ghostCache.lastUpdatedVersion = _gridVersion;
				}
			}
		}

		private static GameObject GetGhostObject(int index)
		{
			if (index != 0)
			{
				return ExtraGhosts[index - 1];
			}
			return PlacementState.PlacementGhost;
		}

		private static GhostCache GetGhostCache(GameObject ghost)
		{
			if (!((Object)(object)ghost == (Object)(object)PlacementState.PlacementGhost))
			{
				return ghost.GetComponent<GhostCache>();
			}
			return null;
		}

		private static Vector3 GetGhostPosition(int row, int column, int index)
		{
			//IL_002c: 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_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)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((index == 0) ? PlacementState.BasePosition : (PlacementState.BasePosition + PlacementState.RowDirection * (float)row + PlacementState.ColumnDirection * (float)column));
			float y = default(float);
			Heightmap.GetHeight(val, ref y);
			val.y = y;
			return val;
		}

		private static void UpdateGhostTransform(GameObject ghost, Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			ghost.transform.position = position;
			ghost.transform.rotation = PlacementState.BaseRotation;
		}

		private static void UpdateGhostStatus(Player player, Piece piece, GameObject ghost, int index)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			Status baseStatus = ((!player.m_noPlacementCost && !player.HaveRequirements(piece, (RequirementMode)0)) ? Status.LackResources : Status.Healthy);
			Status status = GhostStatus.EvaluateStatus(ghost, baseStatus);
			ghost.GetComponent<Piece>().SetInvalidPlacementHeightlight(status != Status.Healthy);
			GhostPlacementStatus[index] = status;
			if (index == 0 && status == Status.Healthy)
			{
				if (ModContext.config.HighlightRootPlacementGhost && GhostPlacementStatus.Count > 1)
				{
					MaterialMan.instance.SetValue<Color>(ghost, ShaderProps._Color, ModContext.config.RootGhostHighlightColor);
					MaterialMan.instance.SetValue<Color>(ghost, ShaderProps._EmissionColor, ModContext.config.RootGhostHighlightColor * 0.7f);
				}
				player.m_placementStatus = (PlacementStatus)0;
			}
		}
	}
	internal class SnapPoint
	{
		public Vector3 pos;

		public Vector3 rowDir;

		public Vector3 colDir;

		public Vector3 origin;

		public bool isCardinal;

		internal SnapPoint()
		{
		}

		internal SnapPoint(Vector3 pos, Vector3 row, Vector3 col, Vector3 origin)
		{
			//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)
			//IL_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			this.pos = pos;
			rowDir = row;
			colDir = col;
			this.origin = origin;
		}
	}
	internal static class SnapPointGenerator
	{
		private const int MaxRotations = 16;

		private static readonly Vector3[] _positionBuffer;

		private static readonly SnapPoint[] _snapBuffer;

		static SnapPointGenerator()
		{
			_positionBuffer = (Vector3[])(object)new Vector3[16];
			_snapBuffer = new SnapPoint[16];
			for (int i = 0; i < 16; i++)
			{
				_snapBuffer[i] = new SnapPoint();
			}
		}

		internal static bool Generate(List<SnapPoint> snapPoints, Vector3 snapFromPos, bool gridDetected)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			int candidateCount = BuildCandidatePositions(snapFromPos, gridDetected);
			return ValidateCandidates(snapPoints, candidateCount, snapFromPos);
		}

		private static int BuildCandidatePositions(Vector3 snapFromPos, bool gridDetected)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			Vector3 rowDirection = PlacementState.RowDirection;
			Vector3 columnDirection = PlacementState.ColumnDirection;
			int result = 0;
			if (gridDetected)
			{
				_positionBuffer[result++] = snapFromPos + rowDirection;
				_positionBuffer[result++] = snapFromPos - rowDirection;
				_positionBuffer[result++] = snapFromPos + columnDirection;
				_positionBuffer[result++] = snapFromPos - columnDirection;
				_positionBuffer[result++] = snapFromPos + rowDirection - columnDirection;
				_positionBuffer[result++] = snapFromPos + rowDirection + columnDirection;
				_positionBuffer[result++] = snapFromPos - rowDirection - columnDirection;
				_positionBuffer[result++] = snapFromPos - rowDirection + columnDirection;
			}
			else if (PlacementState.AltPlacement)
			{
				_positionBuffer[result++] = snapFromPos + rowDirection;
				_positionBuffer[result++] = snapFromPos - rowDirection;
				_positionBuffer[result++] = snapFromPos + columnDirection;
				_positionBuffer[result++] = snapFromPos - columnDirection;
			}
			else
			{
				float num = 22.5f * ((float)Math.PI / 180f);
				Vector3 val = default(Vector3);
				for (int i = 0; i < 16; i++)
				{
					float num2 = num * (float)i;
					float num3 = Mathf.Sin(num2);
					float num4 = Mathf.Cos(num2);
					((Vector3)(ref val))..ctor(rowDirection.x * num4 + rowDirection.z * num3, rowDirection.y, rowDirection.z * num4 - rowDirection.x * num3);
					_positionBuffer[result++] = snapFromPos + val;
				}
			}
			return result;
		}

		private static bool ValidateCandidates(List<SnapPoint> snapPoints, int candidateCount, Vector3 snapFromPos)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			Vector3 rowDirection = PlacementState.RowDirection;
			Vector3 columnDirection = PlacementState.ColumnDirection;
			int num = 0;
			bool flag = false;
			for (int i = 0; i < candidateCount; i++)
			{
				Vector3 val = _positionBuffer[i];
				if (!ModUtils.PositionHasCollisions(val) && (!((Object)(object)PlacementState.Plant != (Object)null) || ModUtils.HasGrowSpace(PlacementState.Plant, val)))
				{
					Vector3 val2 = val - snapFromPos;
					float magnitude = ((Vector3)(ref rowDirection)).magnitude;
					float num2 = Mathf.Abs(Vector3.Dot(val2, ((Vector3)(ref rowDirection)).normalized));
					float num3 = Mathf.Abs(Vector3.Dot(val2, ((Vector3)(ref columnDirection)).normalized));
					float num4 = magnitude * 0.25f;
					bool flag2 = (num2 < num4 && num3 >= num4) || (num3 < num4 && num2 >= num4);
					InitSnapPoint(num++, val, rowDirection, columnDirection, snapFromPos, flag2);
					if (flag2)
					{
						flag = true;
					}
				}
			}
			if (num == 0)
			{
				return false;
			}
			for (int j = 0; j < num; j++)
			{
				SnapPoint snapPoint = _snapBuffer[j];
				if (!ModContext.config.PreferCardinalSnapping || !flag || snapPoint.isCardinal)
				{
					snapPoints.Add(snapPoint);
				}
			}
			return snapPoints.Count > 0;
		}

		private static SnapPoint InitSnapPoint(int index, Vector3 pos, Vector3 row, Vector3 col, Vector3 origin, bool isCardinal)
		{
			//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_0017: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			SnapPoint obj = _snapBuffer[index];
			obj.pos = pos;
			obj.rowDir = row;
			obj.colDir = col;
			obj.origin = origin;
			obj.isCardinal = isCardinal;
			return obj;
		}
	}
	internal static class SnapSystem
	{
		[CompilerGenerated]
		private sealed class <ValidPrimaryCollisions>d__11 : IEnumerable<Transform>, IEnumerable, IEnumerator<Transform>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Transform <>2__current;

			private int <>l__initialThreadId;

			private Vector3 origin;

			public Vector3 <>3__origin;

			private float spacingRadius;

			public float <>3__spacingRadius;

			private int <count>5__2;

			private IEnumerator<Transform> <>7__wrap2;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				bool result;
				try
				{
					switch (<>1__state)
					{
					default:
						result = false;
						goto end_IL_0000;
					case 0:
						<>1__state = -1;
						<count>5__2 = 0;
						<>7__wrap2 = CollisionScanner.Scan(origin, spacingRadius).GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (true)
					{
						if (<>7__wrap2.MoveNext())
						{
							Transform current = <>7__wrap2.Current;
							if (ModUtils.IsPlantOrPickable(((Component)current).gameObject))
							{
								if (++<count>5__2 > 8)
								{
									result = false;
									<>m__Finally1();
								}
								else
								{
									<>2__current = current;
									<>1__state = 1;
									result = true;
								}
								break;
							}
							continue;
						}
						<>m__Finally1();
						<>7__wrap2 = null;
						result = false;
						break;
					}
					end_IL_0000:;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

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

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

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

			[DebuggerHidden]
			IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				<ValidPrimaryCollisions>d__11 <ValidPrimaryCollisions>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ValidPrimaryCollisions>d__ = this;
				}
				else
				{
					<ValidPrimaryCollisions>d__ = new <ValidPrimaryCollisions>d__11(0);
				}
				<ValidPrimaryCollisions>d__.origin = <>3__origin;
				<ValidPrimaryCollisions>d__.spacingRadius = <>3__spacingRadius;
				return <ValidPrimaryCollisions>d__;
			}

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

		private const int MaxValidCollisions = 8;

		private static SnapPoint _lastSnap;

		private static bool _hasLastSnap;

		private static Quaternion _lastGhostRotation;

		internal static bool FindSnapPoints(float pieceSpacing)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (TryGridSnaps(pieceSpacing, out var snapPoints))
			{
				ApplyGridSnap(snapPoints);
				return true;
			}
			if (TryFreeSnaps(pieceSpacing, out var snapPoints2))
			{
				ApplyFreeSnap(snapPoints2);
				return true;
			}
			PlacementState.SnapDirection = Vector3.zero;
			return false;
		}

		private static void ApplyGridSnap(List<SnapPoint> availableSnapPoints)
		{
			ApplyRotationHysteresis();
			(SnapPoint snap, float distance) tuple = FindNearestManhattan(availableSnapPoints);
			SnapPoint item = tuple.snap;
			float item2 = tuple.distance;
			item = ApplyPositionHysteresis(item, item2);
			CommitSnap(item);
			ApplyGridOrientation(item);
		}

		private static void ApplyFreeSnap(List<SnapPoint> availableSnapPoints)
		{
			SnapPoint snap = FindNearestEuclidean(availableSnapPoints);
			CommitSnap(snap);
			ApplyFreeOrientation(snap);
		}

		private static bool TryGridSnaps(float pieceSpacing, out List<SnapPoint> snapPoints)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			snapPoints = new List<SnapPoint>();
			float num = Mathf.Max(pieceSpacing * 0.01f, 0.005f);
			float spacingRadius = pieceSpacing + num;
			List<(Transform, float, List<Transform>)> list = new List<(Transform, float, List<Transform>)>();
			foreach (Transform item3 in ValidPrimaryCollisions(PlacementState.BasePosition, spacingRadius))
			{
				Vector3 val = item3.position - PlacementState.BasePosition;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				float pieceSpacing2 = ModUtils.GetPieceSpacing(((Component)item3).gameObject);
				List<Transform> list2 = new List<Transform>(8);
				foreach (Transform item4 in CollisionScanner.ScanNeighbours(item3, pieceSpacing2))
				{
					if (ModUtils.IsPlantOrPickable(((Component)item4).gameObject))
					{
						list2.Add(item4);
					}
				}
				list.Add((item3, sqrMagnitude, list2));
			}
			list.Sort(delegate((Transform transform, float distance, List<Transform> neighbours) a, (Transform transform, float distance, List<Transform> neighbours) b)
			{
				int num3 = a.distance.CompareTo(b.distance);
				return (num3 != 0) ? num3 : a.neighbours.Count.CompareTo(b.neighbours.Count);
			});
			foreach (var item5 in list)
			{
				Transform item = item5.Item1;
				List<Transform> item2 = item5.Item3;
				Transform val2 = item;
				int num2 = 0;
				foreach (Transform item6 in item2)
				{
					if (++num2 > 8)
					{
						break;
					}
					if (TryDetectGrid(val2.position, item6.position, pieceSpacing) && SnapPointGenerator.Generate(snapPoints, val2.position, gridDetected: true))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryDetectGrid(Vector3 primary, Vector3 neighbour, float pieceSpacing)
		{
			//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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Utils.DirectionXZ(neighbour - primary);
			if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
			{
				return false;
			}
			val = PlacementState.FixedRotation * val;
			PlacementState.RowDirection = val * pieceSpacing;
			Vector3 val2 = Vector3.Cross(Vector3.up, val);
			PlacementState.ColumnDirection = ((Vector3)(ref val2)).normalized * pieceSpacing;
			return true;
		}

		private static bool TryFreeSnaps(float pieceSpacing, out List<SnapPoint> snapPoints)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			snapPoints = new List<SnapPoint>();
			float num = Mathf.Max(pieceSpacing * 0.01f, 0.005f);
			float spacingRadius = pieceSpacing + num;
			foreach (Transform item in ValidPrimaryCollisions(PlacementState.BasePosition, spacingRadius))
			{
				ComputeFreeDirections(item.position, pieceSpacing);
				if (SnapPointGenerator.Generate(snapPoints, item.position, gridDetected: false))
				{
					return true;
				}
			}
			return false;
		}

		private static void ComputeFreeDirections(Vector3 target, float pieceSpacing)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0011: 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_0017: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Utils.DirectionXZ(PlacementState.BasePosition - target);
			PlacementState.RowDirection = PlacementState.FixedRotation * val * pieceSpacing;
			if (!PlacementState.AltPlacement)
			{
				float num = Mathf.Round(Vector3.SignedAngle(Vector3.forward, val, Vector3.up) / 22.5f) * 22.5f;
				PlacementState.RowDirection = PlacementState.FixedRotation * Quaternion.Euler(0f, num, 0f) * Vector3.forward * pieceSpacing;
			}
			PlacementState.ColumnDirection = Vector3.Cross(Vector3.up, PlacementState.RowDirection);
		}

		[IteratorStateMachine(typeof(<ValidPrimaryCollisions>d__11))]
		private static IEnumerable<Transform> ValidPrimaryCollisions(Vector3 origin, float spacingRadius)
		{
			//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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ValidPrimaryCollisions>d__11(-2)
			{
				<>3__origin = origin,
				<>3__spacingRadius = spacingRadius
			};
		}

		private static (SnapPoint snap, float distance) FindNearestManhattan(List<SnapPoint> snapPoints)
		{
			//IL_0009: 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_0014: Un