Decompiled source of SeedTotem v0.2.6

files\plugins\SeedTotem\SeedTotem.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.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SeedTotem.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SeedTotem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SeedTotem")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.1.5")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.5.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 static class PoissonDiscSampling
{
	public static List<Vector2> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 30)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_00a0: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		float num = radius / Mathf.Sqrt(2f);
		int[,] array = new int[Mathf.CeilToInt(sampleRegionSize.x / num), Mathf.CeilToInt(sampleRegionSize.y / num)];
		List<Vector2> list = new List<Vector2>();
		List<Vector2> list2 = new List<Vector2>();
		list2.Add(sampleRegionSize / 2f);
		Vector2 val2 = default(Vector2);
		while (list2.Count > 0)
		{
			int index = Random.Range(0, list2.Count);
			Vector2 val = list2[index];
			bool flag = false;
			for (int i = 0; i < numSamplesBeforeRejection; i++)
			{
				float num2 = Random.value * (float)Math.PI * 2f;
				((Vector2)(ref val2))..ctor(Mathf.Sin(num2), Mathf.Cos(num2));
				Vector2 val3 = val + val2 * Random.Range(radius, 2f * radius);
				if (IsValid(val3, sampleRegionSize, num, radius, list, array))
				{
					list.Add(val3);
					list2.Add(val3);
					array[(int)(val3.x / num), (int)(val3.y / num)] = list.Count;
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				list2.RemoveAt(index);
			}
		}
		return list;
	}

	private static bool IsValid(Vector2 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List<Vector2> points, int[,] grid)
	{
		//IL_0001: 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: 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_0042: 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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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)
		if (candidate.x >= 0f && candidate.x < sampleRegionSize.x && candidate.y >= 0f && candidate.y < sampleRegionSize.y)
		{
			int num = (int)(candidate.x / cellSize);
			int num2 = (int)(candidate.y / cellSize);
			int num3 = Mathf.Max(0, num - 2);
			int num4 = Mathf.Min(num + 2, grid.GetLength(0) - 1);
			int num5 = Mathf.Max(0, num2 - 2);
			int num6 = Mathf.Min(num2 + 2, grid.GetLength(1) - 1);
			for (int i = num3; i <= num4; i++)
			{
				for (int j = num5; j <= num6; j++)
				{
					int num7 = grid[i, j] - 1;
					if (num7 != -1)
					{
						Vector2 val = candidate - points[num7];
						float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
						if (sqrMagnitude < radius * radius)
						{
							return false;
						}
					}
				}
			}
			return true;
		}
		return false;
	}
}
namespace SeedTotem
{
	internal class SeedQueue : IEquatable<SeedQueue>
	{
		public class Entry : IEquatable<Entry>
		{
			public string Name { get; internal set; }

			public int Amount { get; internal set; }

			public Entry(string name, int amount)
			{
				Name = name;
				Amount = amount;
			}

			public bool Equals(Entry other)
			{
				return other != null && Name == other.Name && Amount == other.Amount;
			}

			public override int GetHashCode()
			{
				int num = 221287967;
				num = num * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
				return num * -1521134295 + Amount.GetHashCode();
			}

			public override bool Equals(object obj)
			{
				return Equals(obj as Entry);
			}

			public override string ToString()
			{
				return $"Name: {Name}, Amount: {Amount}";
			}

			public static bool operator ==(Entry left, Entry right)
			{
				return left?.Equals(right) ?? ((object)right == null);
			}

			public static bool operator !=(Entry left, Entry right)
			{
				return !(left == right);
			}
		}

		private readonly Queue<Entry> queue = new Queue<Entry>();

		public int Count => queue.Sum((Entry entry) => entry.Amount);

		public SeedQueue()
		{
		}

		public SeedQueue(ZPackage package)
		{
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				queue.Enqueue(new Entry(package.ReadString(), package.ReadInt()));
			}
		}

		public void AddSeed(string name, int amount)
		{
			if (queue.Any())
			{
				Entry entry = queue.Last();
				if (entry.Name == name)
				{
					entry.Amount += amount;
					return;
				}
			}
			queue.Enqueue(new Entry(name, amount));
		}

