Decompiled source of SeedTotem v4.3.3

files/plugins/SeedTotem/SeedTotem.dll

Decompiled 7 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 On;
using SeedTotem.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SeedTotem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SeedTotem")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("4.3.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.3.3.0")]
[module: UnverifiableCode]
public static class PoissonDiscSampling
{
	public static List<Vector2> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 30)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		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_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_00ad: 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_00bc: 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];
						if (((Vector2)(ref val)).sqrMagnitude < radius * radius)
						{
							return false;
						}
					}
				}
			}
			return true;
		}
		return false;
	}
}
namespace SeedTotem
{
	public class SeedQueue : IEquatable<SeedQueue>
	{
		public sealed 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)
			{
				if (other != null && Name == other.Name)
				{
					return Amount == other.Amount;
				}
				return false;
			}

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

			public override string ToString()
			{
				return base.ToString();
			}

			public override bool Equals(object obj)
			{
				return base.Equals(obj);
			}

			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.Select((Entry entry) => entry.Amount).Sum();

		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 (queue.Count != other.queue.Count)
			{
				return false;
			}
			for (int i = 0; i < queue.Count; i++)
			{
				if (queue.ElementAt(i) != other.queue.ElementAt(i))
				{
					return false;
				}
			}
			return true;
		}

		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		public string Peek()
		{
			if (queue.Count == 0)
			{
				return null;
			}
			return 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 override int GetHashCode()
		{
			return 1833020792 + EqualityComparer<Queue<Entry>>.Default.GetHashCode(queue);
		}

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

		public ZPackage ToZPackage()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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 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);
		}
	}
	internal class SeedTotem : MonoBehaviour, Interactable, Hoverable
	{
		internal enum FieldShape
		{
			Circle,
			Rectangle
		}

		public class ItemConversion
		{
			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
		}

		private const string ZDO_queued = "queued";

		private const string ZDO_total = "total";

		private const string ZDO_restrict = "restrict";

		private const string messageSeedGenericPlural = "$message_seed_totem_seed_generic_plural";

		private const string messageSeedGenericSingular = "$message_seed_totem_seed_generic";

		private const string messageAll = "$message_seed_totem_all";

		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;

		internal static ConfigEntry<float> configFlareSize;

		internal static ConfigEntry<Color> configFlareColor;

		internal static ConfigEntry<Color> configLightColor;

		internal static ConfigEntry<float> configLightIntensity;

		internal static ConfigEntry<Color> configGlowColor;

		internal static ConfigEntry<bool> configShowQueue;

		internal static ConfigEntry<float> configDefaultRadius;

		internal static ConfigEntry<float> configDispersionTime;

		internal static ConfigEntry<float> configMargin;

		internal static ConfigEntry<int> configDispersionCount;

		internal static ConfigEntry<int> configMaxRetries;

		internal static ConfigEntry<bool> configHarvestOnHit;

		internal static ConfigEntry<bool> configCheckCultivated;

		internal static ConfigEntry<bool> configCheckBiome;

		internal static ConfigEntry<int> configMaxSeeds;

		internal static ConfigEntry<float> configMaxRadius;

		internal static ConfigEntry<bool> configAdminOnlyRadius;

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

		private ZNetView m_nview;

		private 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;

		private static bool scanningCultivator = false;

		private string m_hoverText = "";

		private readonly float m_holdRepeatInterval = 1f;

		private float m_lastUseTime;

		internal static ConfigEntry<float> configRadiusChange;

		public void Awake()
		{
			if (m_spaceMask == 0)
			{
				m_spaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });
			}
			ScanCultivator();
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_piece = ((Component)this).GetComponent<Piece>();
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			m_nview.Register<string, int>("AddSeed", (Action<long, string, int>)RPC_AddSeed);
			m_nview.Register<string>("Restrict", (Action<long, string>)RPC_Restrict);
			m_nview.Register<float>("SetRadius", (Action<long, float>)RPC_SetRadius);
			m_nview.Register<float>("SetLength", (Action<long, float>)RPC_SetLength);
			m_nview.Register<float>("SetWidth", (Action<long, float>)RPC_SetWidth);
			if (((Object)this).name.StartsWith("piece_seed_totem_auto_field"))
			{
				m_shape = FieldShape.Rectangle;
				m_rectangleProjector = ((Component)((Component)this).transform.Find("AreaMarker")).GetComponent<RectangleProjector>();
				m_animator = ((Component)this).GetComponent<Animator>();
				m_gearLeft = ((Component)((Component)this).transform.Find("new/pivot_left/gear_left")).GetComponent<MeshRenderer>();
				m_gearRight = ((Component)((Component)this).transform.Find("new/pivot_right/gear_right")).GetComponent<MeshRenderer>();
			}
			if (!Object.op_Implicit((Object)(object)m_enabledEffect))
			{
				m_enabledEffect = ((Component)((Component)this).transform.Find("WayEffect")).gameObject;
			}
			if (!Object.op_Implicit((Object)(object)m_model))
			{
				m_model = ((Component)((Component)this).transform.Find("new/default")).GetComponent<MeshRenderer>();
			}
			if (!Object.op_Implicit((Object)(object)m_areaMarker))
			{
				Transform obj = ((Component)this).transform.Find("AreaMarker");
				m_areaMarker = ((obj != null) ? ((Component)obj).GetComponent<CircleProjector>() : null);
			}
			((MonoBehaviour)this).InvokeRepeating("UpdateSeedTotem", 1f, 1f);
			((MonoBehaviour)this).InvokeRepeating("DisperseSeeds", 1f, configDispersionTime.Value);
			UpdateVisuals();
		}

		public void Start()
		{
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				UpdateMaterials(active: true);
				ShowAreaMarker(0f);
				return;
			}
			UpdateMaterials(active: false);
			HideMarker();
			if (m_nview.IsOwner())
			{
				CountTotal();
			}
		}

		public static void ScanCultivator()
		{
			if (scanningCultivator)
			{
				return;
			}
			scanningCultivator = true;
			foreach (GameObject piece in PieceManager.Instance.GetPieceTable("_CultivatorPieceTable").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;
				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 static void OnDamage(orig_Damage orig, WearNTear self, HitData hit)
		{
			SeedTotem seedTotem = default(SeedTotem);
			if (hit.GetTotalDamage() > 0f && ((Component)self).TryGetComponent<SeedTotem>(ref seedTotem))
			{
				SeedTotem seedTotem2 = seedTotem;
				Character attacker = hit.GetAttacker();
				seedTotem2.OnDamaged((Player)(object)((attacker is Player) ? attacker : null));
			}
			else
			{
				orig.Invoke(self, hit);
			}
		}

		private void OnDamaged(Player player)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (!configHarvestOnHit.Value)
			{
				return;
			}
			if ((Object)(object)player == (Object)null)
			{
				player = Player.m_localPlayer;
			}
			FieldShape shape = m_shape;
			Collider[] array = ((shape != 0 && shape == FieldShape.Rectangle) ? Physics.OverlapBox(((Component)this).transform.TransformPoint(new Vector3(0f, 0f, -1f - GetLength() / 2f)), new Vector3(GetWidth() / 2f + configMargin.Value, 10f, GetLength() / 2f + configMargin.Value), ((Component)this).transform.rotation, m_spaceMask) : Physics.OverlapSphere(((Component)this).transform.position, GetRadius() + configMargin.Value, m_spaceMask));
			for (int i = 0; i < array.Length; i++)
			{
				Pickable component = ((Component)array[i]).GetComponent<Pickable>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.Interact((Humanoid)(object)player, false, false);
				}
			}
		}

		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;
			UpdateVisuals();
		}

		public void UpdateVisuals()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: 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_02e0: 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)
			Vector3 position = ((Component)this).transform.position;
			Logger.LogDebug((object)("Updating color of SeedTotem at " + ((object)(Vector3)(ref position)).ToString()));
			Material[] materials = ((Renderer)m_model).materials;
			Color value = configGlowColor.Value;
			Material[] array = materials;
			foreach (Material val in array)
			{
				string value2 = "Guardstone_OdenGlow_mat";
				if (((Object)val).name.StartsWith(value2))
				{
					val.SetColor("_EmissionColor", value);
				}
			}
			EffectData[] effectPrefabs = m_disperseEffects.m_effectPrefabs;
			for (int i = 0; i < effectPrefabs.Length; i++)
			{
				ColorOverLifetimeModule colorOverLifetime = effectPrefabs[i].m_prefab.GetComponent<ParticleSystem>().colorOverLifetime;
				Gradient val2 = new Gradient();
				val2.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
				{
					new GradientColorKey(value, 0f),
					new GradientColorKey(Color.clear, 0.6f)
				}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
				{
					new GradientAlphaKey(1f, 0f),
					new GradientAlphaKey(0f, 0.6f)
				});
				((ColorOverLifetimeModule)(ref colorOverLifetime)).color = MinMaxGradient.op_Implicit(val2);
			}
			ParticleSystem component = ((Component)m_enabledEffect.transform.Find("sparcs")).gameObject.GetComponent<ParticleSystem>();
			ShapeModule shape = component.shape;
			Vector3 scale = ((ShapeModule)(ref shape)).scale;
			scale.y = 0.5f;
			MainModule main = component.main;
			((MainModule)(ref main)).startColor = new MinMaxGradient(value, value * 0.2f);
			Light component2 = ((Component)m_enabledEffect.transform.Find("Point light")).gameObject.GetComponent<Light>();
			component2.color = configLightColor.Value;
			component2.intensity = configLightIntensity.Value;
			if (m_shape == FieldShape.Circle)
			{
				float radius = GetRadius();
				m_areaMarker.m_radius = radius;
				m_areaMarker.m_nrOfSegments = Mathf.CeilToInt(m_areaMarker.m_radius * 4f);
				scale.x = radius;
				scale.z = radius;
				component2.range = radius;
			}
			else if (Object.op_Implicit((Object)(object)m_rectangleProjector))
			{
				float length = GetLength();
				m_rectangleProjector.m_length = length;
				((Component)m_rectangleProjector).transform.localPosition = new Vector3(0f, 0f, -1f - length / 2f);
				m_rectangleProjector.m_width = GetWidth();
				m_rectangleProjector.RefreshStuff(force: true);
			}
			MainModule main2 = ((Component)m_enabledEffect.transform.Find("flare")).gameObject.GetComponent<ParticleSystem>().main;
			((MainModule)(ref main2)).startColor = new MinMaxGradient(configFlareColor.Value);
			((MainModule)(ref main2)).startSize = new MinMaxCurve(configFlareSize.Value);
		}

		public void UpdateSeedTotem()
		{
			if (m_nview.IsValid())
			{
				bool active = IsEnabled();
				UpdateMaterials(active);
				UpdateHoverText();
			}
		}

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

		private static void SetEmission(Material[] materials, bool active)
		{
			foreach (Material val in materials)
			{
				if (active)
				{
					val.EnableKeyword("_EMISSION");
				}
				else
				{
					val.DisableKeyword("_EMISSION");
				}
			}
		}

		private bool IsEnabled()
		{
			return GetQueueSize() > 0;
		}

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

		public string GetHoverText()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			if (!m_nview.IsValid() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return "";
			}
			ShowAreaMarker();
			if (!configAdminOnlyRadius.Value || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				KeyboardShortcut value;
				switch (m_shape)
				{
				case FieldShape.Circle:
					value = configRadiusIncrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetRadius", new object[1] { GetRadius() + configRadiusChange.Value });
						break;
					}
					value = configRadiusDecrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetRadius", new object[1] { GetRadius() - configRadiusChange.Value });
					}
					break;
				case FieldShape.Rectangle:
					value = configLengthIncrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetLength", new object[1] { GetLength() + configRadiusChange.Value });
						break;
					}
					value = configLengthDecrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetLength", new object[1] { GetLength() - configRadiusChange.Value });
						break;
					}
					value = configWidthIncrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetWidth", new object[1] { GetWidth() + configRadiusChange.Value });
						break;
					}
					value = configWidthDecrementButton.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						m_nview.InvokeRPC("SetWidth", new object[1] { GetWidth() - configRadiusChange.Value });
					}
					break;
				}
			}
			return Localization.instance.Localize(m_hoverText);
		}

		private float GetRadius()
		{
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return configDefaultRadius.Value;
			}
			return m_nview.GetZDO().GetFloat("radius", configDefaultRadius.Value);
		}

		private float GetWidth()
		{
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return configDefaultRadius.Value;
			}
			return m_nview.GetZDO().GetFloat("width", configDefaultRadius.Value);
		}

		private float GetLength()
		{
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return configDefaultRadius.Value;
			}
			return m_nview.GetZDO().GetFloat("length", configDefaultRadius.Value);
		}

		public void ShowAreaMarker(float timeout = 0.5f)
		{
			switch (m_shape)
			{
			case FieldShape.Circle:
				((Component)m_areaMarker).gameObject.SetActive(true);
				break;
			case FieldShape.Rectangle:
				((Component)m_rectangleProjector).gameObject.SetActive(true);
				break;
			}
			((MonoBehaviour)this).CancelInvoke("HideMarker");
			if (timeout > 0f)
			{
				((MonoBehaviour)this).Invoke("HideMarker", timeout);
			}
		}

		public void HideMarker()
		{
			switch (m_shape)
			{
			case FieldShape.Circle:
				((Component)m_areaMarker).gameObject.SetActive(false);
				break;
			case FieldShape.Rectangle:
				((Component)m_rectangleProjector).gameObject.SetActive(false);
				break;
			}
		}

		private void UpdateHoverText()
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0160: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder(GetHoverName() + " (" + GetTotalSeedCount());
			if (configMaxSeeds.Value > 0)
			{
				stringBuilder.Append("/" + configMaxSeeds.Value);
			}
			stringBuilder.Append(")\n");
			string restrict = GetRestrict();
			string text = "$message_seed_totem_seed_generic";
			string text2 = "$message_seed_totem_seed_generic_plural";
			if (restrict != "")
			{
				text = restrict;
				text2 = restrict;
			}
			if (restrict != "")
			{
				stringBuilder.Append("<color=grey>$message_seed_totem_restricted_to</color> <color=green>" + restrict + "</color>\n");
			}
			stringBuilder.Append("[<color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add " + text + "\n");
			stringBuilder.Append("[$message_seed_totem_hold <color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add $message_seed_totem_all " + text2 + "\n");
			stringBuilder.Append("[<color=yellow><b>1-8</b></color>] $message_seed_totem_restrict\n");
			if (!configAdminOnlyRadius.Value || SynchronizationManager.Instance.PlayerIsAdmin)
			{
				switch (m_shape)
				{
				case FieldShape.Circle:
					stringBuilder.Append($"[<color=yellow>{configRadiusIncrementButton.Value}</color>/<color=yellow>{configRadiusDecrementButton.Value}</color>] $hud_seed_totem_change_radius\n");
					break;
				case FieldShape.Rectangle:
					stringBuilder.Append($"[<color=yellow>{configWidthIncrementButton.Value}</color>/<color=yellow>{configWidthDecrementButton.Value}</color>] $hud_seed_totem_change_width\n");
					stringBuilder.Append($"[<color=yellow>{configLengthIncrementButton.Value}</color>/<color=yellow>{configLengthDecrementButton.Value}</color>] $hud_seed_totem_change_length\n");
					break;
				}
			}
			if (configShowQueue.Value)
			{
				stringBuilder.Append("\n");
				for (int i = 0; i < GetQueueSize(); i++)
				{
					string queuedSeed = GetQueuedSeed(i);
					int queuedSeedCount = GetQueuedSeedCount(i);
					PlacementStatus queuedStatus = GetQueuedStatus(i);
					stringBuilder.Append(queuedSeedCount + " " + queuedSeed);
					switch (queuedStatus)
					{
					case PlacementStatus.NoRoom:
						stringBuilder.Append(" <color=grey>[</color><color=green>$message_seed_totem_status_looking_for_space</color><color=grey>]</color>");
						break;
					case PlacementStatus.Planting:
						stringBuilder.Append(" <color=grey>[</color><color=green>$message_seed_totem_status_planting</color><color=grey>]</color>");
						break;
					case PlacementStatus.WrongBiome:
						stringBuilder.Append(" <color=grey>[</color><color=red>$message_seed_totem_status_wrong_biome</color><color=grey>]</color>");
						break;
					}
					stringBuilder.Append("\n");
				}
			}
			m_hoverText = stringBuilder.ToString();
		}

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

		private void DropSeeds(string seedName, int amount)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if (seedName == null)
			{
				return;
			}
			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;
			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;
			}
			while (num > 0);
		}

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

		public string FindSeed(string restrict, Inventory inventory)
		{
			if (restrict == "")
			{
				foreach (string key in seedPrefabMap.Keys)
				{
					if (inventory.HaveItem(key, true))
					{
						return key;
					}
				}
			}
			else if (inventory.HaveItem(restrict, true))
			{
				return restrict;
			}
			return null;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			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;
				return AddAllSeeds(user);
			}
			m_lastUseTime = Time.time;
			string restrict = GetRestrict();
			string text = FindSeed(restrict, user.GetInventory());
			if (text == null)
			{
				string text2 = ((!(restrict == "")) ? restrict : "$message_seed_totem_seed_generic_plural");
				((Character)user).Message((MessageType)2, "$msg_donthaveany " + text2, 0, (Sprite)null);
				return false;
			}
			if (configMaxSeeds.Value > 0 && GetTotalSeedCount() >= 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 (restrict != "" && restrict != key)
				{
					continue;
				}
				int num = user.GetInventory().CountItems(key, -1, true);
				if (configMaxSeeds.Value > 0)
				{
					int totalSeedCount = GetTotalSeedCount();
					int num2 = 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}");
				}
			}
			if (stringBuilder.ToString().Length > 0)
			{
				((Character)user).Message((MessageType)2, stringBuilder.ToString(), 0, (Sprite)null);
				return true;
			}
			string text = ((!(restrict == "")) ? restrict : "$message_seed_totem_seed_generic_plural");
			((Character)user).Message((MessageType)2, "$msg_donthaveany " + text, 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			Vector3 val2 = default(Vector3);
			PlacementStatus result;
			do
			{
				num++;
				FieldShape shape = m_shape;
				Vector3 val;
				if (shape == FieldShape.Circle || shape != FieldShape.Rectangle)
				{
					float radius = GetRadius();
					val = ((Component)this).transform.position + Vector3.up + Random.onUnitSphere * radius;
				}
				else
				{
					float width = GetWidth();
					((Vector3)(ref val2))..ctor(width * Random.Range(0f, 1f) - width / 2f, 0f, -1f - GetLength() * Random.Range(0f, 1f));
					val = ((Component)this).transform.TransformPoint(val2);
				}
				float groundHeight = ZoneSystem.instance.GetGroundHeight(val);
				val.y = groundHeight;
				if ((int)conversion.plant.m_biome != 0 && configCheckBiome.Value && !IsCorrectBiome(val, conversion.plant.m_biome))
				{
					result = PlacementStatus.WrongBiome;
					continue;
				}
				if (conversion.plant.m_needCultivatedGround && configCheckCultivated.Value && !IsCultivated(val))
				{
					result = PlacementStatus.NoRoom;
					continue;
				}
				if (!HasGrowSpace(val, conversion.plant.m_growRadius))
				{
					result = PlacementStatus.NoRoom;
					continue;
				}
				Quaternion val3 = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f);
				GameObject val4 = Object.Instantiate<GameObject>(((Component)conversion.plantPiece).gameObject, val, val3);
				conversion.plantPiece.m_placeEffect.Create(val, val3, val4.transform, 1f, -1);
				RemoveOneSeed();
				return PlacementStatus.Planting;
			}
			while (num <= maxRetries);
			return result;
		}

		private bool IsCorrectBiome(Vector3 p, Biome biome)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			Heightmap val = Heightmap.FindHeightmap(p);
			if (Object.op_Implicit((Object)(object)val))
			{
				return (val.GetBiome(p) & biome) > 0;
			}
			return false;
		}

		private bool IsCultivated(Vector3 p)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Heightmap val = Heightmap.FindHeightmap(p);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val.IsCultivated(p);
			}
			return false;
		}

		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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsOwner() || !m_nview.IsValid() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			bool flag = false;
			int num = 0;
			int value = configMaxRetries.Value;
			while (GetQueueSize() > 0)
			{
				string queuedSeed = GetQueuedSeed();
				int queuedSeedCount = GetQueuedSeedCount();
				if (!seedPrefabMap.ContainsKey(queuedSeed))
				{
					Logger.LogWarning((object)("Key '" + queuedSeed + "' not found in seedPrefabMap"));
					DumpQueueDetails();
					Logger.LogWarning((object)"Shifting queue to remove invalid entry");
					ShiftQueueDown();
					return;
				}
				ItemConversion conversion = seedPrefabMap[queuedSeed];
				PlacementStatus placementStatus = TryPlacePlant(conversion, value);
				SetStatus(placementStatus);
				switch (placementStatus)
				{
				case PlacementStatus.Planting:
					num++;
					flag = true;
					goto IL_00d7;
				case PlacementStatus.WrongBiome:
					MoveToEndOfQueue(queuedSeed, queuedSeedCount, placementStatus);
					break;
				default:
					goto IL_00d7;
				case PlacementStatus.NoRoom:
					break;
				}
				break;
				IL_00d7:
				if (num >= configDispersionCount.Value)
				{
					break;
				}
			}
			if (flag)
			{
				m_disperseEffects.Create(((Component)this).transform.position, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f), ((Component)this).transform, GetRadius() / 5f, -1);
			}
		}

		private void MoveToEndOfQueue(string currentSeed, int currentCount, PlacementStatus status)
		{
			ShiftQueueDown();
			QueueSeed(currentSeed, currentCount, status);
		}

		private bool HasGrowSpace(Vector3 position, float m_growRadius)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (m_spaceMask == 0)
			{
				m_spaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" });
			}
			Collider[] array = Physics.OverlapSphere(position, m_growRadius + 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");
		}

		private int GetCurrentCount(string seedName)
		{
			return m_nview.GetZDO().GetInt(seedName, 0);
		}

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

		private 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);
		}

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

		private 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()
		{
			if (GetQueueSize() <= 0)
			{
				Logger.LogWarning((object)"Tried to remove a seed when none are queued");
				DumpQueueDetails();
				return;
			}
			int queuedSeedCount = GetQueuedSeedCount();
			if (queuedSeedCount > 1)
			{
				SetQueueSeedCount(0, queuedSeedCount - 1);
			}
			else
			{
				ShiftQueueDown();
			}
			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();
			if (GetQueuedSeed(queueSize - 1) == 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 (m_nview.IsOwner())
			{
				newRadius = Mathf.Clamp(newRadius, 2f, configMaxRadius.Value);
				m_nview.GetZDO().Set("radius", newRadius);
			}
			UpdateVisuals();
		}

		private void RPC_SetWidth(long sender, float newWidth)
		{
			if (m_nview.IsOwner())
			{
				newWidth = Mathf.Clamp(newWidth, 2f, configMaxRadius.Value);
				m_nview.GetZDO().Set("width", newWidth);
			}
			UpdateVisuals();
		}

		private void RPC_SetLength(long sender, float newLength)
		{
			if (m_nview.IsOwner())
			{
				newLength = Mathf.Clamp(newLength, 2f, configMaxRadius.Value);
				m_nview.GetZDO().Set("length", newLength);
			}
			UpdateVisuals();
		}

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

		private void RPC_AddSeed(long sender, string seedName, int amount)
		{
			if (m_nview.IsOwner())
			{
				QueueSeed(seedName, amount);
			}
		}

		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();
				}
				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", "");
		}

		internal static void SettingsUpdated()
		{
			SeedTotem[] array = Object.FindObjectsOfType<SeedTotem>();
			foreach (SeedTotem obj in array)
			{
				obj.UpdateVisuals();
				((MonoBehaviour)obj).CancelInvoke("DisperseSeeds");
				((MonoBehaviour)obj).InvokeRepeating("DisperseSeeds", 1f, configDispersionTime.Value);
			}
		}

		public DestructibleType GetDestructibleType()
		{
			return (DestructibleType)1;
		}
	}
	[BepInPlugin("marcopogo.SeedTotem", "Seed Totem", "4.3.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class SeedTotemMod : BaseUnityPlugin
	{
		public enum PieceLocation
		{
			Hammer,
			Cultivator
		}

		public const string PluginGUID = "marcopogo.SeedTotem";

		public const string PluginName = "Seed Totem";

		public const string PluginVersion = "4.3.3";

		public ConfigEntry<int> nexusID;

		private SeedTotemPrefabConfig seedTotemPrefabConfig;

		private Harmony harmony;

		public void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			harmony = new Harmony("marcopogo.SeedTotem");
			harmony.PatchAll();
			WearNTear.Damage += new hook_Damage(SeedTotem.OnDamage);
			CreateConfiguration();
			PrefabManager.OnVanillaPrefabsAvailable += AddCustomPrefabs;
			SeedTotem.configGlowColor.SettingChanged += SettingsChanged;
			SeedTotem.configLightColor.SettingChanged += SettingsChanged;
			SeedTotem.configLightIntensity.SettingChanged += SettingsChanged;
			SeedTotem.configFlareColor.SettingChanged += SettingsChanged;
			SeedTotem.configFlareSize.SettingChanged += SettingsChanged;
			SeedTotemPrefabConfig.configLocation.SettingChanged += UpdatePieceLocation;
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
		}

		private void CreateConfiguration()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//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_010e: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Expected O, but got Unknown
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			//IL_0228: 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_0235: 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_0263: 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_0270: Expected O, but got Unknown
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Expected O, but got Unknown
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Expected O, but got Unknown
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Expected O, but got Unknown
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Expected O, but got Unknown
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Expected O, but got Unknown
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Expected O, but got Unknown
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Expected O, but got Unknown
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Expected O, but got Unknown
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Expected O, but got Unknown
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Expected O, but got Unknown
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Expected O, but got Unknown
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b4: Expected O, but got Unknown
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_0551: Unknown result type (might be due to invalid IL or missing references)
			//IL_057b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f2: Expected O, but got Unknown
			SeedTotem.configMaxRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "Max Dispersion Radius", 20f, new ConfigDescription("Max dispersion radius of the Seed totem.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 64f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configDefaultRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "Default Dispersion Radius", 5f, new ConfigDescription("Default dispersion radius of the Seed totem.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, SeedTotem.configMaxRadius.Value), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configDispersionTime = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "Dispersion time", 10f, new ConfigDescription("Time (in seconds) between each dispersion (low values can cause lag)", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "Space requirement margin", 0.1f, new ConfigDescription("Extra distance to make sure plants have enough space", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configDispersionCount = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Dispersion count", 5, new ConfigDescription("Maximum number of plants to place when dispersing (high values can cause lag)", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configMaxRetries = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Max retries", 8, new ConfigDescription("Maximum number of placement tests on each dispersion (high values can cause lag)", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configHarvestOnHit = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Harvest on hit", true, new ConfigDescription("Should the Seed totem send out a wave to pick all pickables in radius when hit?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configAdminOnlyRadius = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Only admin can change radius", true, new ConfigDescription("Should only admins be able to change the radius of individual Seed totems?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configCheckCultivated = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Check for cultivated ground", true, new ConfigDescription("Should the Seed totem also check for cultivated land?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configCheckBiome = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Check for correct biome", true, new ConfigDescription("Should the Seed totem also check for the correct biome?", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotemPrefabConfig.configRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "Seed totem requirements", "FineWood:5,GreydwarfEye:5,SurtlingCore:1,AncientSeed:1", new ConfigDescription("Requirements to build the Seed totem", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			AutoFieldPrefabConfig.configRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "Advanced seed totem requirements", "FineWood:10,GreydwarfEye:10,SurtlingCore:2,AncientSeed:1", new ConfigDescription("Requirements to build the Advanced seed totem", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configMaxSeeds = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Max seeds in totem (0 is no limit)", 0, new ConfigDescription("Maximum number of seeds in each totem, 0 is no limit", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			SeedTotem.configShowQueue = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Show queue", true, new ConfigDescription("Show the current queue on hover", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configGlowColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Graphical", "Glow lines color", new Color(0f, 0.8f, 0f, 1f), new ConfigDescription("Color of the glowing lines on the Seed totem", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configLightColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Graphical", "Glow light color", new Color(0f, 0.8f, 0f, 0.05f), new ConfigDescription("Color of the light from the Seed totem", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configLightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Graphical", "Glow light intensity", 3f, new ConfigDescription("Intensity of the light flare from the Seed totem", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configFlareColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Graphical", "Glow flare color", new Color(0f, 0.8f, 0f, 0.1f), new ConfigDescription("Color of the light flare from the Seed totem", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configFlareSize = ((BaseUnityPlugin)this).Config.Bind<float>("Graphical", "Glow flare size", 3f, new ConfigDescription("Size of the light flare from the Seed totem", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configRadiusChange = ((BaseUnityPlugin)this).Config.Bind<float>("Input", "Radius size change for each keypress", 1f, new ConfigDescription("How much the radius will change for each keypress", (AcceptableValueBase)null, Array.Empty<object>()));
			SeedTotem.configRadiusIncrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Increment seed totem radius", new KeyboardShortcut((KeyCode)270, Array.Empty<KeyCode>()), (ConfigDescription)null);
			SeedTotem.configRadiusDecrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Decrement seed totem radius", new KeyboardShortcut((KeyCode)269, Array.Empty<KeyCode>()), (ConfigDescription)null);
			SeedTotem.configWidthIncrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Increment seed totem width", new KeyboardShortcut((KeyCode)275, Array.Empty<KeyCode>()), (ConfigDescription)null);
			SeedTotem.configWidthDecrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Decrement seed totem width", new KeyboardShortcut((KeyCode)276, Array.Empty<KeyCode>()), (ConfigDescription)null);
			SeedTotem.configLengthIncrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Increment seed totem length", new KeyboardShortcut((KeyCode)273, Array.Empty<KeyCode>()), (ConfigDescription)null);
			SeedTotem.configLengthDecrementButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Decrement seed totem length", new KeyboardShortcut((KeyCode)274, Array.Empty<KeyCode>()), (ConfigDescription)null);
			nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 876, new ConfigDescription("Nexus mod ID for updates", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[1] { 876 }), Array.Empty<object>()));
			SeedTotemPrefabConfig.configLocation = ((BaseUnityPlugin)this).Config.Bind<PieceLocation>("UI", "Build menu", PieceLocation.Hammer, "In which build menu is the Seed totem located");
		}

		private void OnPiecesRegistered()
		{
			seedTotemPrefabConfig.UpdatePieceLocation();
		}

		public void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void AddCustomPrefabs()
		{
			AssetBundle val = AssetUtils.LoadAssetBundleFromResources("seedtotem", typeof(SeedTotemMod).Assembly);
			try
			{
				seedTotemPrefabConfig = new SeedTotemPrefabConfig();
				GameObject prefab = PrefabManager.Instance.CreateClonedPrefab("SeedTotem", "guard_stone");
				seedTotemPrefabConfig.UpdateCopiedPrefab(val, prefab);
				new AutoFieldPrefabConfig().UpdateCopiedPrefab(val);
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Error while adding cloned item: {arg}");
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= AddCustomPrefabs;
				if (val != null)
				{
					val.Unload(false);
				}
			}
		}

		private void UpdatePieceLocation(object sender, EventArgs e)
		{
			seedTotemPrefabConfig.UpdatePieceLocation();
		}

		private void SettingsChanged(object sender, EventArgs e)
		{
			SeedTotem.SettingsUpdated();
		}

		public static string GetAssetPath(string assetName, bool isDirectory = false)
		{
			string text = Path.Combine(Paths.PluginPath, "SeedTotem", assetName);
			if (isDirectory)
			{
				if (!Directory.Exists(text))
				{
					text = Path.Combine(Path.GetDirectoryName(typeof(SeedTotemMod).Assembly.Location), assetName);
					if (!Directory.Exists(text))
					{
						Logger.LogWarning((object)("Could not find directory (" + assetName + ")."));
						return null;
					}
				}
				return text;
			}
			if (!File.Exists(text))
			{
				text = Path.Combine(Path.GetDirectoryName(typeof(SeedTotemMod).Assembly.Location), assetName);
				if (!File.Exists(text))
				{
					Logger.LogWarning((object)("Could not find asset (" + assetName + ")."));
					return null;
				}
			}
			return text;
		}

		public static RequirementConfig[] ParseRequirements(string prefabName, ConfigEntry<string> config)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			string[] array = config.Value.Split(new char[1] { ',' });
			if (array.Length > 4)
			{
				Logger.LogWarning((object)("More than 4 ingredients defined for $" + prefabName + ", this is likely to cause issues."));
			}
			RequirementConfig[] array2 = (RequirementConfig[])(object)new RequirementConfig[array.Length];
			int num = 0;
			string[] array3 = array;
			for (int i = 0; i < array3.Length; i++)
			{
				string[] array4 = array3[i].Split(new char[1] { ':' });
				string item = array4[0];
				array2[num++] = new RequirementConfig
				{
					Item = item,
					Amount = int.Parse(array4[1]),
					Recover = true
				};
			}
			return array2;
		}
	}
	internal class AutoFieldPrefabConfig
	{
		private const string localizationName = "seed_totem";

		public const string ravenTopic = "$tutorial_seed_totem_topic";

		public const string ravenText = "$tutorial_seed_totem_text";

		public const string ravenLabel = "$tutorial_seed_totem_label";

		public const string requirementsFile = "seed-totem-custom-requirements.json";

		public const string prefabName = "piece_seed_totem_auto_field";

		internal static ConfigEntry<string> configRecipe;

		private GameObject currentPiece;

		public void UpdateCopiedPrefab(AssetBundle assetBundle)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00c6: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = assetBundle.LoadAsset<GameObject>("piece_seed_totem_auto_field");
			Sprite autoFieldIcon = assetBundle.LoadAsset<Sprite>("auto_field_icon");
			KitbashManager instance = KitbashManager.Instance;
			KitbashConfig val2 = new KitbashConfig();
			val2.Layer = "piece";
			val2.FixReferences = true;
			List<KitbashSourceConfig> list = new List<KitbashSourceConfig>
			{
				new KitbashSourceConfig
				{
					Name = "default",
					TargetParentPath = "new",
					SourcePrefab = "guard_stone",
					SourcePath = "new/default",
					Scale = Vector3.one * 0.6f
				}
			};
			KitbashSourceConfig val3 = new KitbashSourceConfig();
			val3.Name = "hopper";
			val3.TargetParentPath = "new";
			val3.Position = new Vector3(0.29f, 1.12f, 1.26f);
			val3.Rotation = Quaternion.Euler(177.7f, -258.918f, -89.55298f);
			val3.Scale = Vector3.one;
			val3.SourcePrefab = "piece_spinningwheel";
			val3.SourcePath = "SpinningWheel_Destruction/SpinningWheel_Destruction_SpinningWheel_Broken.016";
			val3.Materials = new string[1] { "SpinningWheel_mat" };
			list.Add(val3);
			val3 = new KitbashSourceConfig();
			val3.Name = "gear_left";
			val3.TargetParentPath = "new/pivot_left";
			val3.Position = new Vector3(-0.383f, 0.8181f, -0.8028001f);
			val3.Rotation = Quaternion.Euler(0f, -90.00001f, -90.91601f);
			val3.Scale = Vector3.one * 0.68285f;
			val3.SourcePrefab = "piece_artisanstation";
			val3.SourcePath = "ArtisanTable_Destruction/ArtisanTable_Destruction.007_ArtisanTable.019";
			val3.Materials = new string[2] { "ArtisanTable_Mat", "TearChanal_mat" };
			list.Add(val3);
			val3 = new KitbashSourceConfig();
			val3.Name = "gear_right";
			val3.TargetParentPath = "new/pivot_right";
			val3.Position = new Vector3(-0.47695f, 0.5057697f, -0.7557001f);
			val3.Rotation = Quaternion.Euler(0f, -90.00001f, -90.91601f);
			val3.Scale = Vector3.one * 0.68285f;
			val3.SourcePrefab = "piece_artisanstation";
			val3.SourcePath = "ArtisanTable_Destruction/ArtisanTable_Destruction.006_ArtisanTable.018";
			val3.Materials = new string[2] { "ArtisanTable_Mat", "TearChanal_mat" };
			list.Add(val3);
			val2.KitbashSources = list;
			KitbashObject autoFieldKitbash = instance.AddKitbash(val, val2);
			KitbashObject obj = autoFieldKitbash;
			obj.OnKitbashApplied = (Action)Delegate.Combine(obj.OnKitbashApplied, (Action)delegate
			{
				//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_00d6: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0107: Expected O, but got Unknown
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Expected O, but got Unknown
				SeedTotem seedTotem = autoFieldKitbash.Prefab.AddComponent<SeedTotem>();
				seedTotem.m_shape = SeedTotem.FieldShape.Rectangle;
				GameObject val4 = Object.Instantiate<GameObject>(((Component)PrefabManager.Instance.GetPrefab("guard_stone").transform.Find("WayEffect")).gameObject, autoFieldKitbash.Prefab.transform);
				((Object)val4).name = "WayEffect";
				seedTotem.m_enabledEffect = val4;
				seedTotem.m_model = ((Component)((Component)seedTotem).transform.Find("new/default")).GetComponent<MeshRenderer>();
				seedTotem.UpdateVisuals();
				seedTotem.m_enabledEffect = val4;
				RectangleProjector rectangleProjector = ((Component)autoFieldKitbash.Prefab.transform.Find("AreaMarker")).gameObject.AddComponent<RectangleProjector>();
				seedTotem.m_rectangleProjector = rectangleProjector;
				PieceManager.Instance.AddPiece(new CustomPiece(autoFieldKitbash.Prefab, true, new PieceConfig
				{
					PieceTable = "Hammer",
					CraftingStation = "piece_artisanstation",
					Requirements = SeedTotemMod.ParseRequirements("piece_seed_totem_auto_field", configRecipe),
					Icon = autoFieldIcon
				}));
			});
		}

		internal void UpdatePieceLocation()
		{
			Logger.LogDebug((object)("Moving Seed totem to " + SeedTotemPrefabConfig.configLocation.Value));
			foreach (SeedTotemMod.PieceLocation value in Enum.GetValues(typeof(SeedTotemMod.PieceLocation)))
			{
				currentPiece = RemovePieceFromPieceTable(value, "piece_seed_totem_auto_field");
				if ((Object)(object)currentPiece != (Object)null)
				{
					break;
				}
			}
			if (SeedTotemPrefabConfig.configLocation.Value == SeedTotemMod.PieceLocation.Cultivator)
			{
				GetPieceTable(SeedTotemPrefabConfig.configLocation.Value).m_pieces.Insert(2, currentPiece);
			}
			else
			{
				GetPieceTable(SeedTotemPrefabConfig.configLocation.Value).m_pieces.Add(currentPiece);
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Player.m_localPlayer.AddKnownPiece(currentPiece.GetComponent<Piece>());
			}
		}

		private PieceTable GetPieceTable(SeedTotemMod.PieceLocation location)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			string text = $"_{location}PieceTable";
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(PieceTable));
			for (int i = 0; i < array.Length; i++)
			{
				PieceTable val = (PieceTable)array[i];
				string name = ((Object)((Component)val).gameObject).name;
				if (text == name)
				{
					return val;
				}
			}
			return null;
		}

		private GameObject RemovePieceFromPieceTable(SeedTotemMod.PieceLocation location, string pieceName)
		{
			Logger.LogDebug((object)("Removing " + pieceName + " from " + location));
			PieceTable pieceTable = GetPieceTable(location);
			int num = pieceTable.m_pieces.FindIndex((GameObject piece) => ((Object)piece).name == pieceName);
			if (num >= 0)
			{
				Logger.LogDebug((object)("Found Piece " + pieceName + " at position " + num));
				GameObject result = pieceTable.m_pieces[num];
				pieceTable.m_pieces.RemoveAt(num);
				return result;
			}
			return null;
		}
	}
	internal class SeedTotemPrefabConfig
	{
		public const string prefabName = "SeedTotem";

		private const string localizationName = "seed_totem";

		public const string ravenTopic = "$tutorial_seed_totem_topic";

		public const string ravenText = "$tutorial_seed_totem_text";

		public const string ravenLabel = "$tutorial_seed_totem_label";

		internal static ConfigEntry<SeedTotemMod.PieceLocation> configLocation;

		internal static ConfigEntry<string> configRecipe;

		private GameObject currentPiece;

		private GameObject Prefab;

		public void UpdateCopiedPrefab(AssetBundle assetBundle, GameObject Prefab)
		{
			this.Prefab = Prefab;
			Piece component = Prefab.GetComponent<Piece>();
			component.m_name = "$piece_seed_totem_name";
			component.m_description = "$piece_seed_totem_description";
			component.m_clipGround = true;
			component.m_groundPiece = true;
			component.m_groundOnly = true;
			component.m_noInWater = true;
			GuidePoint[] componentsInChildren = Prefab.GetComponentsInChildren<GuidePoint>();
			foreach (GuidePoint obj in componentsInChildren)
			{
				obj.m_text.m_key = "seed_totem";
				obj.m_text.m_topic = "$tutorial_seed_totem_topic";
				obj.m_text.m_text = "$tutorial_seed_totem_text";
				obj.m_text.m_label = "$tutorial_seed_totem_label";
			}
			SeedTotem seedTotem = Prefab.AddComponent<SeedTotem>();
			PrivateArea component2 = Prefab.GetComponent<PrivateArea>();
			if ((Object)(object)component2 != (Object)null)
			{
				Logger.LogDebug((object)"Converting PrivateArea to SeedTotem");
				seedTotem.CopyPrivateArea(component2);
				Logger.LogDebug((object)("Destroying redundant PrivateArea: " + (object)component2));
				Object.DestroyImmediate((Object)(object)component2);
			}
			RegisterPiece(assetBundle);
		}

		internal void RegisterPiece(AssetBundle assetBundle)
		{
			//IL_0016: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			Logger.LogInfo((object)"Registering Seed Totem Piece");
			PieceManager.Instance.AddPiece(new CustomPiece(Prefab, false, new PieceConfig
			{
				PieceTable = ((ConfigEntryBase)configLocation).GetSerializedValue(),
				Icon = assetBundle.LoadAsset<Sprite>("seed_totem_icon"),
				Description = "$piece_seed_totem_description",
				Requirements = SeedTotemMod.ParseRequirements("SeedTotem", configRecipe)
			}));
		}

		internal void UpdatePieceLocation()
		{
			Logger.LogInfo((object)("Moving Seed Totem to " + configLocation.Value));
			foreach (SeedTotemMod.PieceLocation value in Enum.GetValues(typeof(SeedTotemMod.PieceLocation)))
			{
				currentPiece = RemovePieceFromPieceTable(value, "SeedTotem");
				if ((Object)(object)currentPiece != (Object)null)
				{
					break;
				}
			}
			if (configLocation.Value == SeedTotemMod.PieceLocation.Cultivator)
			{
				GetPieceTable(configLocation.Value).m_pieces.Insert(2, currentPiece);
			}
			else
			{
				GetPieceTable(configLocation.Value).m_pieces.Add(currentPiece);
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Player.m_localPlayer.AddKnownPiece(currentPiece.GetComponent<Piece>());
			}
		}

		private PieceTable GetPieceTable(SeedTotemMod.PieceLocation location)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			string text = $"_{location}PieceTable";
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(PieceTable));
			for (int i = 0; i < array.Length; i++)
			{
				PieceTable val = (PieceTable)array[i];
				string name = ((Object)((Component)val).gameObject).name;
				if (text == name)
				{
					return val;
				}
			}
			return null;
		}

		private GameObject RemovePieceFromPieceTable(SeedTotemMod.PieceLocation location, string pieceName)
		{
			Logger.LogDebug((object)("Removing " + pieceName + " from " + location));
			PieceTable pieceTable = GetPieceTable(location);
			int num = pieceTable.m_pieces.FindIndex((GameObject piece) => ((Object)piece).name == pieceName);
			if (num >= 0)
			{
				Logger.LogDebug((object)("Found Piece " + pieceName + " at position " + num));
				GameObject result = pieceTable.m_pieces[num];
				pieceTable.m_pieces.RemoveAt(num);
				return result;
			}
			return null;
		}
	}
}
namespace SeedTotem.Utils
{
	internal class RectangleProjector : MonoBehaviour
	{
		public float cubesSpeed = 1f;

