Decompiled source of RestlessPlant v0.1.5

RestlessPlant.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RestlessQoL.Api;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RestlessPlant")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.5.0")]
[assembly: AssemblyInformationalVersion("0.1.5+2c0c2f5c300f7632949fdc966ce798be447161fb")]
[assembly: AssemblyProduct("RestlessPlant")]
[assembly: AssemblyTitle("RestlessPlant")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RestlessPlant
{
	internal enum CropGate
	{
		Forage,
		Sapling,
		Flora
	}
	internal readonly struct CropRow
	{
		public string Source { get; }

		public string Item { get; }

		public string Name { get; }

		public string Description { get; }

		public CropGate Gate { get; }

		public bool Till { get; }

		public bool Attach { get; }

		public string Prefab => "Restless_" + Source;

		public CropRow(string source, string item, string name, string description, CropGate gate = CropGate.Forage, bool till = true, bool attach = false)
		{
			Source = source;
			Item = item;
			Name = name;
			Description = description;
			Gate = gate;
			Till = till;
			Attach = attach;
		}
	}
	internal static class CropBook
	{
		public static readonly IReadOnlyList<CropRow> Rows = new CropRow[31]
		{
			new CropRow("RaspberryBush", "Raspberry", "Raspberry bush", "Plant a raspberry bush."),
			new CropRow("BlueberryBush", "Blueberries", "Blueberry bush", "Plant a blueberry bush."),
			new CropRow("CloudberryBush", "Cloudberry", "Cloudberry bush", "Plant a cloudberry bush."),
			new CropRow("LingonberryBush", "Lingonberry", "Lingonberry bush", "Plant a lingonberry bush."),
			new CropRow("Pickable_Mushroom", "Mushroom", "Mushroom", "Plant mushrooms."),
			new CropRow("Pickable_Mushroom_yellow", "MushroomYellow", "Yellow mushroom", "Plant yellow mushrooms."),
			new CropRow("Pickable_Mushroom_blue", "MushroomBlue", "Blue mushroom", "Plant blue mushrooms."),
			new CropRow("Pickable_Thistle", "Thistle", "Thistle", "Plant thistle."),
			new CropRow("Pickable_Dandelion", "Dandelion", "Dandelion", "Plant dandelion."),
			new CropRow("Pickable_Mushroom_Magecap", "MushroomMagecap", "Magecap", "Plant magecap."),
			new CropRow("Pickable_Mushroom_JotunPuffs", "MushroomJotunPuffs", "Jotun puffs", "Plant jotun puffs."),
			new CropRow("Pickable_SmokePuff", "MushroomSmokePuff", "Smoke puff", "Plant smoke puff."),
			new CropRow("Pickable_Fiddlehead", "Fiddleheadfern", "Fiddlehead", "Plant fiddlehead."),
			new CropRow("Ancient_Sapling", "ElderBark", "Ancient sapling", "Plant an ancient sapling.", CropGate.Sapling, till: false),
			new CropRow("Ygga_Sapling", "YggdrasilWood", "Ygga sapling", "Plant a ygga sapling.", CropGate.Sapling, till: false),
			new CropRow("Autumn_Birch_Sapling", "FineWood", "Autumn birch sapling", "Plant an autumn birch sapling.", CropGate.Sapling, till: false),
			new CropRow("Ashwood_Sapling", "Blackwood", "Ashwood sapling", "Plant an ashwood sapling.", CropGate.Sapling, till: false),
			new CropRow("Beech_small1", "Wood", "Small beech", "Plant a small beech.", CropGate.Flora, till: false),
			new CropRow("FirTree_small", "Wood", "Small fir", "Plant a small fir.", CropGate.Flora, till: false),
			new CropRow("FirTree_small_dead", "Wood", "Small dead fir", "Plant a small dead fir.", CropGate.Flora, till: false),
			new CropRow("Bush01", "Wood", "Small bush", "Plant a small bush.", CropGate.Flora, till: false),
			new CropRow("Bush01_heath", "Wood", "Heath bush", "Plant a heath bush.", CropGate.Flora, till: false),
			new CropRow("Bush02_en", "Wood", "Fruitless bush", "Plant a fruitless bush.", CropGate.Flora, till: false),
			new CropRow("shrub_2", "Wood", "Small shrub", "Plant a small shrub.", CropGate.Flora, till: false),
			new CropRow("shrub_2_heath", "Wood", "Heath shrub", "Plant a heath shrub.", CropGate.Flora, till: false),
			new CropRow("YggaShoot_small1", "YggdrasilWood", "Ygga shoot", "Plant a small ygga shoot.", CropGate.Flora, till: false),
			new CropRow("vines", "Wood", "Vines", "Plant wall vines.", CropGate.Flora, till: false, attach: true),
			new CropRow("FernAshlands", "Wood", "Ashlands fern", "Plant an Ashlands fern.", CropGate.Flora, till: false),
			new CropRow("Pickable_Branch", "Wood", "Branch", "Place a pickable branch.", CropGate.Flora, till: false),
			new CropRow("Pickable_Stone", "Stone", "Stone", "Place a pickable stone.", CropGate.Flora, till: false),
			new CropRow("Pickable_Flint", "Flint", "Flint", "Place a pickable flint.", CropGate.Flora, till: false)
		};

		public static bool Allowed(CropRow row)
		{
			return row.Gate switch
			{
				CropGate.Sapling => PlantConfig.ExtraSaplings.Value, 
				CropGate.Flora => PlantConfig.ExtraFlora.Value, 
				_ => PlantConfig.ExtraCrops.Value, 
			};
		}

		public static bool IsOurs(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return false;
			}
			return prefabName.StartsWith("Restless_");
		}
	}
	internal static class CropPieces
	{
		private const float DefaultRespawnMinutes = 240f;

		private static bool _added;

		public static void Load()
		{
			PrefabManager.OnVanillaPrefabsAvailable += Add;
		}

		private static void Add()
		{
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Expected O, but got Unknown
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= Add;
			if (_added)
			{
				return;
			}
			_added = true;
			if (!PlantConfig.On)
			{
				return;
			}
			Piece val = TemplatePiece();
			int num = 0;
			foreach (CropRow row in CropBook.Rows)
			{
				if (!CropBook.Allowed(row))
				{
					continue;
				}
				GameObject prefab = PrefabManager.Instance.GetPrefab(row.Source);
				if ((Object)(object)prefab == (Object)null)
				{
					Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no vanilla prefab)."));
					continue;
				}
				string text = ItemOf(row, prefab);
				if (text == null)
				{
					Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no item " + row.Item + ")."));
					continue;
				}
				Sprite val2 = IconOf(text);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogInfo((object)("RestlessPlant skipped " + row.Source + " (no icon on " + text + ")."));
					continue;
				}
				GameObject val3 = PrefabManager.Instance.CreateClonedPrefab(row.Prefab, row.Source);
				if (!((Object)(object)val3 == (Object)null))
				{
					LODGroup[] componentsInChildren = val3.GetComponentsInChildren<LODGroup>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						Object.Destroy((Object)(object)componentsInChildren[i]);
					}
					Renderer[] componentsInChildren2 = val3.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer obj in componentsInChildren2)
					{
						((Component)obj).gameObject.SetActive(true);
						obj.enabled = true;
					}
					Piece val4 = val3.GetComponent<Piece>() ?? val3.AddComponent<Piece>();
					bool value = PlantConfig.GrowAnywhere.Value;
					val4.m_groundOnly = !row.Attach && !value;
					val4.m_groundPiece = !row.Attach;
					val4.m_allowAltGroundPlacement = value;
					val4.m_noInWater = !value;
					val4.m_cultivatedGroundOnly = row.Till && !value;
					val4.m_icon = val2;
					if ((Object)(object)val != (Object)null)
					{
						CopyPlacement(val4, val);
					}
					FlattenLod(val3);
					TunePickable(prefab, val3);
					PieceConfig val5 = new PieceConfig
					{
						Name = row.Name,
						Description = row.Description,
						PieceTable = PieceTables.Cultivator,
						CraftingStation = CraftingStations.None,
						Icon = val2
					};
					val5.AddRequirement(text, 1, true);
					PieceManager.Instance.AddPiece(new CustomPiece(val3, true, val5));
					num++;
				}
			}
			Plugin.Log.LogInfo((object)$"RestlessPlant added {num} cultivator crops.");
		}

		private static Piece? TemplatePiece()
		{
			string[] array = new string[3] { "sapling_carrot", "Plant_Carrot", "CarrotSeeds" };
			foreach (string text in array)
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(text);
				Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static void CopyPlacement(Piece dest, Piece src)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			dest.m_placeEffect = src.m_placeEffect;
			dest.m_category = src.m_category;
		}

		private static void FlattenLod(GameObject go)
		{
			LODGroup[] componentsInChildren = go.GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val in componentsInChildren)
			{
				LOD[] lODs = val.GetLODs();
				Renderer[] array = ((lODs.Length != 0) ? lODs[0].renderers : null);
				Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val2 in componentsInChildren2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						val2.enabled = array == null || Array.IndexOf(array, val2) >= 0;
					}
				}
				val.enabled = false;
				Object.DestroyImmediate((Object)(object)val);
			}
		}

		private static void TunePickable(GameObject source, GameObject clone)
		{
			Pickable componentInChildren = source.GetComponentInChildren<Pickable>(true);
			Pickable componentInChildren2 = clone.GetComponentInChildren<Pickable>(true);
			if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren2 == (Object)null))
			{
				componentInChildren2.m_respawnTimeMinutes = componentInChildren.m_respawnTimeMinutes;
				componentInChildren2.m_amount = componentInChildren.m_amount;
				if (componentInChildren2.m_respawnTimeMinutes <= 0f)
				{
					componentInChildren2.m_respawnTimeMinutes = 240f;
				}
			}
		}

		private static string? ItemOf(CropRow row, GameObject source)
		{
			if ((Object)(object)PrefabManager.Instance.GetPrefab(row.Item) != (Object)null)
			{
				return row.Item;
			}
			Pickable componentInChildren = source.GetComponentInChildren<Pickable>(true);
			if ((Object)(object)componentInChildren?.m_itemPrefab == (Object)null)
			{
				return null;
			}
			return Utils.GetPrefabName(componentInChildren.m_itemPrefab);
		}

		private static Sprite? IconOf(string item)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(item);
			ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				return val.m_itemData.GetIcon();
			}
			catch
			{
				Sprite[] array = val.m_itemData?.m_shared?.m_icons;
				return (array != null && array.Length > 0) ? array[0] : null;
			}
		}
	}
	internal static class PlantConfig
	{
		private static readonly ConfigurationManagerAttributes Admin = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};

		private static readonly ConfigurationManagerAttributes Hidden = new ConfigurationManagerAttributes
		{
			Browsable = false
		};

		public static ConfigEntry<bool> Enabled = null;

		public static ConfigEntry<bool> ExtraCrops = null;

		public static ConfigEntry<bool> ExtraSaplings = null;

		public static ConfigEntry<bool> ExtraFlora = null;

		public static ConfigEntry<bool> GrowAnywhere = null;

		public static ConfigEntry<bool> Grid = null;

		public static ConfigEntry<int> GridColumns = null;

		public static ConfigEntry<int> GridRows = null;

		public static ConfigEntry<float> Spacing = null;

		public static ConfigEntry<bool> SnapToField = null;

		public static ConfigEntry<float> SnapRange = null;

		public static ConfigEntry<bool> BulkHarvest = null;

		public static ConfigEntry<bool> BulkBeehives = null;

		public static ConfigEntry<float> HarvestRange = null;

		public static ConfigEntry<bool> Replant = null;

		public static ConfigEntry<bool> RegrowHint = null;

		public static ConfigEntry<KeyboardShortcut> ColsUp = null;

		public static ConfigEntry<KeyboardShortcut> ColsDown = null;

		public static ConfigEntry<KeyboardShortcut> RowsUp = null;

		public static ConfigEntry<KeyboardShortcut> RowsDown = null;

		public static ConfigEntry<KeyboardShortcut> SnapToggle = null;

		public static bool On => Enabled.Value;

		public static void Bind(ConfigFile config)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Expected O, but got Unknown
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			Enabled = config.Bind<bool>("Plant", "Enabled", true, new ConfigDescription("Cultivator extras, grid planting, and bulk harvest. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			ExtraCrops = config.Bind<bool>("Plant", "BerryBushesAndForage", true, new ConfigDescription("Add berry bushes, mushrooms, thistle, and later-biome forage to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			ExtraSaplings = config.Bind<bool>("Plant", "ExtraSaplings", true, new ConfigDescription("Add ancient, ygga, autumn birch, and ashwood saplings to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			ExtraFlora = config.Bind<bool>("Plant", "DecorativeTrees", true, new ConfigDescription("Add small trees, shrubs, vines, and stick/stone/flint pickables to the cultivator. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			GrowAnywhere = config.Bind<bool>("Plant", "GrowAnywhere", false, new ConfigDescription("Skip tilled ground, biome, sun, and space checks so plants can sit on floors and wild soil. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			Grid = config.Bind<bool>("Grid", "Enabled", true, "Plant a rectangle of the selected cultivator piece. Client-local size.");
			ConfigEntry<int> val = config.Bind<int>("Plant", "GridSize", 1, new ConfigDescription("Obsolete. Copied once into GridColumns and GridRows.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { Hidden }));
			GridColumns = config.Bind<int>("Grid", "Columns", 1, new ConfigDescription("How many plants wide. [ ] resize.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), Array.Empty<object>()));
			GridRows = config.Bind<int>("Grid", "Rows", 1, new ConfigDescription("How many plants deep. - = resize.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), Array.Empty<object>()));
			if (GridColumns.Value == 1 && GridRows.Value == 1 && val.Value > 1)
			{
				GridColumns.Value = val.Value;
				GridRows.Value = val.Value;
			}
			Spacing = config.Bind<float>("Grid", "Spacing", 2f, new ConfigDescription("Metres between grid cells. Plant pieces use their grow radius when larger.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			SnapToField = config.Bind<bool>("Grid", "SnapToField", true, "Snap the cultivator ghost onto a nearby plant's spacing. Client-local.");
			SnapRange = config.Bind<float>("Grid", "SnapRange", 3f, new ConfigDescription("How far to look for a plant to snap to, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>()));
			BulkHarvest = config.Bind<bool>("Harvest", "BulkHarvest", true, new ConfigDescription("Picking a player-grown plant also picks matching neighbours. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			BulkBeehives = config.Bind<bool>("Harvest", "BulkBeehives", true, new ConfigDescription("Using a beehive also takes honey from matching neighbours. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			HarvestRange = config.Bind<float>("Harvest", "HarvestRange", 2.5f, new ConfigDescription("Bulk-harvest radius for plants and hives.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), new object[1] { Admin }));
			Replant = config.Bind<bool>("Harvest", "ReplantOnHarvest", true, new ConfigDescription("One-shot crops (carrots and the like) replant the picked piece if you can pay for it. Host-locked.", (AcceptableValueBase)null, new object[1] { Admin }));
			RegrowHint = config.Bind<bool>("Client", "RegrowHint", true, "Show time until fruit or a sapling is ready. Client-local.");
			ColsUp = config.Bind<KeyboardShortcut>("Client", "GridColumnsBigger", new KeyboardShortcut((KeyCode)93, Array.Empty<KeyCode>()), "Add a column to the planting rectangle. Client-local.");
			ColsDown = config.Bind<KeyboardShortcut>("Client", "GridColumnsSmaller", new KeyboardShortcut((KeyCode)91, Array.Empty<KeyCode>()), "Remove a column from the planting rectangle. Client-local.");
			RowsUp = config.Bind<KeyboardShortcut>("Client", "GridRowsBigger", new KeyboardShortcut((KeyCode)61, Array.Empty<KeyCode>()), "Add a row to the planting rectangle. Client-local.");
			RowsDown = config.Bind<KeyboardShortcut>("Client", "GridRowsSmaller", new KeyboardShortcut((KeyCode)45, Array.Empty<KeyCode>()), "Remove a row from the planting rectangle. Client-local.");
			SnapToggle = config.Bind<KeyboardShortcut>("Client", "SnapToggle", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Toggle snap onto an existing field. Client-local.");
		}
	}
	internal static class PlantGrid
	{
		private readonly struct Cell
		{
			public Vector3 Pos { get; }

			public bool Ok { get; }

			public Cell(Vector3 pos, bool ok)
			{
				//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)
				Pos = pos;
				Ok = ok;
			}
		}

		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPostfix]
			[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
			private static void AfterGhost(Player __instance)
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				if (_placing)
				{
					return;
				}
				if (Cultivating(__instance))
				{
					Piece selectedPiece = __instance.GetSelectedPiece();
					if ((Object)(object)selectedPiece != (Object)null)
					{
						PlantHarvest.Remember(selectedPiece);
					}
				}
				GameObject placementGhost = __instance.m_placementGhost;
				if ((Object)(object)placementGhost != (Object)null && Cultivating(__instance) && PlantConfig.On && PlantConfig.Grid.Value)
				{
					Align(__instance, placementGhost);
				}
				if (!Active(__instance) || ((int)__instance.m_placementStatus != 0 && !PlantGrow.Free))
				{
					Hide();
					return;
				}
				if ((Object)(object)placementGhost == (Object)null)
				{
					Hide();
					return;
				}
				Piece selectedPiece2 = __instance.GetSelectedPiece();
				if ((Object)(object)selectedPiece2 != (Object)(object)_lastPiece)
				{
					Clear();
					_lastPiece = selectedPiece2;
					PlantHarvest.Remember(selectedPiece2);
				}
				int num = 0;
				foreach (Cell item in Cells(__instance, placementGhost.transform))
				{
					if (num >= Ghosts.Count || (Object)(object)Ghosts[num] == (Object)null)
					{
						GameObject val = MakeGhost(placementGhost, item.Pos, placementGhost.transform.rotation);
						if (num < Ghosts.Count)
						{
							Ghosts[num] = val;
						}
						else
						{
							Ghosts.Add(val);
						}
					}
					else
					{
						Ghosts[num].transform.SetPositionAndRotation(item.Pos, placementGhost.transform.rotation);
						Ghosts[num].SetActive(true);
					}
					Paint(Ghosts[num], item.Ok);
					num++;
				}
				for (int num2 = Ghosts.Count - 1; num2 >= num; num2--)
				{
					if ((Object)(object)Ghosts[num2] != (Object)null)
					{
						Object.Destroy((Object)(object)Ghosts[num2]);
					}
					Ghosts.RemoveAt(num2);
				}
				if (_lastCols != PlantConfig.GridColumns.Value || _lastRows != PlantConfig.GridRows.Value || _lastSnap != PlantConfig.SnapToField.Value)
				{
					_lastCols = PlantConfig.GridColumns.Value;
					_lastRows = PlantConfig.GridRows.Value;
					_lastSnap = PlantConfig.SnapToField.Value;
					((Character)__instance).Message((MessageType)1, "Plant " + _lastCols + "×" + _lastRows + "  [ ] wide  - = deep" + (_lastSnap ? "  snap" : ""), 0, (Sprite)null, false);
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(Player), "TryPlacePiece")]
			private static void AfterPlace(Player __instance, Piece piece, bool __result)
			{
				//IL_0033: 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_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				if (_placing || !__result || !Active(__instance) || (Object)(object)piece == (Object)null)
				{
					return;
				}
				GameObject placementGhost = __instance.m_placementGhost;
				if ((Object)(object)placementGhost == (Object)null)
				{
					return;
				}
				Quaternion rotation = placementGhost.transform.rotation;
				_placing = true;
				try
				{
					foreach (Cell item in Cells(__instance, placementGhost.transform))
					{
						if (item.Ok)
						{
							if (!__instance.HaveRequirements(piece, (RequirementMode)0))
							{
								break;
							}
							__instance.PlacePiece(piece, item.Pos, rotation, false, false);
						}
					}
				}
				finally
				{
					_placing = false;
				}
			}
		}

		private static readonly List<GameObject> Ghosts = new List<GameObject>();

		private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock();

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private static readonly Color Bad = new Color(1f, 0.35f, 0.35f, 1f);

		private static Piece? _lastPiece;

		private static int _lastCols;

		private static int _lastRows;

		private static bool _lastSnap;

		private static bool _placing;

		public static bool Wide
		{
			get
			{
				if (PlantConfig.GridColumns.Value <= 1)
				{
					return PlantConfig.GridRows.Value > 1;
				}
				return true;
			}
		}

		public static void Tick()
		{
			//IL_0041: 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_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_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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			if (SettingsPageApi.IsMenuOpen || !PlantConfig.On || !PlantConfig.Grid.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).InPlaceMode() || !Cultivating(localPlayer))
			{
				return;
			}
			KeyboardShortcut value = PlantConfig.SnapToggle.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				PlantConfig.SnapToField.Value = !PlantConfig.SnapToField.Value;
				((Character)localPlayer).Message((MessageType)1, PlantConfig.SnapToField.Value ? "Plant snap on" : "Plant snap off", 0, (Sprite)null, false);
				_lastSnap = PlantConfig.SnapToField.Value;
			}
			value = PlantConfig.ColsUp.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Nudge(PlantConfig.GridColumns, 1, "wide");
				return;
			}
			value = PlantConfig.ColsDown.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Nudge(PlantConfig.GridColumns, -1, "wide");
				return;
			}
			value = PlantConfig.RowsUp.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Nudge(PlantConfig.GridRows, 1, "deep");
				return;
			}
			value = PlantConfig.RowsDown.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				Nudge(PlantConfig.GridRows, -1, "deep");
			}
		}

		private static void Nudge(ConfigEntry<int> entry, int delta, string axis)
		{
			int num = Mathf.Clamp(entry.Value + delta, 1, 7);
			if (num != entry.Value)
			{
				entry.Value = num;
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, "Plant " + PlantConfig.GridColumns.Value + "×" + PlantConfig.GridRows.Value + " " + axis, 0, (Sprite)null, false);
				}
				_lastCols = PlantConfig.GridColumns.Value;
				_lastRows = PlantConfig.GridRows.Value;
			}
		}

		public static bool Active(Player player)
		{
			if (!PlantConfig.On || !PlantConfig.Grid.Value || (Object)(object)player == (Object)null || !Wide)
			{
				return false;
			}
			if (Cultivating(player))
			{
				return (Object)(object)player.m_placementGhost != (Object)null;
			}
			return false;
		}

		public static bool Cultivating(Player player)
		{
			PieceTable buildPieces = player.m_buildPieces;
			if ((Object)(object)buildPieces == (Object)null)
			{
				return false;
			}
			return (((Object)buildPieces).name ?? "").IndexOf("Cultivator", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static IEnumerable<Cell> Cells(Player player, Transform ghost)
		{
			int cols = Mathf.Clamp(PlantConfig.GridColumns.Value, 1, 7);
			int rows = Mathf.Clamp(PlantConfig.GridRows.Value, 1, 7);
			int midX = (cols - 1) / 2;
			int midZ = (rows - 1) / 2;
			Piece piece = player.GetSelectedPiece();
			float space = Spacing(((Component)ghost).GetComponent<Piece>() ?? piece);
			Vector3 origin = ghost.position;
			Vector3 right = Flat(ghost.right);
			Vector3 fwd = Flat(ghost.forward);
			Plant plant = ((Component)ghost).GetComponent<Plant>();
			for (int z = 0; z < rows; z++)
			{
				for (int x = 0; x < cols; x++)
				{
					if (x != midX || z != midZ)
					{
						Vector3 grounded = origin + (float)(x - midX) * space * right + (float)(z - midZ) * space * fwd;
						bool flag = Sit(grounded, out grounded);
						yield return new Cell(grounded, flag && CanGrow(((Component)ghost).gameObject, piece, plant, grounded));
					}
				}
			}
		}

		private static Vector3 Flat(Vector3 axis)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			axis.y = 0f;
			if (!(((Vector3)(ref axis)).sqrMagnitude > 0.0001f))
			{
				return Vector3.forward;
			}
			return ((Vector3)(ref axis)).normalized;
		}

		private static float Spacing(Piece? piece)
		{
			Plant val = (((Object)(object)piece != (Object)null) ? ((Component)piece).GetComponent<Plant>() : null);
			float num = (((Object)(object)val != (Object)null) ? (val.m_growRadius * 2f) : 0f);
			return Mathf.Max(PlantConfig.Spacing.Value, num);
		}

		private static bool Sit(Vector3 pos, out Vector3 grounded)
		{
			//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_004a: 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_0055: 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_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_0030: 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_003d: 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)
			grounded = pos;
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			float num = default(float);
			if (PlantGrow.Free && instance.GetSolidHeight(pos, ref num, 1000))
			{
				grounded = new Vector3(pos.x, num, pos.z);
				return true;
			}
			float num2 = default(float);
			if (instance.GetGroundHeight(pos, ref num2))
			{
				grounded = new Vector3(pos.x, num2, pos.z);
				return true;
			}
			return false;
		}

		private static bool CanGrow(GameObject ghost, Piece? piece, Plant? plant, Vector3 pos)
		{
			//IL_001e: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0042: 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_0056: 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_0065: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			if (PlantGrow.Free)
			{
				return true;
			}
			if ((Object)(object)plant != (Object)null)
			{
				return (int)Probe(ghost, plant, pos) == 0;
			}
			Heightmap val = Heightmap.FindHeightmap(pos);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (((Object)(object)piece == (Object)null || piece.m_cultivatedGroundOnly) && !val.IsCultivated(pos))
			{
				return false;
			}
			if ((Object)(object)piece != (Object)null && (int)piece.m_onlyInBiome != 0 && (val.GetBiome(pos, 0.02f, false) & piece.m_onlyInBiome) == 0)
			{
				return false;
			}
			return !Physics.CheckSphere(pos, 0.4f, Plant.m_spaceMask, (QueryTriggerInteraction)1);
		}

		private static Status Probe(GameObject ghost, Plant plant, Vector3 pos)
		{
			//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_0049: 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_0058: 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)
			Transform transform = ghost.transform;
			Vector3 position = transform.position;
			Collider[] componentsInChildren = ghost.GetComponentsInChildren<Collider>(true);
			bool[] array = new bool[componentsInChildren.Length];
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				array[i] = componentsInChildren[i].enabled;
				componentsInChildren[i].enabled = false;
			}
			transform.position = pos;
			Status status = plant.GetStatus();
			transform.position = position;
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				componentsInChildren[j].enabled = array[j];
			}
			return status;
		}

		private static void Align(Player player, GameObject ghost)
		{
			//IL_002b: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0084: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (!PlantConfig.SnapToField.Value)
			{
				return;
			}
			Piece selectedPiece = player.GetSelectedPiece();
			float num = Spacing(ghost.GetComponent<Piece>() ?? selectedPiece);
			Transform val = Field(ghost.transform.position, num, ghost);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 val2 = Flat(val.right);
			Vector3 val3 = Flat(val.forward);
			Vector3 val4 = ghost.transform.position - val.position;
			float num2 = Mathf.Round(Vector3.Dot(val4, val2) / num);
			float num3 = Mathf.Round(Vector3.Dot(val4, val3) / num);
			if (Mathf.Abs(num2) < 0.01f && Mathf.Abs(num3) < 0.01f)
			{
				float num4 = Vector3.Dot(val4, val2);
				float num5 = Vector3.Dot(val4, val3);
				if (Mathf.Abs(num4) >= Mathf.Abs(num5))
				{
					num2 = ((num4 >= 0f) ? 1f : (-1f));
				}
				else
				{
					num3 = ((num5 >= 0f) ? 1f : (-1f));
				}
			}
			if (Sit(val.position + val2 * (num2 * num) + val3 * (num3 * num), out var grounded))
			{
				ghost.transform.SetPositionAndRotation(grounded, Quaternion.LookRotation(val3, Vector3.up));
			}
		}

		private static Transform? Field(Vector3 from, float space, GameObject ghost)
		{
			//IL_0017: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(PlantConfig.SnapRange.Value, space + 0.25f);
			Collider[] array = Physics.OverlapSphere(from, num, Plant.m_pieceMask, (QueryTriggerInteraction)1);
			Transform result = null;
			float num2 = num * num;
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Transform root = ((Component)val).transform.root;
				if (!((Object)(object)root == (Object)(object)ghost.transform) && !IsGhost(((Component)root).gameObject) && (!((Object)(object)((Component)root).GetComponentInChildren<Plant>(true) == (Object)null) || !((Object)(object)((Component)root).GetComponentInChildren<Pickable>(true) == (Object)null)))
				{
					Vector3 val2 = root.position - from;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!(sqrMagnitude < 0.01f) && !(sqrMagnitude > num2))
					{
						result = root;
						num2 = sqrMagnitude;
					}
				}
			}
			return result;
		}

		private static bool IsGhost(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				return ((Object)go).name.IndexOf("RestlessPlantGhost", StringComparison.Ordinal) >= 0;
			}
			return false;
		}

		public static void Hide()
		{
			foreach (GameObject ghost in Ghosts)
			{
				if ((Object)(object)ghost != (Object)null)
				{
					ghost.SetActive(false);
				}
			}
		}

		public static void Clear()
		{
			foreach (GameObject ghost in Ghosts)
			{
				if (!((Object)(object)ghost == (Object)null))
				{
					ghost.SetActive(false);
					Object.Destroy((Object)(object)ghost);
				}
			}
			Ghosts.Clear();
			_lastPiece = null;
		}

		private static GameObject MakeGhost(GameObject source, Vector3 pos, Quaternion rot)
		{
			//IL_002c: 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)
			bool activeSelf = source.activeSelf;
			source.SetActive(false);
			GameObject obj = Object.Instantiate<GameObject>(source);
			source.SetActive(activeSelf);
			((Object)obj).name = "RestlessPlantGhost";
			obj.transform.SetPositionAndRotation(pos, rot);
			Strip(obj);
			obj.SetActive(true);
			return obj;
		}

		private static void Strip(GameObject go)
		{
			ZNetView[] componentsInChildren = go.GetComponentsInChildren<ZNetView>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Piece[] componentsInChildren2 = go.GetComponentsInChildren<Piece>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			WearNTear[] componentsInChildren3 = go.GetComponentsInChildren<WearNTear>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Pickable[] componentsInChildren4 = go.GetComponentsInChildren<Pickable>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			Plant[] componentsInChildren5 = go.GetComponentsInChildren<Plant>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[i]);
			}
			Rigidbody[] componentsInChildren6 = go.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren6.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren6[i]);
			}
			Collider[] componentsInChildren7 = go.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren7.Length; i++)
			{
				componentsInChildren7[i].enabled = false;
			}
			LODGroup[] componentsInChildren8 = go.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren8.Length; i++)
			{
				componentsInChildren8[i].enabled = false;
			}
		}

		private static void Paint(GameObject go, bool ok)
		{
			//IL_001e: 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)
			Block.Clear();
			Block.SetColor(ColorId, ok ? Color.white : Bad);
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.SetPropertyBlock(Block);
				}
			}
		}
	}
	internal static class PlantGrow
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPrefix]
			[HarmonyPatch(typeof(Plant), "GetStatus")]
			private static bool AnyStatus(ref Status __result)
			{
				if (!Free)
				{
					return true;
				}
				__result = (Status)0;
				return false;
			}

			[HarmonyPrefix]
			[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
			private static void BeforeGhost(Player __instance)
			{
				if (PlantGrid.Cultivating(__instance))
				{
					Relax(__instance.m_placementGhost);
				}
			}

			[HarmonyPrefix]
			[HarmonyPatch(typeof(Player), "TryPlacePiece")]
			private static void Soften(Piece piece)
			{
				//IL_0052: 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_0065: Unknown result type (might be due to invalid IL or missing references)
				if (Free && !((Object)(object)piece == (Object)null))
				{
					_till = piece.m_cultivatedGroundOnly;
					_ground = piece.m_groundOnly;
					piece.m_cultivatedGroundOnly = false;
					piece.m_groundOnly = false;
					Plant component = ((Component)piece).GetComponent<Plant>();
					if (!((Object)(object)component == (Object)null))
					{
						_need = component.m_needCultivatedGround;
						_biome = component.m_biome;
						component.m_needCultivatedGround = false;
						component.m_biome = (Biome)0;
					}
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(Player), "TryPlacePiece")]
			private static void Harden(Piece piece)
			{
				//IL_0044: 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)
				if (Free && !((Object)(object)piece == (Object)null))
				{
					piece.m_cultivatedGroundOnly = _till;
					piece.m_groundOnly = _ground;
					Plant component = ((Component)piece).GetComponent<Plant>();
					if (!((Object)(object)component == (Object)null))
					{
						component.m_needCultivatedGround = _need;
						component.m_biome = _biome;
					}
				}
			}
		}

		private static bool _till;

		private static bool _ground;

		private static bool _need;

		private static Biome _biome;

		public static bool Free
		{
			get
			{
				if (PlantConfig.On)
				{
					return PlantConfig.GrowAnywhere.Value;
				}
				return false;
			}
		}

		public static void Relax(GameObject? ghost)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (Free && !((Object)(object)ghost == (Object)null))
			{
				Piece[] componentsInChildren = ghost.GetComponentsInChildren<Piece>(true);
				foreach (Piece obj in componentsInChildren)
				{
					obj.m_cultivatedGroundOnly = false;
					obj.m_groundOnly = false;
					obj.m_noInWater = false;
				}
				Plant[] componentsInChildren2 = ghost.GetComponentsInChildren<Plant>(true);
				foreach (Plant obj2 in componentsInChildren2)
				{
					obj2.m_needCultivatedGround = false;
					obj2.m_biome = (Biome)0;
				}
			}
		}
	}
	internal static class PlantHarvest
	{
		[HarmonyPatch]
		private static class Patches
		{
			[HarmonyPostfix]
			[HarmonyPatch(typeof(Pickable), "Interact")]
			private static void AfterPick(Pickable __instance, Humanoid character, bool __result)
			{
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				if (__result && PlantConfig.On && !_busy && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && Ours(__instance))
				{
					Piece componentInParent = ((Component)__instance).GetComponentInParent<Piece>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						Remember(componentInParent);
					}
					if (PlantConfig.BulkHarvest.Value)
					{
						Bulk(__instance, character);
					}
					if (PlantConfig.Replant.Value && __instance.m_respawnTimeMinutes <= 0f && (Object)(object)((componentInParent != null) ? ((Component)componentInParent).GetComponent<Plant>() : null) != (Object)null)
					{
						Replant((Player?)(object)((character is Player) ? character : null), ((Component)__instance).transform.position, ((Component)__instance).transform.rotation, componentInParent);
					}
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(Beehive), "Interact")]
			private static void AfterHive(Beehive __instance, Humanoid character, bool __result)
			{
				if (__result && PlantConfig.On && PlantConfig.BulkBeehives.Value && !_busy && !((Object)(object)character != (Object)(object)Player.m_localPlayer))
				{
					BulkHives(__instance, character);
				}
			}
		}

		private static Piece? _remembered;

		private static bool _busy;

		public static void Remember(Piece? piece)
		{
			if ((Object)(object)piece != (Object)null)
			{
				_remembered = piece;
			}
		}

		public static Piece? Hint()
		{
			if (!PlantConfig.Replant.Value)
			{
				return null;
			}
			return _remembered;
		}

		public static bool Grown(Pickable pickable)
		{
			return Ours(pickable);
		}

		private static bool Ours(Pickable pickable)
		{
			if ((Object)(object)pickable == (Object)null)
			{
				return false;
			}
			if (Utils.GetPrefabName(((Component)pickable).gameObject).StartsWith("Restless_"))
			{
				return true;
			}
			Piece componentInParent = ((Component)pickable).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent.GetCreator() != 0;
			}
			return false;
		}

		private static void BulkHives(Beehive picked, Humanoid character)
		{
			//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_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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			float value = PlantConfig.HarvestRange.Value;
			Vector3 position = ((Component)picked).transform.position;
			_busy = true;
			try
			{
				Beehive[] array = Object.FindObjectsByType<Beehive>((FindObjectsSortMode)0);
				foreach (Beehive val in array)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)picked))
					{
						Vector3 val2 = ((Component)val).transform.position - position;
						if (!(((Vector3)(ref val2)).sqrMagnitude > value * value))
						{
							val.Interact(character, false, false);
						}
					}
				}
			}
			finally
			{
				_busy = false;
			}
		}

		private static void Bulk(Pickable picked, Humanoid character)
		{
			//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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			string prefabName = Utils.GetPrefabName(((Component)picked).gameObject);
			float value = PlantConfig.HarvestRange.Value;
			Vector3 position = ((Component)picked).transform.position;
			_busy = true;
			try
			{
				Pickable[] array = Object.FindObjectsByType<Pickable>((FindObjectsSortMode)0);
				foreach (Pickable val in array)
				{
					if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)picked || !val.CanBePicked() || Utils.GetPrefabName(((Component)val).gameObject) != prefabName || !Ours(val))
					{
						continue;
					}
					Vector3 val2 = ((Component)val).transform.position - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude > value * value))
					{
						Vector3 position2 = ((Component)val).transform.position;
						Quaternion rotation = ((Component)val).transform.rotation;
						Piece componentInParent = ((Component)val).GetComponentInParent<Piece>();
						bool flag = val.m_respawnTimeMinutes <= 0f;
						val.Interact(character, false, false);
						if (PlantConfig.Replant.Value && flag && (Object)(object)((componentInParent != null) ? ((Component)componentInParent).GetComponent<Plant>() : null) != (Object)null)
						{
							Replant((Player?)(object)((character is Player) ? character : null), position2, rotation, componentInParent);
						}
					}
				}
			}
			finally
			{
				_busy = false;
			}
		}

		private static void Replant(Player? player, Vector3 pos, Quaternion rot, Piece? piece)
		{
			//IL_0032: 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)
			Piece val = (((Object)(object)piece != (Object)null) ? piece : _remembered);
			if (!((Object)(object)player == (Object)null) && !((Object)(object)val == (Object)null) && player.HaveRequirements(val, (RequirementMode)0))
			{
				player.PlacePiece(val, pos, rot, false, false);
			}
		}
	}
	internal static class PlantHover
	{
		[HarmonyPatch(typeof(Pickable), "GetHoverText")]
		private static class PickableHover
		{
			[HarmonyPostfix]
			private static void After(Pickable __instance, ref string __result)
			{
				if (!PlantConfig.On)
				{
					return;
				}
				if (PlantConfig.RegrowHint.Value && __instance.m_picked && __instance.m_respawnTimeMinutes > 0f)
				{
					double num = RemainingMinutes(__instance);
					if (num > 0.05)
					{
						string hoverName = __instance.GetHoverName();
						__result = (string.IsNullOrEmpty(hoverName) ? ("Regrows in " + Format(num)) : (hoverName + "\nRegrows in " + Format(num)));
					}
				}
				if (!PlantConfig.Replant.Value || __instance.m_respawnTimeMinutes > 0f || !PlantHarvest.Grown(__instance))
				{
					return;
				}
				Piece val = PlantHarvest.Hint();
				if (!((Object)(object)val == (Object)null))
				{
					string text = (string.IsNullOrEmpty(val.m_name) ? ((Object)val).name : Localization.instance.Localize(val.m_name));
					if (string.IsNullOrEmpty(__result))
					{
						__result = "Replant " + text;
					}
					else if (__result.IndexOf("Replant", StringComparison.OrdinalIgnoreCase) < 0)
					{
						__result = __result + "\nReplant " + text;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Plant), "GetHoverText")]
		private static class SaplingHover
		{
			[HarmonyPostfix]
			private static void After(Plant __instance, ref string __result)
			{
				if (!PlantConfig.On || !PlantConfig.RegrowHint.Value)
				{
					return;
				}
				double num = ((double)__instance.GetGrowTime() - __instance.TimeSincePlanted()) / 60.0;
				if (!(num <= 0.05))
				{
					string text = "Grows in " + Format(num);
					if (string.IsNullOrEmpty(__result))
					{
						__result = text;
					}
					else if (__result.IndexOf("Grows in", StringComparison.OrdinalIgnoreCase) < 0)
					{
						__result = __result + "\n" + text;
					}
				}
			}
		}

		private static double RemainingMinutes(Pickable pick)
		{
			long num = PickedTime(pick);
			if (num <= 1)
			{
				return pick.m_respawnTimeMinutes;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return pick.m_respawnTimeMinutes;
			}
			double totalMinutes = (ZNet.instance.GetTime() - new DateTime(num)).TotalMinutes;
			return (double)pick.m_respawnTimeMinutes - totalMinutes;
		}

		private static long PickedTime(Pickable pick)
		{
			if ((Object)(object)pick.m_nview != (Object)null && pick.m_nview.IsValid())
			{
				return pick.m_nview.GetZDO().GetLong(ZDOVars.s_pickedTime, 0L);
			}
			return pick.m_pickedTime;
		}

		private static string Format(double minutes)
		{
			if (minutes < 1.0)
			{
				return "soon";
			}
			if (minutes < 60.0)
			{
				return $"{Mathf.CeilToInt((float)minutes)} min";
			}
			int num = (int)(minutes / 60.0);
			int num2 = Mathf.CeilToInt((float)(minutes % 60.0));
			if (num2 >= 60)
			{
				num++;
				num2 = 0;
			}
			if (num2 <= 0)
			{
				return $"{num}h";
			}
			return $"{num}h {num2}m";
		}
	}
	internal static class PlantSettings
	{
		internal static IDisposable Register()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Expected O, but got Unknown
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			return SettingsPageApi.RegisterSettings("restless.plant", (SettingsSection[])(object)new SettingsSection[4]
			{
				new SettingsSection("Planting", (SettingsOption[])(object)new SettingsOption[5]
				{
					new SettingsOption("Enable RestlessPlant", (ConfigEntryBase)(object)PlantConfig.Enabled, true, "", true),
					new SettingsOption("Berry bushes and forage", (ConfigEntryBase)(object)PlantConfig.ExtraCrops, true, "", true),
					new SettingsOption("Extra saplings", (ConfigEntryBase)(object)PlantConfig.ExtraSaplings, true, "", true),
					new SettingsOption("Decorative plants", (ConfigEntryBase)(object)PlantConfig.ExtraFlora, true, "", true),
					new SettingsOption("Grow anywhere", (ConfigEntryBase)(object)PlantConfig.GrowAnywhere, true, "", true)
				}),
				new SettingsSection("Harvesting", (SettingsOption[])(object)new SettingsOption[4]
				{
					new SettingsOption("Harvest neighbouring crops", (ConfigEntryBase)(object)PlantConfig.BulkHarvest, true, "", false),
					new SettingsOption("Collect neighbouring beehives", (ConfigEntryBase)(object)PlantConfig.BulkBeehives, true, "", false),
					new SettingsOption("Harvest range", (ConfigEntryBase)(object)PlantConfig.HarvestRange, true, "m", false),
					new SettingsOption("Replant on harvest", (ConfigEntryBase)(object)PlantConfig.Replant, true, "", false)
				}),
				new SettingsSection("Your planting grid", (SettingsOption[])(object)new SettingsOption[6]
				{
					new SettingsOption("Grid planting", (ConfigEntryBase)(object)PlantConfig.Grid, false, "", false),
					new SettingsOption("Columns", (ConfigEntryBase)(object)PlantConfig.GridColumns, false, "", false),
					new SettingsOption("Rows", (ConfigEntryBase)(object)PlantConfig.GridRows, false, "", false),
					new SettingsOption("Spacing", (ConfigEntryBase)(object)PlantConfig.Spacing, false, "m", false),
					new SettingsOption("Snap to existing field", (ConfigEntryBase)(object)PlantConfig.SnapToField, false, "", false),
					new SettingsOption("Snap range", (ConfigEntryBase)(object)PlantConfig.SnapRange, false, "m", false)
				}),
				new SettingsSection("Your controls and hints", (SettingsOption[])(object)new SettingsOption[6]
				{
					new SettingsOption("Show regrowth time", (ConfigEntryBase)(object)PlantConfig.RegrowHint, false, "", false),
					new SettingsOption("Add column", (ConfigEntryBase)(object)PlantConfig.ColsUp, false, "", false),
					new SettingsOption("Remove column", (ConfigEntryBase)(object)PlantConfig.ColsDown, false, "", false),
					new SettingsOption("Add row", (ConfigEntryBase)(object)PlantConfig.RowsUp, false, "", false),
					new SettingsOption("Remove row", (ConfigEntryBase)(object)PlantConfig.RowsDown, false, "", false),
					new SettingsOption("Toggle field snapping", (ConfigEntryBase)(object)PlantConfig.SnapToggle, false, "", false)
				})
			});
		}
	}
	[BepInPlugin("restless.plant", "RestlessPlant", "0.1.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "restless.plant";

		public const string PluginName = "RestlessPlant";

		public const string PluginVersion = "0.1.5";

		private Harmony? _harmony;

		private IDisposable? _settings;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PlantConfig.Bind(((BaseUnityPlugin)this).Config);
			_settings = PlantSettings.Register();
			CropPieces.Load();
			_harmony = new Harmony("restless.plant");
			_harmony.PatchAll();
			Log.LogInfo((object)"RestlessPlant 0.1.5 loaded.");
		}

		private void Update()
		{
			if (!Console.IsVisible())
			{
				PlantGrid.Tick();
			}
		}

		private void OnDestroy()
		{
			_settings?.Dispose();
			PlantGrid.Clear();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}