		public bool Equals(SeedQueue other)
		{
			if ((object)other == null)
			{
				return false;
			}
			if ((object)this == other)
			{
				return true;
			}
			if (queue.Count != other.queue.Count)
			{
				return false;
			}
			for (int i = 0; i < queue.Count; i++)
			{
				if (!queue.ElementAt(i).Equals(other.queue.ElementAt(i)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool operator ==(SeedQueue left, SeedQueue right)
		{
			return left?.Equals(right) ?? ((object)right == null);
		}

		public static bool operator !=(SeedQueue left, SeedQueue right)
		{
			return !(left == right);
		}

		public override bool Equals(object obj)
		{
			return Equals(obj as SeedQueue);
		}

		public override int GetHashCode()
		{
			return 1833020792 + EqualityComparer<Queue<Entry>>.Default.GetHashCode(queue);
		}

		public string Peek()
		{
			return (queue.Count == 0) ? null : queue.Peek().Name;
		}

		public string Dequeue()
		{
			if (queue.Count == 0)
			{
				return null;
			}
			Entry entry = queue.Peek();
			entry.Amount--;
			if (entry.Amount <= 0)
			{
				queue.Dequeue();
			}
			return entry.Name;
		}

		public List<Entry> Restrict(string newRestrict)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (Entry item in queue)
			{
				if (dictionary.TryGetValue(item.Name, out var value))
				{
					dictionary[item.Name] = value + item.Amount;
				}
				else
				{
					dictionary[item.Name] = item.Amount;
				}
			}
			queue.Clear();
			if (dictionary.TryGetValue(newRestrict, out var value2))
			{
				queue.Enqueue(new Entry(newRestrict, value2));
				dictionary.Remove(newRestrict);
			}
			return dictionary.Select((KeyValuePair<string, int> kv) => new Entry(kv.Key, kv.Value)).ToList();
		}

		public void RemoveSeed()
		{
			if (queue.Any())
			{
				Entry entry = queue.Peek();
				entry.Amount--;
				if (entry.Amount <= 0)
				{
					queue.Dequeue();
				}
			}
		}

		public ZPackage ToZPackage()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(queue.Count);
			foreach (Entry item in queue)
			{
				val.Write(item.Name);
				val.Write(item.Amount);
			}
			return val;
		}
	}
	public class SeedTotem : MonoBehaviour, Interactable, Hoverable
	{
		internal enum FieldShape
		{
			Circle,
			Rectangle
		}

		public class ItemConversion
		{
			public GameObject pickablePrefab;

			public ItemDrop seedDrop;

			public Piece plantPiece;

			public Plant plant;

			public override string ToString()
			{
				return seedDrop.m_itemData.m_shared.m_name + " -> " + plant.m_name;
			}
		}

		public enum PlacementStatus
		{
			Init,
			Planting,
			NoRoom,
			WrongBiome
		}

		public static class PrefabHierarchyLogger
		{
			public static void LogPrefabHierarchy(GameObject prefab, string label)
			{
				if ((Object)(object)prefab == (Object)null)
				{
					Debug.LogWarning((object)(label + ": Prefab is null!"));
					return;
				}
				Debug.Log((object)("--- " + label + " hierarchy ---"));
				LogChildrenRecursive(prefab.transform, 0);
			}

			private static void LogChildrenRecursive(Transform parent, int indent)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				string text = new string(' ', indent * 2);
				Debug.Log((object)(text + ((Object)parent).name));
				foreach (Transform item in parent)
				{
					Transform parent2 = item;
					LogChildrenRecursive(parent2, indent + 1);
				}
			}
		}

		[CompilerGenerated]
		private sealed class <PullInHarvestedItems>d__48 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Vector3 origin;

			public Player player;

			public SeedTotem <>4__this;

			private Collider[] <itemColliders>5__1;

			private Collider[] <>s__2;

			private int <>s__3;

			private Collider <itemCollider>5__4;

			private ItemDrop <itemDrop>5__5;

			private Vector3 <playerPos>5__6;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<itemColliders>5__1 = null;
				<>s__2 = null;
				<itemCollider>5__4 = null;
				<itemDrop>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0039: 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)
				//IL_00c3: 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_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_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<itemColliders>5__1 = Physics.OverlapSphere(origin, 2f, LayerMask.GetMask(new string[1] { "item" }));
					<>s__2 = <itemColliders>5__1;
					for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++)
					{
						<itemCollider>5__4 = <>s__2[<>s__3];
						if (((Component)<itemCollider>5__4).TryGetComponent<ItemDrop>(ref <itemDrop>5__5))
						{
							<itemDrop>5__5.m_autoPickup = true;
							<playerPos>5__6 = ((Component)player).transform.position + Vector3.up * 1f;
							((Component)<itemDrop>5__5).transform.position = Vector3.Lerp(((Component)<itemDrop>5__5).transform.position, <playerPos>5__6, 0.5f);
							Logger.LogDebug((object)("Pulled harvested item '" + <itemDrop>5__5.m_itemData.m_shared.m_name + "' toward player."));
						}
						<itemDrop>5__5 = null;
						<itemCollider>5__4 = null;
					}
					<>s__2 = null;
					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();
			}
		}

		private const string ZDO_queued = "queued";

		private const string ZDO_total = "total";

		private const string ZDO_restrict = "restrict";

		private static readonly string messageSeedGenericPlural = LocalizationConfig.message_seed_totem_seed_generic_plural;

		private static readonly string messageSeedGenericSingular = LocalizationConfig.message_seed_totem_seed_generic;

		private static readonly string messageAll = LocalizationConfig.message_seed_totem_all;

		internal static GameObject sfxCultivatorPrefab;

		internal static GameObject greydwarfHealSfx;

		internal static ConfigEntry<KeyboardShortcut> configRadiusDecrementButton;

		internal static ConfigEntry<KeyboardShortcut> configRadiusIncrementButton;

		internal static ConfigEntry<KeyboardShortcut> configWidthDecrementButton;

		internal static ConfigEntry<KeyboardShortcut> configWidthIncrementButton;

		internal static ConfigEntry<KeyboardShortcut> configLengthDecrementButton;

		internal static ConfigEntry<KeyboardShortcut> configLengthIncrementButton;

		public static Dictionary<string, ItemConversion> seedPrefabMap = new Dictionary<string, ItemConversion>();

		internal ZNetView m_nview;

		public Piece m_piece;

		internal CircleProjector m_areaMarker;

		internal RectangleProjector m_rectangleProjector;

		private Animator m_animator;

		internal GameObject m_enabledEffect;

		internal MeshRenderer m_model;

		internal MeshRenderer m_gearLeft;

		internal MeshRenderer m_gearRight;

		public static EffectList m_disperseEffects = new EffectList();

		private static int m_spaceMask;

		internal FieldShape m_shape = FieldShape.Circle;

		internal SeedQueue Queue = new SeedQueue();

		private static readonly Color OdenGlow = new Color(0f, 1f, 0f) * 1.6f;

		private static readonly Color OdenGlowNoRoom = new Color(0.3f, 1f, 0f) * 1.3f;

		private static readonly Color OdenGlowWrongBiome = new Color(1f, 0.3f, 0f) * 3f;

		private static readonly Color OdenGlowDormant = new Color(0f, 0.3f, 0f) * 0.1f;

		private static bool scanningCultivator = false;

		private string m_hoverText = "";

		private float m_holdRepeatInterval = 1f;

		private float m_lastUseTime;

		internal static ConfigEntry<float> configRadiusChange;

		private float fxTimer;

		public int SeedQueueCount => (Queue != null) ? Queue.Count : 0;

		public float CurrentWidth => ((Object)(object)m_rectangleProjector != (Object)null) ? m_rectangleProjector.m_width : 0f;

		public float CurrentLength => ((Object)(object)m_rectangleProjector != (Object)null) ? m_rectangleProjector.m_length : 0f;

		public float CurrentRadius => ((Object)(object)m_areaMarker != (Object)null) ? m_areaMarker.m_radius : 0f;

		public void Awake()
		{
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)this).name.StartsWith("AutoField"))
			{
				m_shape = FieldShape.Rectangle;
				Transform obj = ((Component)this).transform.Find("AreaMarker");
				m_rectangleProjector = ((obj != null) ? ((Component)obj).GetComponent<RectangleProjector>() : null) ?? m_rectangleProjector;
				m_animator = ((Component)this).GetComponent<Animator>();
				Transform obj2 = ((Component)this).transform.Find("new/pivot_left/gear_left");
				m_gearLeft = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshRenderer>() : null);
				Transform obj3 = ((Component)this).transform.Find("new/pivot_right/gear_right");
				m_gearRight = ((obj3 != null) ? ((Component)obj3).GetComponent<MeshRenderer>() : null);
			}
			m_nview = ((Component)this).GetComponent<ZNetView>() ?? m_nview;
			m_piece = ((Component)this).GetComponent<Piece>() ?? m_piece;
			Transform obj4 = ((Component)this).transform.Find("AreaMarker");
			m_areaMarker = ((obj4 != null) ? ((Component)obj4).GetComponent<CircleProjector>() : null);
			Transform obj5 = ((Component)this).transform.Find("AreaMarker");
			m_rectangleProjector = ((obj5 != null) ? ((Component)obj5).GetComponent<RectangleProjector>() : null);
			Logger.LogInfo((object)$"[SeedTotem.Awake] RectangleProjector found: {(Object)(object)m_rectangleProjector != (Object)null}");
			if ((Object)(object)m_rectangleProjector != (Object)null)
			{
				Logger.LogInfo((object)$"[Awake] RectangleProjector initial localScale: {((Component)m_rectangleProjector).transform.localScale}");
			}
			Transform obj6 = ((Component)this).transform.Find("WayEffect");
			m_enabledEffect = ((obj6 != null) ? ((Component)obj6).gameObject : null) ?? m_enabledEffect;
			Transform obj7 = ((Component)this).transform.Find("new/default");
			m_model = ((obj7 != null) ? ((Component)obj7).GetComponent<MeshRenderer>() : null) ?? m_model;
			if (m_shape == FieldShape.Circle && (Object)(object)m_areaMarker == (Object)null)
			{
				Logger.LogWarning((object)"AreaMarker (CircleProjector) not found!");
			}
			if (m_shape == FieldShape.Rectangle && (Object)(object)m_rectangleProjector == (Object)null)
			{
				Logger.LogWarning((object)"AreaMarker (RectangleProjector) not found!");
			}
			if ((Object)(object)m_piece == (Object)null)
			{
				Logger.LogWarning((object)"Piece (m_piece) not found!");
			}
			if ((Object)(object)m_nview == (Object)null)
			{
				Logger.LogWarning((object)"ZNetView (m_nview) not found!");
			}
			if ((Object)(object)m_enabledEffect == (Object)null)
			{
				Logger.LogWarning((object)"WayEffect (m_enabledEffect) not found!");
			}
			if ((Object)(object)m_model == (Object)null)
			{
				Logger.LogWarning((object)"new/default (m_model) not found!");
			}
			SeedTotemHoverHelper seedTotemHoverHelper = ((Component)this).GetComponent<SeedTotemHoverHelper>() ?? ((Component)this).gameObject.AddComponent<SeedTotemHoverHelper>();
			seedTotemHoverHelper.totem = this;
			if ((Object)(object)m_model != (Object)null)
			{
				Material[] materials = ((Renderer)m_model).materials;
				int num = Array.FindIndex(materials, (Material m) => ((Object)m).name.StartsWith("Guardstone_OdenGlow"));
				if (num >= 0)
				{
					Color val = new Color(3f / 85f, 0.28627452f, 0f) * 1.6f;
					materials[num].SetColor("_EmissionColor", val);
					materials[num].EnableKeyword("_EMISSION");
					materials[num].globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
					Logger.LogInfo((object)$"[OdenGlow] Modified shared material at index {num}");
				}
				else
				{
					Logger.LogWarning((object)"[OdenGlow] Guardstone_OdenGlow not found in model materials");
				}
			}
			if (m_spaceMask == 0)
			{
				m_spaceMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "item" });
			}
			ZNetView nview = m_nview;
			if (nview != null)
			{
				nview.Register("DropAllSeeds", (Action<long>)delegate(long sender)
				{
					RPC_DropAllSeeds(sender);
				});
			}
			ZNetView nview2 = m_nview;
			if (nview2 != null)
			{
				nview2.Register<string, int>("AddSeed", (Action<long, string, int>)RPC_AddSeed);
			}
			ZNetView nview3 = m_nview;
			if (nview3 != null)
			{
				nview3.Register<string>("Restrict", (Action<long, string>)RPC_Restrict);
			}
			ZNetView nview4 = m_nview;
			if (nview4 != null)
			{
				nview4.Register<float>("SetRadius", (Action<long, float>)RPC_SetRadius);
			}
			ZNetView nview5 = m_nview;
			if (nview5 != null)
			{
				nview5.Register<float>("SetLength", (Action<long, float>)RPC_SetLength);
			}
			ZNetView nview6 = m_nview;
			if (nview6 != null)
			{
				nview6.Register<float>("SetWidth", (Action<long, float>)RPC_SetWidth);
			}
			ZNetView nview7 = m_nview;
			if (nview7 != null)
			{
				nview7.Register("SyncEffects", (Action<long>)delegate
				{
					UpdateEffects();
				});
			}
			ScanCultivator();
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			}
			else
			{
				Logger.LogWarning((object)"WearNTear component not found!");
			}
			((MonoBehaviour)this).InvokeRepeating("DisperseSeeds", 3f, SeedTotemMod.configDispersionTime.Value);
			if (Queue == null)
			{
				Queue = new SeedQueue();
			}
			if (m_shape == FieldShape.Circle)
			{
				UpdateVisuals();
			}
			if ((Object)(object)m_areaMarker != (Object)null)
			{
				((Component)m_areaMarker).gameObject.SetActive(false);
				Logger.LogInfo((object)("[Awake] " + ((Object)this).name + ": CircleProjector hidden at startup."));
			}
			if ((Object)(object)m_rectangleProjector != (Object)null)
			{
				m_rectangleProjector.StopProjecting();
				Logger.LogInfo((object)("[Awake] " + ((Object)this).name + ": RectangleProjector hidden at startup."));
			}
			if (m_nview.IsOwner())
			{
				UpdateMaterials(active: true);
			}
		}

		private void RPC_DropAllSeeds(long sender)
		{
			if (m_nview.IsOwner())
			{
				DropAllSeeds();
				UpdateEffects();
			}
		}

		public void Start()
		{
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				UpdateMaterials(active: true);
				HideMarker();
			}
			else
			{
				UpdateMaterials(active: false);
				if (m_nview.IsOwner())
				{
					CountTotal();
				}
			}
			if (m_shape == FieldShape.Circle && (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO() != null)
			{
				UpdateVisuals();
			}
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO() != null)
			{
				UpdateEffects();
			}
		}

		public static void ScanCultivator()
		{
			if (scanningCultivator)
			{
				return;
			}
			scanningCultivator = true;
			PieceTable pieceTable = PieceManager.Instance.GetPieceTable("_CultivatorPieceTable");
			foreach (GameObject piece in pieceTable.m_pieces)
			{
				Plant component = piece.GetComponent<Plant>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					continue;
				}
				Piece component2 = piece.GetComponent<Piece>();
				Requirement[] resources = component2.m_resources;
				if (resources.Length > 1)
				{
					Logger.LogWarning((object)("  Multiple seeds required for " + component.m_name + "? Skipping"));
					continue;
				}
				Requirement val = resources[0];
				ItemDrop resItem = val.m_resItem;
				ItemDrop resItem2 = val.m_resItem;
				if ((Object)(object)resItem2 != (Object)null && ((Object)resItem2).name.Equals("Sap", StringComparison.OrdinalIgnoreCase))
				{
					Logger.LogInfo((object)"[SeedTotem] Skipping Sap in cultivator scan");
				}
				else if (!seedPrefabMap.ContainsKey(resItem.m_itemData.m_shared.m_name))
				{
					Logger.LogDebug((object)("Looking for Prefab of " + resItem.m_itemData.m_shared.m_name + " -> " + ((Object)((Component)resItem).gameObject).name));
					ItemConversion itemConversion = new ItemConversion
					{
						seedDrop = val.m_resItem,
						plantPiece = component2,
						plant = component
					};
					Logger.LogDebug((object)("Registering seed type: " + itemConversion));
					seedPrefabMap.Add(resItem.m_itemData.m_shared.m_name, itemConversion);
				}
			}
			scanningCultivator = false;
		}

		internal void OnDamaged(HitData hit)
		{
			//IL_0049: 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_0085: 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_00b7: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			Character attacker = hit.GetAttacker();
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null)
			{
				if (!SeedTotemMod.configHarvestOnHit.Value)
				{
					return;
				}
				Logger.LogDebug((object)("OnDamaged: Hit by player " + val.GetPlayerName() + " — triggering harvest."));
				QueryTriggerInteraction val2 = (QueryTriggerInteraction)2;
				FieldShape shape = m_shape;
				FieldShape fieldShape = shape;
				Collider[] array = ((fieldShape != 0 && fieldShape == FieldShape.Rectangle) ? Physics.OverlapBox(((Component)this).transform.TransformPoint(new Vector3(0f, 0f, -1f - GetLength() / 2f)), new Vector3(GetWidth() / 2f + SeedTotemMod.configMargin.Value, 10f, GetLength() / 2f + SeedTotemMod.configMargin.Value), ((Component)this).transform.rotation, m_spaceMask, val2) : Physics.OverlapSphere(((Component)this).transform.position, GetRadius() + SeedTotemMod.configMargin.Value, m_spaceMask, val2));
				Collider[] array2 = array;
				foreach (Collider val3 in array2)
				{
					Pickable val4 = ((Component)val3).GetComponent<Pickable>() ?? ((Component)val3).GetComponentInParent<Pickable>();
					if ((Object)(object)val4 != (Object)null)
					{
						Vector3 position = ((Component)val4).transform.position;
						val4.Interact((Humanoid)(object)val, false, false);
						((MonoBehaviour)this).StartCoroutine(PullInHarvestedItems(position, val));
					}
				}
			}
			else if ((Object)(object)attacker != (Object)null)
			{
				Logger.LogDebug((object)$"OnDamaged: Hit by non-player ({((Object)attacker).name}, {((object)attacker).GetType()}) — skipping harvest.");
			}
			else
			{
				Logger.LogDebug((object)"OnDamaged: Unknown attacker (null) — skipping harvest.");
			}
		}

		[IteratorStateMachine(typeof(<PullInHarvestedItems>d__48))]
		private IEnumerator PullInHarvestedItems(Vector3 origin, Player player)
		{
			//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)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PullInHarvestedItems>d__48(0)
			{
				<>4__this = this,
				origin = origin,
				player = player
			};
		}

		internal void CopyPrivateArea(PrivateArea privateArea)
		{
			m_areaMarker = privateArea.m_areaMarker;
			((Component)m_areaMarker).gameObject.SetActive(false);
			m_enabledEffect = privateArea.m_enabledEffect;
			m_model = privateArea.m_model;
			if ((Object)(object)m_model != (Object)null && (Object)(object)m_enabledEffect != (Object)null && (Object)(object)m_areaMarker != (Object)null)
			{
				try
				{
					UpdateVisuals();
					return;
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("UpdateVisuals failed: " + ex.Message));
					return;
				}
			}
			Logger.LogWarning((object)"Skipping UpdateVisuals: required components are missing.");
		}

		public void UpdateVisuals(bool force = false)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			float radius = GetRadius();
			float width = GetWidth();
			float length = GetLength();
			if (m_shape == FieldShape.Circle && (Object)(object)m_areaMarker != (Object)null)
			{
				m_areaMarker.m_radius = radius;
				m_areaMarker.m_nrOfSegments = Mathf.CeilToInt(radius * 4f);
				((Component)m_areaMarker).gameObject.SetActive(false);
				Logger.LogInfo((object)$"[UpdateVisuals] Circle: radius={radius}, segments={m_areaMarker.m_nrOfSegments}");
			}
			else if (m_shape == FieldShape.Rectangle && (Object)(object)m_rectangleProjector != (Object)null && (!m_rectangleProjector.isRunning || force))
			{
				m_rectangleProjector.m_width = width;
				m_rectangleProjector.m_length = length;
				((Component)m_rectangleProjector).transform.localPosition = new Vector3(0f, 0f, -1f - length * 0.5f);
				if (m_rectangleProjector.isRunning)
				{
					m_rectangleProjector.RefreshStuff(force: true);
				}
				else
				{
					m_rectangleProjector.RefreshStuff(force: true);
					m_rectangleProjector.StartProjecting();
				}
				Logger.LogInfo((object)$"[UpdateVisuals] Rectangle: width={width}, length={length}");
			}
			Logger.LogInfo((object)$"[UpdateVisuals] {((Object)this).name}: Final values → Circle radius={radius}, Rect width={width}, length={length}");
		}

		public void UpdateVisuals()
		{
			UpdateVisuals(force: false);
		}

		private void UpdateMaterials(bool active)
		{
			if ((Object)(object)m_enabledEffect != (Object)null)
			{
				m_enabledEffect.SetActive(active);
			}
			if (Object.op_Implicit((Object)(object)m_animator))
			{
				((Behaviour)m_animator).enabled = active;
				((Behaviour)m_animator).enabled = active;
				MeshRenderer gearLeft = m_gearLeft;
				SetEmission((gearLeft != null) ? ((Renderer)gearLeft).materials : null, active);
				MeshRenderer gearRight = m_gearRight;
				SetEmission((gearRight != null) ? ((Renderer)gearRight).materials : null, active);
			}
			if ((Object)(object)m_model != (Object)null)
			{
				SetEmission(((Renderer)m_model).materials, active);
			}
		}

		private static void SetEmission(Material[] materials, bool active)
		{
			//IL_00da: 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_009f: 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)
			if (materials == null)
			{
				return;
			}
			foreach (Material val in materials)
			{
				if (!((Object)(object)val == (Object)null) && val.HasProperty("_EmissionColor") && ((Object)val).name.StartsWith("Guardstone_OdenGlow"))
				{
					if (active)
					{
						val.EnableKeyword("_EMISSION");
						val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
						val.SetColor("_EmissionColor", OdenGlow);
						Logger.LogInfo((object)string.Format("[GlowDebug] mat.name={0}, _EmissionColor={1}, _Color={2}", ((Object)val).name, val.GetColor("_EmissionColor"), val.GetColor("_Color")));
					}
					else
					{
						val.DisableKeyword("_EMISSION");
						val.SetColor("_EmissionColor", Color.black);
					}
				}
			}
		}

		private void UpdateGlowColor(PlacementStatus status)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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)
			if ((Object)(object)m_model == (Object)null)
			{
				return;
			}
			Material[] materials = ((Renderer)m_model).materials;
			foreach (Material val in materials)
			{
				if (((Object)val).name.StartsWith("Guardstone_OdenGlow"))
				{
					val.EnableKeyword("_EMISSION");
					val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1;
					switch (status)
					{
					case PlacementStatus.Init:
						val.SetColor("_EmissionColor", OdenGlowDormant);
						break;
					case PlacementStatus.WrongBiome:
						val.SetColor("_EmissionColor", OdenGlowWrongBiome);
						break;
					case PlacementStatus.NoRoom:
						val.SetColor("_EmissionColor", OdenGlowNoRoom);
						break;
					default:
						val.SetColor("_EmissionColor", OdenGlow);
						break;
					}
				}
			}
		}

		internal void UpdateEffects()
		{
			//IL_01a3: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: 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_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			bool flag = GetTotalSeedCount() > 0;
			bool flag2 = flag && GetQueuedStatus() == PlacementStatus.Planting;
			PlacementStatus queuedStatus = GetQueuedStatus();
			if (!((Object)(object)m_enabledEffect != (Object)null))
			{
				return;
			}
			m_enabledEffect.SetActive(true);
			Transform val = m_enabledEffect.transform.Find("Point light");
			Transform val2 = m_enabledEffect.transform.Find("flare");
			Transform val3 = m_enabledEffect.transform.Find("sparcs");
			Transform val4 = m_enabledEffect.transform.Find("sfx");
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(flag);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(flag);
			}
			if ((Object)(object)val4 != (Object)null)
			{
				((Component)val4).gameObject.SetActive(flag && SeedTotemMod.configSoundEffect.Value);
			}
			Transform[] array = (from t in ((Component)m_enabledEffect.transform).GetComponentsInChildren<Transform>(true)
				where ((Object)t).name == "sparcs"
				select t).ToArray();
			Transform[] array2 = array;
			foreach (Transform val5 in array2)
			{
				((Component)val5).gameObject.SetActive(flag);
			}
			Color val6 = default(Color);
			((Color)(ref val6))..ctor(0f, 0.8f, 0f, 1f);
			Color val7 = default(Color);
			((Color)(ref val7))..ctor(1f, 0.5f, 0f, 1f);
			Color val8 = val6;
			Color val9 = val6;
			if (queuedStatus == PlacementStatus.WrongBiome)
			{
				val8 = val7;
				val9 = val7;
			}
			float num = (flag2 ? 0.1f : 0.05f);
			float intensity = (flag2 ? 3f : 2f);
			if ((Object)(object)val3 != (Object)null)
			{
				ParticleSystem component = ((Component)val3).GetComponent<ParticleSystem>();
				if ((Object)(object)component != (Object)null)
				{
					MainModule main = component.main;
					((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(val8.r, val8.g, val8.b, 1f));
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				ParticleSystem component2 = ((Component)val2).GetComponent<ParticleSystem>();
				if ((Object)(object)component2 != (Object)null)
				{
					MainModule main2 = component2.main;
					((MainModule)(ref main2)).startColor = MinMaxGradient.op_Implicit(new Color(val9.r, val9.g, val9.b, num));
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				Light component3 = ((Component)val).GetComponent<Light>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.color = new Color(val8.r, val8.g, val8.b);
					component3.intensity = intensity;
				}
			}
			UpdateMaterials(flag2 || flag);
			UpdateGlowColor(queuedStatus);
		}

		public string GetHoverName()
		{
			return m_piece.m_name;
		}

		public string GetHoverText()
		{
			//IL_0043: 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)
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return "";
			}
			if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position) >= 10f)
			{
				return "";
			}
			try
			{
				ShowAreaMarker();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("SeedTotem: error showing rectangle projector: " + ex.Message));
			}
			SeedTotemHoverHelper component = ((Component)this).GetComponent<SeedTotemHoverHelper>();
			if ((Object)(object)component != (Object)null)
			{
				return component.BuildHoverText();
			}
			Logger.LogWarning((object)"SeedTotem: HoverHelper component missing, no hover text shown.");
			return "";
		}

		private float GetSafeZDOFloat(string key, float fallback)
		{
			return ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO() != null) ? m_nview.GetZDO().GetFloat(key, fallback) : fallback;
		}

		internal float GetLength()
		{
			return GetSafeZDOFloat("length", SeedTotemMod.configDefaultLength?.Value ?? 20f);
		}

		internal float GetWidth()
		{
			return GetSafeZDOFloat("width", SeedTotemMod.configDefaultWidth?.Value ?? 10f);
		}

		internal float GetRadius()
		{
			return GetSafeZDOFloat("radius", SeedTotemMod.configDefaultRadius?.Value ?? 10f);
		}

		public void ShowAreaMarker(float timeout = 0.5f)
		{
			if (m_shape == FieldShape.Circle && (Object)(object)m_areaMarker != (Object)null)
			{
				((Component)m_areaMarker).gameObject.SetActive(true);
			}
			else if (m_shape == FieldShape.Rectangle && (Object)(object)m_rectangleProjector != (Object)null && !m_rectangleProjector.isRunning)
			{
				UpdateVisuals();
			}
			((MonoBehaviour)this).CancelInvoke("HideMarker");
			if (timeout > 0f)
			{
				((MonoBehaviour)this).Invoke("HideMarker", timeout);
			}
		}

		public void HideMarker()
		{
			switch (m_shape)
			{
			case FieldShape.Circle:
				if ((Object)(object)m_areaMarker != (Object)null)
				{
					((Component)m_areaMarker).gameObject.SetActive(false);
				}
				break;
			case FieldShape.Rectangle:
				if ((Object)(object)m_rectangleProjector != (Object)null)
				{
					m_rectangleProjector.StopProjecting();
					Logger.LogInfo((object)"[HideMarker] RectangleProjector stopped.");
				}
				break;
			}
		}

		public void UpdateHoverText()
		{
			SeedTotemHoverHelper component = ((Component)this).GetComponent<SeedTotemHoverHelper>();
			if ((Object)(object)component != (Object)null)
			{
				m_hoverText = component.BuildHoverText();
				return;
			}
			Logger.LogWarning((object)"SeedTotem: Missing SeedTotemHoverHelper component!");
			m_hoverText = "";
		}

		internal int GetTotalSeedCount()
		{
			return m_nview.GetZDO().GetInt("total", 0);
		}

		private void DropSeeds(string seedName, int amount)
		{
			//IL_00c6: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			if (seedName == null)
			{
				return;
			}
			Logger.LogDebug((object)("Dropping instances of " + seedName));
			if (!seedPrefabMap.ContainsKey(seedName))
			{
				Logger.LogWarning((object)("Skipping unknown key " + seedName));
				return;
			}
			ItemDrop seedDrop = seedPrefabMap[seedName].seedDrop;
			GameObject gameObject = ((Component)seedDrop).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				Logger.LogWarning((object)("No seed found for " + seedName));
				return;
			}
			int num = amount;
			int maxStackSize = seedDrop.m_itemData.m_shared.m_maxStackSize;
			Logger.LogDebug((object)("Dropping " + num + " in stacks of " + maxStackSize));
			do
			{
				Vector3 val = ((Component)this).transform.position + Vector3.up + Random.insideUnitSphere * 0.3f;
				Quaternion val2 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
				ItemDrop component = Object.Instantiate<GameObject>(gameObject, val, val2).GetComponent<ItemDrop>();
				int num2 = ((num > maxStackSize) ? maxStackSize : num);
				if (amount != 0)
				{
					component.m_itemData.m_stack = num2;
				}
				num -= num2;
				Logger.LogDebug((object)("Dropped " + num2 + ", " + num + " left to go"));
			}
			while (num > 0);
		}

		private void DropAllSeeds()
		{
			while (GetQueueSize() > 0)
			{
				string queuedSeed = GetQueuedSeed();
				int queuedSeedCount = GetQueuedSeedCount();
				DropSeeds(queuedSeed, queuedSeedCount);
				ShiftQueueDown();
			}
			SetTotalSeedCount(0);
		}

		public string FindSeed(string restrict, Inventory inventory)
		{
			if (restrict == "")
			{
				foreach (string key in seedPrefabMap.Keys)
				{
					Logger.LogDebug((object)("Looking for seed " + key));
					if (inventory.HaveItem(key, true))
					{
						Logger.LogDebug((object)"Found seed!");
						return key;
					}
				}
			}
			else
			{
				Logger.LogDebug((object)("Looking for seed " + restrict));
				if (inventory.HaveItem(restrict, true))
				{
					Logger.LogDebug((object)"Found seed!");
					return restrict;
				}
			}
			return null;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_00e2: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			if (((Character)Player.m_localPlayer).InPlaceMode())
			{
				return false;
			}
			if (hold)
			{
				if (m_holdRepeatInterval <= 0f)
				{
					return false;
				}
				if (Time.time - m_lastUseTime < m_holdRepeatInterval)
				{
					return false;
				}
				m_lastUseTime = Time.time;
				bool flag = AddAllSeeds(user);
				if (!flag && m_nview.IsOwner() && GetTotalSeedCount() > 0)
				{
					DropAllSeeds();
					UpdateEffects();
					((Character)user).Message((MessageType)2, LocalizationConfig.message_seed_totem_queue_dropped, 0, (Sprite)null);
					if ((Object)(object)greydwarfHealSfx != (Object)null)
					{
						Object.Instantiate<GameObject>(greydwarfHealSfx, ((Component)this).transform.position, Quaternion.identity);
					}
					if (m_disperseEffects != null && m_disperseEffects.m_effectPrefabs.Length != 0)
					{
						float num = ((m_shape == FieldShape.Rectangle) ? (Mathf.Max(GetWidth(), GetLength()) / 5f * 1.5f) : (GetRadius() / 5f));
						Quaternion val = ((m_shape == FieldShape.Rectangle) ? Quaternion.Euler(300f, 0f, 0f) : Quaternion.identity);
						m_disperseEffects.Create(((Component)this).transform.position, val, ((Component)this).transform, num, -1);
					}
				}
				return flag;
			}
			m_lastUseTime = Time.time;
			string restrict = GetRestrict();
			string text = FindSeed(restrict, user.GetInventory());
			if (text == "VineberrySeeds" && !SeedTotemMod.configAllowVineberrySeeds.Value)
			{
				((Character)user).Message((MessageType)2, LocalizationConfig.message_seed_totem_vineberry_blocked, 0, (Sprite)null);
				return false;
			}
			if (SeedTotemMod.MushroomList.Contains(text) && !SeedTotemMod.configAllowMushrooms.Value)
			{
				Logger.LogInfo((object)"Mushroom rejected by config");
				return false;
			}
			if (SeedTotemMod.BushList.Contains(text) && !SeedTotemMod.configAllowBushes.Value)
			{
				Logger.LogInfo((object)"Bush  rejected by config.");
				return false;
			}
			if (SeedTotemMod.FlowerList.Contains(text) && !SeedTotemMod.configAllowFlowers.Value)
			{
				Logger.LogInfo((object)"Flower rejected by config.");
				return false;
			}
			if (text == null)
			{
				string text2 = ((!(restrict == "")) ? restrict : messageSeedGenericPlural);
				((Character)user).Message((MessageType)2, Localization.instance.Localize("$msg_donthaveany " + text2), 0, (Sprite)null);
				return false;
			}
			if (SeedTotemMod.configMaxSeeds.Value > 0)
			{
				int totalSeedCount = GetTotalSeedCount();
				if (totalSeedCount >= SeedTotemMod.configMaxSeeds.Value)
				{
					((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
					return false;
				}
			}
			user.GetInventory().RemoveItem(text, 1, -1, true);
			m_nview.InvokeRPC("AddSeed", new object[2] { text, 1 });
			((Character)user).Message((MessageType)2, "$msg_added " + text, 0, (Sprite)null);
			return true;
		}

		private bool AddAllSeeds(Humanoid user)
		{
			string restrict = GetRestrict();
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			foreach (string key in seedPrefabMap.Keys)
			{
				if ((key == "VineberrySeeds" && !SeedTotemMod.configAllowVineberrySeeds.Value) || (restrict != "" && restrict != key) || (SeedTotemMod.MushroomList.Contains(key) && !SeedTotemMod.configAllowMushrooms.Value) || (SeedTotemMod.BushList.Contains(key) && !SeedTotemMod.configAllowBushes.Value) || (SeedTotemMod.FlowerList.Contains(key) && !SeedTotemMod.configAllowFlowers.Value))
				{
					continue;
				}
				Logger.LogDebug((object)("Looking for seed " + key));
				int num = user.GetInventory().CountItems(key, -1, true);
				if (SeedTotemMod.configMaxSeeds.Value > 0)
				{
					int totalSeedCount = GetTotalSeedCount();
					int num2 = SeedTotemMod.configMaxSeeds.Value - totalSeedCount;
					if (num2 < 0)
					{
						if (flag)
						{
							return true;
						}
						((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null);
						return false;
					}
					num = Math.Min(num2, num);
				}
				if (num > 0)
				{
					m_nview.InvokeRPC("AddSeed", new object[2] { key, num });
					user.GetInventory().RemoveItem(key, num, -1, true);
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append("\n");
					}
					stringBuilder.Append("$msg_added " + num + " " + key);
				}
			}
			string text = stringBuilder.ToString();
			if (text.Length > 0)
			{
				((Character)user).Message((MessageType)2, stringBuilder.ToString(), 0, (Sprite)null);
				return true;
			}
			string text2 = ((!(restrict == "")) ? restrict : messageSeedGenericPlural);
			((Character)user).Message((MessageType)2, Localization.instance.Localize("$msg_donthaveany " + text2), 0, (Sprite)null);
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if (Object.op_Implicit((Object)(object)item.m_shared.m_buildPieces))
			{
				return false;
			}
			if (((Character)Player.m_localPlayer).InPlaceMode())
			{
				return false;
			}
			string text = GetSeedName(item);
			if (text == null)
			{
				return false;
			}
			if (!seedPrefabMap.ContainsKey(text))
			{
				if (!(GetRestrict() != ""))
				{
					((Character)user).Message((MessageType)2, "$message_seed_totem_not_a_seed", 0, (Sprite)null);
					return false;
				}
				text = "";
				((Character)user).Message((MessageType)2, "$message_seed_totem_unrestricted", 0, (Sprite)null);
			}
			Logger.LogDebug((object)("Restricting to " + text));
			m_nview.InvokeRPC("Restrict", new object[1] { text });
			return true;
		}

		private string GetSeedName(ItemData item)
		{
			return item.m_shared.m_name;
		}

		private PlacementStatus TryPlacePlant(ItemConversion conversion, int maxRetries)
		{
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Expected I4, but got Unknown
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Expected I4, but got Unknown
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Unknown result type (might be due to invalid IL or missing references)
			//IL_056d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_0595: Unknown result type (might be due to invalid IL or missing references)
			//IL_0597: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0629: Unknown result type (might be due to invalid IL or missing references)
			//IL_0613: Unknown result type (might be due to invalid IL or missing references)
			//IL_062e: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0713: Unknown result type (might be due to invalid IL or missing references)
			//IL_0715: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)conversion.plantPiece != (Object)null && (Object)(object)conversion.plant != (Object)null)
			{
				Logger.LogDebug((object)$"[DisperseSeeds] Trying to place {((Object)conversion.plantPiece).name}, maxRetries={maxRetries}");
			}
			else
			{
				string text = conversion.seedDrop?.m_itemData?.m_shared?.m_name ?? "unknown";
				string text2 = (((Object)(object)conversion.plantPiece != (Object)null) ? "OK" : "null");
				string text3 = (((Object)(object)conversion.plant != (Object)null) ? "OK" : "null");
				string text4 = conversion.seedDrop?.m_itemData?.m_shared?.m_name ?? "unknown";
				string text5 = Localization.instance.Localize(text4);
				Logger.LogWarning((object)("[DisperseSeeds] Missing conversion data for '" + text4 + "' (" + text5 + "): plantPiece=" + text2 + ", plant=" + text3));
			}
			int num = 0;
			Vector3 val = default(Vector3);
			PlacementStatus placementStatus;
			do
			{
				num++;
				Vector3 val2;
				switch (m_shape)
				{
				case FieldShape.Circle:
				{
					float radius = GetRadius();
					val2 = ((Component)this).transform.position + Vector3.up + Random.onUnitSphere * radius;
					Logger.LogDebug((object)$"[DisperseSeeds] Circle shape, radius={radius}, generated position={val2}");
					break;
				}
				case FieldShape.Rectangle:
				{
					float width = GetWidth();
					float length = GetLength();
					((Vector3)(ref val))..ctor(width * Random.Range(0f, 1f) - width / 2f, 0f, -1f - length * Random.Range(0f, 1f));
					val2 = ((Component)this).transform.TransformPoint(val);
					Logger.LogDebug((object)$"[DisperseSeeds] Rectangle shape, width={width}, length={length}, generated position={val2}");
					break;
				}
				default:
					Logger.LogWarning((object)"[DisperseSeeds] Unknown shape type.");
					return PlacementStatus.NoRoom;
				}
				float groundHeight = ZoneSystem.instance.GetGroundHeight(val2);
				val2.y = groundHeight;
				Logger.LogDebug((object)$"[DisperseSeeds] Adjusted to ground height: {val2}");
				if ((Object)(object)conversion.plantPiece == (Object)null || (Object)(object)conversion.plant == (Object)null)
				{
					string name = conversion.seedDrop.m_itemData.m_shared.m_name;
					float num2 = 0.5f;
					if (SeedTotemMod.MushroomList.Contains(name))
					{
						num2 = SeedTotemMod.configMushroomGrowRadius.Value;
					}
					else if (SeedTotemMod.BushList.Contains(name))
					{
						num2 = SeedTotemMod.configBushGrowRadius.Value;
					}
					else if (SeedTotemMod.FlowerList.Contains(name))
					{
						num2 = SeedTotemMod.configFlowerGrowRadius.Value;
					}
					if (!HasGrowSpace(val2, num2))
					{
						Logger.LogDebug((object)$"[DisperseSeeds] Not enough grow space at position {val2}, radius: {num2}");
						UpdateGlowColor(PlacementStatus.NoRoom);
						return PlacementStatus.NoRoom;
					}
					Quaternion val3 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
					GameObject val4 = conversion.pickablePrefab ?? ((Component)conversion.seedDrop).gameObject;
					GameObject val5 = Object.Instantiate<GameObject>(val4, val2, val3);
					if ((Object)(object)sfxCultivatorPrefab != (Object)null)
					{
						Object.Instantiate<GameObject>(sfxCultivatorPrefab, val2, Quaternion.identity);
					}
					RemoveOneSeed();
					return PlacementStatus.Planting;
				}
				if ((int)conversion.plant.m_biome != 0 && SeedTotemMod.configCheckBiome.Value && !IsCorrectBiome(val2, conversion.plant.m_biome))
				{
					Heightmap val6 = Heightmap.FindHeightmap(val2);
					Biome val7 = (Biome)(((Object)(object)val6 != (Object)null) ? ((int)val6.GetBiome(val2, 0.02f, false)) : 0);
					Logger.LogDebug((object)($"[DisperseSeeds] Wrong biome at {val2}:" + $" required=0x{(int)conversion.plant.m_biome:X}," + $" actual=0x{(int)val7:X}"));
					UpdateGlowColor(PlacementStatus.WrongBiome);
					return PlacementStatus.WrongBiome;
				}
				if (conversion.plant.m_needCultivatedGround && SeedTotemMod.configCheckCultivated.Value && !IsCultivated(val2))
				{
					Logger.LogDebug((object)$"[DisperseSeeds] Missing cultivated ground at position {val2}");
					placementStatus = PlacementStatus.NoRoom;
					UpdateGlowColor(PlacementStatus.NoRoom);
					continue;
				}
				if (!HasGrowSpace(val2, conversion.plant.m_growRadius))
				{
					Logger.LogDebug((object)$"[DisperseSeeds] Not enough grow space at position {val2}, radius: {conversion.plant.m_growRadius}");
					placementStatus = PlacementStatus.NoRoom;
					UpdateGlowColor(PlacementStatus.NoRoom);
					continue;
				}
				Logger.LogDebug((object)$"Placing new plant {conversion.plantPiece} at {val2}");
				Quaternion val8 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
				GameObject val9 = Object.Instantiate<GameObject>(((Component)conversion.plantPiece).gameObject, val2, val8);
				conversion.plantPiece.m_placeEffect.Create(val2, val8, val9.transform, 1f, -1);
				RemoveOneSeed();
				if (m_disperseEffects != null)
				{
					float num3 = ((m_shape == FieldShape.Rectangle) ? (Mathf.Max(GetWidth(), GetLength()) / 5f * 1.5f) : (GetRadius() / 5f));
					Quaternion val10 = ((m_shape == FieldShape.Rectangle) ? Quaternion.Euler(300f, 0f, 0f) : Quaternion.Euler(0f, 0f, 0f));
					if (m_disperseEffects != null && m_disperseEffects.m_effectPrefabs != null && m_disperseEffects.m_effectPrefabs.Length != 0)
					{
						Logger.LogDebug((object)$"[DisperseEffect] Prefabs={m_disperseEffects?.m_effectPrefabs?.Length}");
						EffectData[] effectPrefabs = m_disperseEffects.m_effectPrefabs;
						foreach (EffectData val11 in effectPrefabs)
						{
							object obj;
							if (val11 == null)
							{
								obj = null;
							}
							else
							{
								GameObject prefab = val11.m_prefab;
								obj = ((prefab != null) ? ((Object)prefab).name : null);
							}
							Logger.LogDebug((object)("Effect prefab: " + (string?)obj));
						}
						Logger.LogDebug((object)$"[DisperseEffect] Creating effect at {val2}");
						m_disperseEffects.Create(val2, val10, ((Component)this).transform, num3, -1);
					}
					else
					{
						Logger.LogWarning((object)"[DisperseEffect] Effect list is null or empty!");
					}
				}
				PlacementStatus placementStatus2 = PlacementStatus.Planting;
				UpdateGlowColor(placementStatus2);
				return placementStatus2;
			}
			while (num <= maxRetries);
			Logger.LogDebug((object)("Max retries reached, result " + placementStatus));
			UpdateGlowColor(placementStatus);
			return placementStatus;
		}

		private bool IsCorrectBiome(Vector3 p, Biome biome)
		{
			//IL_0001: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			Heightmap val = Heightmap.FindHeightmap(p);
			return Object.op_Implicit((Object)(object)val) && (val.GetBiome(p, 0.02f, false) & biome) > 0;
		}

		private bool IsCultivated(Vector3 p)
		{
			//IL_0001: 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)
			Heightmap val = Heightmap.FindHeightmap(p);
			return Object.op_Implicit((Object)(object)val) && val.IsCultivated(p);
		}

		private void DumpQueueDetails()
		{
			StringBuilder stringBuilder = new StringBuilder("QueueDetails:");
			for (int i = 0; i < GetQueueSize(); i++)
			{
				string queuedSeed = GetQueuedSeed(i);
				int queuedSeedCount = GetQueuedSeedCount(i);
				PlacementStatus queuedStatus = GetQueuedStatus(i);
				stringBuilder.AppendLine("Position " + i + " -> " + queuedSeed + " -> " + queuedSeedCount + " -> " + queuedStatus);
			}
			Logger.LogWarning((object)stringBuilder.ToString());
		}

		internal void DisperseSeeds()
		{
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsOwner() || !m_nview.IsValid() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				Logger.LogDebug((object)$"DisperseSeeds: m_nview={(Object)(object)m_nview != (Object)null}, isOwner={(Object)(object)m_nview != (Object)null && m_nview.IsOwner()}, isValid={(Object)(object)m_nview != (Object)null && m_nview.IsValid()}");
				return;
			}
			if (seedPrefabMap == null || SeedTotemMod.configMaxRetries == null || SeedTotemMod.configDispersionCount == null)
			{
				Logger.LogWarning((object)"Critical configuration or prefab map is missing; skipping DisperseSeeds.");
				return;
			}
			bool flag = false;
			int num = 0;
			int value = SeedTotemMod.configMaxRetries.Value;
			while (GetQueueSize() > 0)
			{
				Logger.LogDebug((object)$"DisperseSeeds: queue size = {GetQueueSize()}");
				string queuedSeed = GetQueuedSeed();
				int queuedSeedCount = GetQueuedSeedCount();
				if (string.IsNullOrEmpty(queuedSeed))
				{
					Logger.LogWarning((object)"Current seed is null or empty; skipping.");
					ShiftQueueDown();
					continue;
				}
				if (!seedPrefabMap.ContainsKey(queuedSeed))
				{
					Logger.LogWarning((object)("Key '" + queuedSeed + "' not found in seedPrefabMap"));
					DumpQueueDetails();
					Logger.LogWarning((object)"Shifting queue to remove invalid entry");
					ShiftQueueDown();
					continue;
				}
				Logger.LogDebug((object)$"DisperseSeeds: seedPrefabMap contains {seedPrefabMap.Count} entries");
				ItemConversion conversion = seedPrefabMap[queuedSeed];
				PlacementStatus placementStatus = TryPlacePlant(conversion, value);
				SetStatus(placementStatus);
				UpdateEffects();
				if (placementStatus == PlacementStatus.Planting)
				{
					num++;
					flag = true;
				}
				else
				{
					if (placementStatus == PlacementStatus.WrongBiome)
					{
						Logger.LogDebug((object)("Wrong biome detected, moving " + queuedSeed + " to end of queue"));
						MoveToEndOfQueue(queuedSeed, queuedSeedCount, placementStatus);
						break;
					}
					if (placementStatus == PlacementStatus.NoRoom)
					{
						break;
					}
				}
				if (num < SeedTotemMod.configDispersionCount.Value)
				{
					continue;
				}
				break;
			}
			if (flag && m_disperseEffects != null)
			{
				m_disperseEffects.Create(((Component)this).transform.position, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f), ((Component)this).transform, GetRadius() / 5f, -1);
			}
			else if (m_disperseEffects == null)
			{
				Logger.LogWarning((object)"Disperse effects object is null; cannot play effect.");
			}
		}

		private void MoveToEndOfQueue(string currentSeed, int currentCount, PlacementStatus status)
		{
			Logger.LogDebug((object)("Moving " + currentSeed + " to end of queue"));
			DumpQueueDetails();
			ShiftQueueDown();
			int queueSize = GetQueueSize();
			m_nview.GetZDO().Set("item" + queueSize, currentSeed);
			m_nview.GetZDO().Set("item" + queueSize + "count", currentCount);
			m_nview.GetZDO().Set("item" + queueSize + "status", (int)status);
			m_nview.GetZDO().Set("queued", queueSize + 1);
			Logger.LogDebug((object)"After move");
			DumpQueueDetails();
		}

		private bool HasGrowSpace(Vector3 position, float m_growRadius)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (m_spaceMask == 0)
			{
				m_spaceMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "item" });
			}
			Collider[] array = Physics.OverlapSphere(position, m_growRadius + SeedTotemMod.configMargin.Value, m_spaceMask);
			for (int i = 0; i < array.Length; i++)
			{
				Plant component = ((Component)array[i]).GetComponent<Plant>();
				if (!Object.op_Implicit((Object)(object)component) || (Object)(object)component != (Object)(object)this)
				{
					return false;
				}
			}
			return true;
		}

		public void OnDestroyed()
		{
			Logger.LogInfo((object)"SeedTotem destroyed, dropping all seeds");
			DropAllSeeds();
			((MonoBehaviour)this).CancelInvoke("UpdateSeedTotem");
		}

		internal int GetQueueSize()
		{
			return m_nview.GetZDO().GetInt("queued", 0);
		}

		internal string GetQueuedSeed(int queuePosition = 0)
		{
			if (GetQueueSize() == 0)
			{
				return null;
			}
			return m_nview.GetZDO().GetString("item" + queuePosition, (string)null);
		}

		private void SetStatus(PlacementStatus status)
		{
			m_nview.GetZDO().Set("item0status", (int)status);
		}

		internal PlacementStatus GetQueuedStatus(int queuePosition = 0)
		{
			if (GetQueueSize() == 0)
			{
				return PlacementStatus.Init;
			}
			return (PlacementStatus)m_nview.GetZDO().GetInt("item" + queuePosition + "status", 0);
		}

		internal int GetQueuedSeedCount(int queuePosition = 0)
		{
			if (GetQueueSize() == 0)
			{
				return 0;
			}
			return m_nview.GetZDO().GetInt("item" + queuePosition + "count", 0);
		}

		private void SetQueueSeedCount(int queuePosition, int count)
		{
			m_nview.GetZDO().Set("item" + queuePosition + "count", count);
		}

		private void RemoveOneSeed()
		{
			Logger.LogDebug((object)"--Removing 1 seed--");
			int queueSize = GetQueueSize();
			if (queueSize <= 0)
			{
				Logger.LogWarning((object)"Tried to remove a seed when none are queued");
				DumpQueueDetails();
				return;
			}
			int queuedSeedCount = GetQueuedSeedCount();
			Logger.LogDebug((object)("Current count " + queuedSeedCount));
			if (queuedSeedCount > 1)
			{
				SetQueueSeedCount(0, queuedSeedCount - 1);
			}
			else
			{
				ShiftQueueDown();
				UpdateEffects();
			}
			SetTotalSeedCount(GetTotalSeedCount() - 1);
		}

		private void ShiftQueueDown()
		{
			int queueSize = GetQueueSize();
			if (queueSize == 0)
			{
				Logger.LogError((object)"Invalid ShiftQueueDown, queue is empty");
				DumpQueueDetails();
				return;
			}
			for (int i = 0; i < queueSize; i++)
			{
				string @string = m_nview.GetZDO().GetString("item" + (i + 1), "");
				m_nview.GetZDO().Set("item" + i, @string);
				int @int = m_nview.GetZDO().GetInt("item" + (i + 1) + "count", 0);
				m_nview.GetZDO().Set("item" + i + "count", @int);
				int int2 = m_nview.GetZDO().GetInt("item" + (i + 1) + "status", 0);
				m_nview.GetZDO().Set("item" + i + "status", int2);
			}
			queueSize--;
			m_nview.GetZDO().Set("queued", queueSize);
		}

		private void QueueSeed(string name, int amount = 1, PlacementStatus status = PlacementStatus.Init)
		{
			int queueSize = GetQueueSize();
			string queuedSeed = GetQueuedSeed(queueSize - 1);
			if (queuedSeed == name)
			{
				SetQueueSeedCount(queueSize - 1, GetQueuedSeedCount(queueSize - 1) + amount);
			}
			else
			{
				m_nview.GetZDO().Set("item" + queueSize, name);
				m_nview.GetZDO().Set("item" + queueSize + "count", amount);
				m_nview.GetZDO().Set("item" + queueSize + "status", (int)status);
				m_nview.GetZDO().Set("queued", queueSize + 1);
			}
			SetTotalSeedCount(GetTotalSeedCount() + amount);
		}

		private void SetTotalSeedCount(int amount)
		{
			m_nview.GetZDO().Set("total", amount);
		}

		private void RPC_SetRadius(long sender, float newRadius)
		{
			if (!SeedTotemMod.configAdminOnlyResize.Value || !SeedTotemMod.configAdminOnlyResize.Value || (ZNet.instance.IsServer() && ZNet.instance.GetPeer(sender) == null) || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				if (m_nview.IsOwner())
				{
					newRadius = Mathf.Clamp(newRadius, 2f, SeedTotemMod.configMaxRadius.Value);
					Logger.LogInfo((object)$"Updating radius to {newRadius}");
					m_nview.GetZDO().Set("radius", newRadius);
				}
				UpdateVisuals(force: true);
			}
		}

		private void RPC_SetWidth(long sender, float newWidth)
		{
			if (!SeedTotemMod.configAdminOnlyResize.Value || !SeedTotemMod.configAdminOnlyResize.Value || (ZNet.instance.IsServer() && ZNet.instance.GetPeer(sender) == null) || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				if (m_nview.IsOwner())
				{
					newWidth = Mathf.Clamp(newWidth, 2f, SeedTotemMod.configMaxRadius.Value);
					Logger.LogInfo((object)$"Updating width to {newWidth}");
					m_nview.GetZDO().Set("width", newWidth);
				}
				UpdateVisuals(force: true);
				if ((Object)(object)m_rectangleProjector != (Object)null)
				{
					m_rectangleProjector.ResetProjection();
				}
			}
		}

		private void RPC_SetLength(long sender, float newLength)
		{
			if (!SeedTotemMod.configAdminOnlyResize.Value || (ZNet.instance.IsServer() && ZNet.instance.GetPeer(sender) == null) || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				if (m_nview.IsOwner())
				{
					newLength = Mathf.Clamp(newLength, 2f, SeedTotemMod.configMaxRadius.Value);
					Logger.LogInfo((object)$"Updating length to {newLength}");
					m_nview.GetZDO().Set("length", newLength);
				}
				UpdateVisuals(force: true);
				if ((Object)(object)m_rectangleProjector != (Object)null)
				{
					m_rectangleProjector.ResetProjection();
				}
			}
		}

		private void RPC_DropSeeds(long sender)
		{
			if (m_nview.IsOwner())
			{
				DropAllSeeds();
			}
		}

		private void RPC_AddSeed(long sender, string seedName, int amount)
		{
			if (seedName == "VineberrySeeds" && !SeedTotemMod.configAllowVineberrySeeds.Value)
			{
				Logger.LogInfo((object)"VineberrySeeds rejected by config.");
			}
			else if (SeedTotemMod.MushroomList.Contains(seedName) && !SeedTotemMod.configAllowMushrooms.Value)
			{
				Logger.LogInfo((object)"Mushroom rejected by config.");
			}
			else if (SeedTotemMod.BushList.Contains(seedName) && !SeedTotemMod.configAllowBushes.Value)
			{
				Logger.LogInfo((object)"Bush rejected by config.");
			}
			else if (SeedTotemMod.FlowerList.Contains(seedName) && !SeedTotemMod.configAllowFlowers.Value)
			{
				Logger.LogInfo((object)"Flower rejected by config.");
			}
			else if (m_nview.IsOwner())
			{
				QueueSeed(seedName, amount);
				UpdateEffects();
			}
		}

		private void RPC_Restrict(long sender, string restrict)
		{
			if (!m_nview.IsOwner())
			{
				return;
			}
			SetRestrict(restrict);
			int queueSize = GetQueueSize();
			int num = 0;
			for (int i = 0; i < queueSize; i++)
			{
				string queuedSeed = GetQueuedSeed();
				int queuedSeedCount = GetQueuedSeedCount();
				if (queuedSeed != restrict)
				{
					DropSeeds(queuedSeed, queuedSeedCount);
					ShiftQueueDown();
					UpdateEffects();
				}
				else
				{
					num += queuedSeedCount;
					MoveToEndOfQueue(queuedSeed, queuedSeedCount, GetQueuedStatus());
				}
			}
			SetTotalSeedCount(num);
			Logger.LogDebug((object)("Restricted to " + restrict));
		}

		private void CountTotal()
		{
			int queueSize = GetQueueSize();
			int num = 0;
			for (int i = 0; i < queueSize; i++)
			{
				num += GetQueuedSeedCount();
			}
			SetTotalSeedCount(num);
		}

		private void SetRestrict(string seedName)
		{
			m_nview.GetZDO().Set("restrict", seedName);
		}

		public string GetRestrict()
		{
			return m_nview.GetZDO().GetString("restrict", "");
		}

		public DestructibleType GetDestructibleType()
		{
			//IL_0011: 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)
			return (DestructibleType)((!SeedTotemMod.configMobsIgnoreTotems.Value) ? 1 : 0);
		}

		public void Update()
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
			{
				fxTimer += Time.deltaTime;
				if (fxTimer >= 1f)
				{
					UpdateEffects();
					fxTimer = 0f;
				}
			}
		}
	}
	public class SeedTotemHoverHelper : MonoBehaviour, Hoverable
	{
		public SeedTotem totem;

		public string GetHoverText()
		{
			return BuildHoverText();
		}

		public string GetHoverName()
		{
			if ((Object)(object)totem == (Object)null)
			{
				return "";
			}
			return (totem.m_shape == SeedTotem.FieldShape.Circle) ? LocalizationConfig.piece_seed_totem_name : LocalizationConfig.piece_seed_totem_auto_field_name;
		}

		public string BuildHoverText()
		{
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)totem == (Object)null)
				{
					return "";
				}
				StringBuilder stringBuilder = new StringBuilder();
				string text = ((totem.m_shape == SeedTotem.FieldShape.Circle) ? LocalizationConfig.piece_seed_totem_name : LocalizationConfig.piece_seed_totem_auto_field_name);
				stringBuilder.AppendLine("<color=orange><b>" + text + "</b></color>");
				stringBuilder.Append("\n");
				if (SeedTotemMod.configShowQueue.Value)
				{
					int totalSeedCount = totem.GetTotalSeedCount();
					if (totalSeedCount > 0)
					{
						stringBuilder.AppendLine(string.Format(LocalizationConfig.seedtotem_queue_count, totalSeedCount));
						string queuedSeed = totem.GetQueuedSeed();
						string text2 = ((queuedSeed != null) ? Localization.instance.Localize(queuedSeed) : Localization.instance.Localize("$seedtotem_queue_empty"));
						SeedTotem.PlacementStatus queuedStatus = totem.GetQueuedStatus();
						string text3 = ((queuedStatus == SeedTotem.PlacementStatus.WrongBiome) ? LocalizationConfig.message_seed_totem_status_wrong_biome : LocalizationConfig.message_seed_totem_status_planting);
						string text4 = ((queuedStatus == SeedTotem.PlacementStatus.WrongBiome) ? "red" : "green");
						stringBuilder.AppendLine("<color=" + text4 + ">" + text3 + "</color> " + text2);
						if (queuedStatus == SeedTotem.PlacementStatus.NoRoom)
						{
							stringBuilder.AppendLine("<color=yellow>" + LocalizationConfig.message_seed_totem_status_looking_for_space + "</color>");
						}
						stringBuilder.Append("\n");
					}
					else
					{
						stringBuilder.AppendLine(LocalizationConfig.seedtotem_queue_empty);
						stringBuilder.Append("\n\n");
					}
				}
				if (!SeedTotemMod.configAdminOnlyResize.Value || SynchronizationManager.Instance.PlayerIsAdmin)
				{
					KeyboardShortcut value;
					KeyCode mainKey;
					if (totem.m_shape == SeedTotem.FieldShape.Circle)
					{
						value = SeedTotemMod.configRadiusIncrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text5 = ((object)(KeyCode)(ref mainKey)).ToString();
						value = SeedTotemMod.configRadiusDecrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text6 = ((object)(KeyCode)(ref mainKey)).ToString();
						if (text5 != "None" || text6 != "None")
						{
							stringBuilder.AppendLine("<color=white><size=80%>[" + text5 + "/" + text6 + "] Change radius</size></color>");
						}
					}
					else if (totem.m_shape == SeedTotem.FieldShape.Rectangle)
					{
						value = SeedTotemMod.configWidthIncrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text7 = ((object)(KeyCode)(ref mainKey)).ToString();
						value = SeedTotemMod.configWidthDecrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text8 = ((object)(KeyCode)(ref mainKey)).ToString();
						if (text7 != "None" || text8 != "None")
						{
							stringBuilder.AppendLine("<color=white><size=80%>[" + text7 + "/" + text8 + "] Change width</size></color>");
						}
						value = SeedTotemMod.configLengthIncrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text9 = ((object)(KeyCode)(ref mainKey)).ToString();
						value = SeedTotemMod.configLengthDecrementButton.Value;
						mainKey = ((KeyboardShortcut)(ref value)).MainKey;
						string text10 = ((object)(KeyCode)(ref mainKey)).ToString();
						if (text9 != "None" || text10 != "None")
						{
							stringBuilder.AppendLine("<color=white><size=80%>[" + text9 + "/" + text10 + "] Change length</size></color>");
						}
					}
				}
				return stringBuilder.ToString();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("SeedTotemHoverHelper: Exception in BuildHoverText — " + ex.Message + "\n" + ex.StackTrace));
				return "";
			}
		}
	}
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("0zzerod.SeedTotem", "Seed Totem", "0.2.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SeedTotemMod : BaseUnityPlugin
	{
		public const string PluginGUID = "0zzerod.SeedTotem";

		public const string PluginName = "Seed Totem";

		public const string PluginVersion = "0.2.6";

		public static ConfigFile config;

		public static ConfigEntry<string> configLanguage;

		public static ConfigEntry<bool> configShowQueue;

		public static ConfigEntry<float> configDefaultRadius;

		public static ConfigEntry<float> configMaxRadius;

		public static ConfigEntry<float> configRadiusChange;

		public static ConfigEntry<float> configDispersionTime;

		public static ConfigEntry<int> configDispersionCount;

		public static ConfigEntry<int> configMaxRetries;

		public static ConfigEntry<int> configMaxSeeds;

		public static ConfigEntry<bool> configCheckCultivated;

		public static ConfigEntry<bool> configCheckBiome;

		public static ConfigEntry<bool> configHarvestOnHit;

		public static ConfigEntry<bool> configAdminOnlyResize;

		public static ConfigEntry<float> configDefaultWidth;

		public static ConfigEntry<float> configDefaultLength;

		public static ConfigEntry<float> configWidthChange;

		public static ConfigEntry<float> configLengthChange;

		public static ConfigEntry<KeyboardShortcut> configRadiusDecrementButton;

		public static ConfigEntry<KeyboardShortcut> configRadiusIncrementButton;

		public static ConfigEntry<KeyboardShortcut> configWidthDecrementButton;

		public static ConfigEntry<KeyboardShortcut> configWidthIncrementButton;

		public static ConfigEntry<KeyboardShortcut> configLengthDecrementButton;

		public static ConfigEntry<KeyboardShortcut> configLengthIncrementButton;

		public static ConfigEntry<float> configMargin;

		public static ConfigEntry<bool> configSoundEffect;

		public static ConfigEntry<float> configAshvineMinWallDistance;

		public static ConfigEntry<float> configAshvineMaxWallDistance;

		public static ConfigEntry<string> configAshvineWallTypes;

		public static ConfigEntry<bool> configAllowVineberrySeeds;

		public static ConfigEntry<bool> configMobsIgnoreTotems;

		public static ConfigEntry<bool> configAllowMushrooms;

		internal static ConfigEntry<string> configMushroomMappings;

		public static ConfigEntry<bool> configAllowBushes;

		internal static ConfigEntry<string> configBushMappings;

		public static ConfigEntry<bool> configAllowFlowers;

		internal static ConfigEntry<string> configFlowerMappings;

		public static readonly List<string> MushroomList = new List<string>();

		public static readonly List<string> BushList = new List<string>();

		public static readonly List<string> FlowerList = new List<string>();

		public static ConfigEntry<float> configMushroomGrowRadius;

		public static ConfigEntry<float> configBushGrowRadius;

		public static ConfigEntry<float> configFlowerGrowRadius;

		private Harmony harmony;

		public void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			config = ((BaseUnityPlugin)this).Config;
			harmony = new Harmony("0zzerod.SeedTotem");
			harmony.PatchAll();
			SetupGeneralConfig();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefabs;
			PrefabManager.OnVanillaPrefabsAvailable += delegate
			{
				SeedTotem.sfxCultivatorPrefab = PrefabManager.Instance.GetPrefab("sfx_build_cultivator");
				SeedTotem.greydwarfHealSfx = PrefabManager.Instance.GetPrefab("sfx_greydwarf_shaman_heal");
			};
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Seed Totem v0.2.6 initialized.");
		}

		private void SetupGeneralConfig()
		{
			//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_001a: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Expected O, but got Unknown
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Expected O, but got Unknown
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Expected O, but got Unknown
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Expected O, but got Unknown
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Expected O, but got Unknown
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Expected O, but got Unknown
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Expected O, but got Unknown
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Expected O, but got Unknown
			//IL_0453: Expected O, but got Unknown
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Expected O, but got Unknown
			//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Expected O, but got Unknown
			//IL_04dd: Expected O, but got Unknown
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Expected O, but got Unknown
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Expected O, but got Unknown
			//IL_0567: Expected O, but got Unknown
			//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bd: Expected O, but got Unknown
			//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Expected O, but got Unknown
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_0623: Expected O, but got Unknown
			//IL_0648: Unknown result type (might be due to invalid IL or missing references)
			//IL_0652: Expected O, but got Unknown
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_069d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0724: Unknown result type (might be due to invalid IL or missing references)
			//IL_0751: Unknown result type (might be due to invalid IL or missing references)
			//IL_0780: Unknown result type (might be due to invalid IL or missing references)
			//IL_078a: Expected O, but got Unknown
			config = ((BaseUnityPlugin)this).Config;
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			configLanguage = config.Bind<string>("Language", "Language", "English", "Language for localization.");
			LocalizationConfig.Init(config);
			LocalizationConfig.ApplyLanguage(configLanguage.Value);
			configLanguage.SettingChanged += delegate
			{
				LocalizationConfig.ApplyLanguage(configLanguage.Value);
			};
			configShowQueue = config.Bind<bool>("Visuals", "ShowQueue", true, new ConfigDescription("Show the seed queue on hover.", (AcceptableValueBase)null, Array.Empty<object>()));
			configDefaultRadius = config.Bind<float>("SeedTotem", "DefaultRadius", 12f, new ConfigDescription("Default radius.", (AcceptableValueBase)null, new object[1] { val }));
			configMaxRadius = config.Bind<float>("SeedTotem", "MaxRadius", 48f, new ConfigDescription("Maximum radius.", (AcceptableValueBase)null, new object[1] { val }));
			configRadiusChange = config.Bind<float>("SeedTotem", "RadiusChangeStep", 3f, new ConfigDescription("Radius change per step.", (AcceptableValueBase)null, new object[1] { val }));
			configWidthChange = config.Bind<float>("SeedTotem", "WidthChangeStep", 3f, new ConfigDescription("Width change per step.", (AcceptableValueBase)null, new object[1] { val }));
			configLengthChange = config.Bind<float>("SeedTotem", "LengthChangeStep", 3f, new ConfigDescription("Length change per step.", (AcceptableValueBase)null, new object[1] { val }));
			configDefaultWidth = config.Bind<float>("AdvancedSeedTotem", "DefaultWidth", 9f, new ConfigDescription("Default width for Auto Field.", (AcceptableValueBase)null, new object[1] { val }));
			configDefaultLength = config.Bind<float>("AdvancedSeedTotem", "DefaultLength", 21f, new ConfigDescription("Default length for Auto Field.", (AcceptableValueBase)null, new object[1] { val }));
			configDispersionTime = config.Bind<float>("Gameplay", "DispersionTime", 10f, new ConfigDescription("Interval between seed dispersion.", (AcceptableValueBase)null, new object[1] { val }));
			configDispersionCount = config.Bind<int>("Gameplay", "DispersionCount", 3, new ConfigDescription("Seeds to disperse per cycle.", (AcceptableValueBase)null, new object[1] { val }));
			configMaxRetries = config.Bind<int>("Gameplay", "MaxPlacementRetries", 10, new ConfigDescription("Max retries for placement.", (AcceptableValueBase)null, new object[1] { val }));
			configMaxSeeds = config.Bind<int>("Gameplay", "MaxSeeds", 100, new ConfigDescription("Max seeds in queue.", (AcceptableValueBase)null, new object[1] { val }));
			configCheckCultivated = config.Bind<bool>("Gameplay", "CheckCultivated", true, new ConfigDescription("Require cultivated ground.", (AcceptableValueBase)null, new object[1] { val }));
			configCheckBiome = config.Bind<bool>("Gameplay", "CheckBiome", true, new ConfigDescription("Require correct biome.", (AcceptableValueBase)null, new object[1] { val }));
			configHarvestOnHit = config.Bind<bool>("Gameplay", "HarvestOnHit", true, new ConfigDescription("Harvest pickables on hit.", (AcceptableValueBase)null, new object[1] { val }));
			configAdminOnlyResize = config.Bind<bool>("Gameplay", "AdminOnlyRadiusControl", true, new ConfigDescription("Only admin can resize radius.", (AcceptableValueBase)null, new object[1] { val }));
			configMargin = config.Bind<float>("Gameplay", "Margin", 0.5f, new ConfigDescription("Extra margin (in meters) for grow space and harvesting checks.", (AcceptableValueBase)null, new object[1] { val }));
			configMobsIgnoreTotems = config.Bind<bool>("Gameplay", "MobsIgnoreTotems", true, new ConfigDescription("If true, mobs will ignore Seed Totems.", (AcceptableValueBase)null, new object[1] { val }));
			configAllowMushrooms = config.Bind<bool>("Mushrooms", "AllowMushrooms", true, new ConfigDescription("If true, allows mushrooms to be queued and planted. (Jotun Puffs and Magecap are always allowed standard) ", (AcceptableValueBase)null, new object[1] { val }));
			configMushroomMappings = config.Bind<string>(new ConfigDefinition("Mushrooms", "MushroomMappings"), "Mushroom:Pickable_Mushroom, MushroomYellow:Pickable_Mushroom_yellow, MushroomBlue:Pickable_Mushroom_blue, MushroomSmokePuff:Pickable_SmokePuff", new ConfigDescription("Mushroom mappings from item name to pickable prefab name. Format: ItemName:PickablePrefab,ItemName2:PickablePrefab2", (AcceptableValueBase)null, new object[1] { val }));
			configMushroomGrowRadius = config.Bind<float>("Mushrooms", "GrowRadius", 0.2f, "Grow space radius required for mushrooms.");
			configAllowBushes = config.Bind<bool>("Bushes", "AllowBushes", true, new ConfigDescription("If true, allows (Berry) Bushes to be queued and planted.", (AcceptableValueBase)null, new object[1] { val }));
			configBushMappings = config.Bind<string>(new ConfigDefinition("Bushes", "BushMappings"), "Raspberry:RaspberryBush, Blueberries:BlueberryBush, Cloudberry:CloudberryBush", new ConfigDescription("Bush mappings from item name to pickable prefab name. Format: ItemName:PickablePrefab,ItemName2:PickablePrefab2", (AcceptableValueBase)null, new object[1] { val }));
			configBushGrowRadius = config.Bind<float>("Bushes", "GrowRadius", 0.5f, "Grow space radius required for berry bushes.");
			configAllowFlowers = config.Bind<bool>("Flowers", "AllowFlowers", true, new ConfigDescription("If true, allows Flowers to be queued and planted.", (AcceptableValueBase)null, new object[1] { val }));
			configFlowerMappings = config.Bind<string>(new ConfigDefinition("Flowers", "FlowerMappings"), "Dandelion:Pickable_Dandelion, Thistle:Pickable_Thistle, Fiddleheadfern:Pickable_Fiddlehead", new ConfigDescription("Flower mappings from item name to pickable prefab name. Format: ItemName:PickablePrefab,ItemName2:PickablePrefab2", (AcceptableValueBase)null, new object[1] { val }));
			configFlowerGrowRadius = config.Bind<float>("Flowers", "GrowRadius", 0.2f, "Grow space radius required for flowers.");
			configAshvineMinWallDistance = config.Bind<float>("Ashvine", "MinWallDistance", 1f, new ConfigDescription("Minimum distance from wall structure to allow ashvine planting.", (AcceptableValueBase)null, new object[1] { val }));
			configAshvineMaxWallDistance = config.Bind<float>("Ashvine", "MaxWallDistance", 4f, new ConfigDescription("Maximum distance from wall structure to allow ashvine planting.", (AcceptableValueBase)null, new object[1] { val }));
			configAshvineWallTypes = config.Bind<string>("Ashvine", "WallTypes", "woodwall,stonewall,pillar", new ConfigDescription("Comma-separated list of wall keywords to check proximity against for ashvine planting.", (AcceptableValueBase)null, new object[1] { val }));
			configAllowVineberrySeeds = config.Bind<bool>("Ashvine", "AllowVineberrySeeds", false, new ConfigDescription("If true, allows VineberrySeeds to be planted in standard Seed Totems.", (AcceptableValueBase)null, new object[1] { val }));
			configRadiusIncrementButton = config.Bind<KeyboardShortcut>("Keybinds", "RadiusIncrementButton", new KeyboardShortcut((KeyCode)270, Array.Empty<KeyCode>()), "Key to increase radius.");
			configRadiusDecrementButton = config.Bind<KeyboardShortcut>("Keybinds", "RadiusDecrementButton", new KeyboardShortcut((KeyCode)269, Array.Empty<KeyCode>()), "Key to decrease radius.");
			configWidthIncrementButton = config.Bind<KeyboardShortcut>("Keybinds", "WidthIncrementButton", new KeyboardShortcut((KeyCode)262, Array.Empty<KeyCode>()), "Key to increase width.");
			configWidthDecrementButton = config.Bind<KeyboardShortcut>("Keybinds", "WidthDecrementButton", new KeyboardShortcut((KeyCode)260, Array.Empty<KeyCode>()), "Key to decrease width.");
			configLengthIncrementButton = config.Bind<KeyboardShortcut>("Keybinds", "LengthIncrementButton", new KeyboardShortcut((KeyCode)264, Array.Empty<KeyCode>()), "Key to increase length.");
			configLengthDecrementButton = config.Bind<KeyboardShortcut>("Keybinds", "LengthDecrementButton", new KeyboardShortcut((KeyCode)258, Array.Empty<KeyCode>()), "Key to decrease length.");
			configSoundEffect = config.Bind<bool>("Sounds", "SoundEffect", false, new ConfigDescription("Enable sound effect when planting seeds.", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private void RegisterPrefabs()
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_016e: Expected O, but got Unknown
			try
			{
				RegisterDisperseSeedsEffect();
				GameObject val = PrefabManager.Instance.CreateClonedPrefab("SeedTotem", "guard_stone");
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"[SeedTotemMod] Failed to clone SeedTotem prefab.");
				}
				else
				{
					SeedTotem.PrefabHierarchyLogger.LogPrefabHierarchy(val, "SeedTotemPrefab");
					Transform obj = val.transform.Find("AreaMarker");
					CircleProjector val2 = ((obj != null) ? ((Component)obj).GetComponent<CircleProjector>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"[SeedTotemMod] Prefab already has a CircleProjector; skipping kitbash.");
					}
					else
					{
						Transform val3 = val.transform.Find("AreaMarker");
						if ((Object)(object)val3 != (Object)null)
						{
							Object.DestroyImmediate((Object)(object)((Component)val3).gameObject);
							((BaseUnityPlugin)this).Logger.LogInfo((object)"[SeedTotemMod] Removed invalid AreaMarker orphan.");
						}
						GameObject prefab = PrefabManager.Instance.GetPrefab("guard_stone");
						Transform val4 = ((prefab != null) ? prefab.transform.Find("AreaMarker") : null);
						if ((Object)(object)val4 != (Object)null)
						{
							KitbashConfig val5 = new KitbashConfig
							{
								KitbashSources = new List<KitbashSourceConfig>
								{
									new KitbashSourceConfig
									{
										SourcePrefab = "guard_stone",
										SourcePath = "AreaMarker",
										Position = val4.localPosition,
										Rotation = val4.localRotation,
										Scale = val4.localScale
									}
								}
							};
							KitbashManager.Instance.AddKitbash(val, val5);
							((BaseUnityPlugin)this).Logger.LogInfo((object)"[SeedTotemMod] Kit-bashed guard_stone AreaMarker into SeedTotem prefab.");
						}
						else
						{
							((BaseUnityPlugin)this).Logger.LogError((object)"[SeedTotemMod] guard_stone/AreaMarker not found; kitbash skipped.");
						}
					}
					SeedTotemPrefabConfig seedTotemPrefabConfig = new SeedTotemPrefabConfig();
					seedTotemPrefabConfig.UpdateCopiedPrefab(val);
					seedTotem