		public float m_length = 2f;

		public float m_width = 2f;

		private static GameObject _segment;

		private GameObject rootCube;

		private float cubesThickness = 0.15f;

		private float cubesHeight = 0.1f;

		private float cubesLength = 1f;

		private int cubesPerWidth;

		private int cubesPerLength;

		private float updatesPerSecond = 60f;

		private float cubesLength100;

		private float cubesWidth100;

		private float sideLengthHalved;

		private float sideWidthHalved;

		internal bool isRunning;

		private Transform parentNorth;

		private Transform parentEast;

		private Transform parentSouth;

		private Transform parentWest;

		private List<Transform> cubesNorth = new List<Transform>();

		private List<Transform> cubesEast = new List<Transform>();

		private List<Transform> cubesSouth = new List<Transform>();

		private List<Transform> cubesWest = new List<Transform>();

		private static GameObject SelectionSegment
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_segment))
				{
					_segment = Object.Instantiate<GameObject>(PrefabManager.Instance.GetPrefab("piece_workbench").GetComponentInChildren<CircleProjector>().m_prefab);
					_segment.SetActive(true);
				}
				return _segment;
			}
		}

		public void Start()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0045: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			rootCube = new GameObject("cube");
			GameObject obj = Object.Instantiate<GameObject>(SelectionSegment);
			obj.transform.SetParent(rootCube.transform);
			obj.transform.localScale = new Vector3(1f, 1f, 1f);
			obj.transform.localPosition = new Vector3(0f, 0f, -0.5f);
			rootCube.transform.localScale = new Vector3(cubesThickness, cubesHeight, cubesLength);
			rootCube.SetActive(true);
			RefreshStuff();
			StartProjecting();
		}

		private void OnEnable()
		{
			if (!isRunning && !((Object)(object)parentNorth == (Object)null))
			{
				isRunning = true;
				StartMarchingCubes();
			}
		}

		private void StartMarchingCubes()
		{
			((MonoBehaviour)this).StartCoroutine(AnimateElements(parentNorth, cubesNorth, length: false));
			((MonoBehaviour)this).StartCoroutine(AnimateElements(parentEast, cubesEast, length: true));
			((MonoBehaviour)this).StartCoroutine(AnimateElements(parentSouth, cubesSouth, length: false));
			((MonoBehaviour)this).StartCoroutine(AnimateElements(parentWest, cubesWest, length: true));
		}

		private void OnDisable()
		{
			isRunning = false;
		}

		public void StartProjecting()
		{
			if (!isRunning)
			{
				isRunning = true;
				parentNorth = CreateElements(0, cubesNorth);
				parentEast = CreateElements(90, cubesEast);
				parentSouth = CreateElements(180, cubesSouth);
				parentWest = CreateElements(270, cubesWest);
				StartMarchingCubes();
			}
		}

		public void StopProjecting()
		{
			if (isRunning)
			{
				isRunning = false;
				((MonoBehaviour)this).StopAllCoroutines();
				Object.Destroy((Object)(object)((Component)parentNorth).gameObject);
				Object.Destroy((Object)(object)((Component)parentEast).gameObject);
				Object.Destroy((Object)(object)((Component)parentSouth).gameObject);
				Object.Destroy((Object)(object)((Component)parentWest).gameObject);
				cubesNorth.Clear();
				cubesEast.Clear();
				cubesSouth.Clear();
				cubesWest.Clear();
			}
		}

		internal void RefreshStuff(bool force = false)
		{
			cubesPerLength = Mathf.FloorToInt(m_length / 2f);
			cubesPerWidth = Mathf.FloorToInt(m_width / 2f);
			cubesLength100 = m_length / (float)cubesPerLength;
			cubesWidth100 = m_width / (float)cubesPerWidth;
			sideLengthHalved = m_length / 2f;
			sideWidthHalved = m_width / 2f;
			if (isRunning && (force || cubesPerLength + 1 != cubesNorth.Count || cubesPerWidth + 1 != cubesEast.Count))
			{
				StopProjecting();
				StartProjecting();
			}
		}

		private Transform CreateElements(int rotation, List<Transform> cubes)
		{
			//IL_0007: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = new GameObject(rotation.ToString()).transform;
			((Component)transform).transform.position = ((Component)this).transform.position;
			((Component)transform).transform.rotation = ((Component)this).transform.rotation;
			((Component)transform).transform.RotateAround(((Component)this).transform.position, Vector3.up, (float)rotation);
			transform.SetParent(((Component)this).transform);
			int num = ((rotation % 180 == 0) ? cubesPerLength : cubesPerWidth);
			for (int i = 0; i < num + 1; i++)
			{
				cubes.Add(Object.Instantiate<GameObject>(rootCube, ((Component)this).transform.position, Quaternion.identity, transform).transform);
			}
			Transform transform2 = new GameObject("Start").transform;
			Transform transform3 = new GameObject("End").transform;
			transform2.SetParent(transform);
			transform3.SetParent(transform);
			for (int j = 0; j < cubes.Count; j++)
			{
				cubes[j].forward = transform.right;
			}
			return transform;
		}

		private IEnumerator AnimateElements(Transform cubeParent, List<Transform> cubes, bool length)
		{
			Transform a = cubeParent.Find("Start");
			Transform b = cubeParent.Find("End");
			int cubesPerSide = (length ? cubesPerLength : cubesPerWidth);
			float sideLength = (length ? m_length : m_width);
			float halfSideLength = (length ? sideLengthHalved : sideWidthHalved);
			float halfSideWidth = (length ? sideWidthHalved : sideLengthHalved);
			float cubes2 = (length ? cubesLength100 : cubesWidth100);
			while (true)
			{
				RefreshStuff();
				a.position = cubeParent.forward * (halfSideWidth - cubesThickness / 2f) - cubeParent.right * halfSideLength + cubeParent.position;
				b.position = cubeParent.forward * (halfSideWidth - cubesThickness / 2f) + cubeParent.right * halfSideLength + cubeParent.position;
				Vector3 val = b.position - a.position;
				for (int i = 0; i < cubes.Count; i++)
				{
					Transform val2 = cubes[i];
					((Component)val2).gameObject.SetActive(true);
					float num = (Time.time * cubesSpeed + sideLength / (float)cubesPerSide * (float)i) % (sideLength + cubes2);
					if (num < cubesLength)
					{
						val2.position = ((Vector3)(ref val)).normalized * num + a.position;
						val2.localScale = new Vector3(val2.localScale.x, val2.localScale.y, cubesLength - (cubesLength - num));
					}
					else if (num >= sideLength && num <= sideLength + cubesLength)
					{
						val2.position = ((Vector3)(ref val)).normalized * sideLength + a.position;
						val2.localScale = new Vector3(val2.localScale.x, val2.localScale.y, cubesLength - (num - sideLength));
					}
					else if (num >= sideLength && num >= sideLength + cubesLength)
					{
						((Component)val2).gameObject.SetActive(false);
					}
					else
					{
						val2.position = ((Vector3)(ref val)).normalized * num + a.position;
						val2.localScale = new Vector3(val2.localScale.x, val2.localScale.y, cubesLength);
					}
				}
				yield return (object)new WaitForSecondsRealtime(1f / updatesPerSecond);
			}
		}
	}
}