Decompiled source of SwmarlyValheimSeedTotem v4.3.13

plugins/SeedTotem/SeedTotem.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SeedTotem.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.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.4")]
[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.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
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
{
	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<SeedTotemMod.PieceLocation> configLocation;

		internal static ConfigEntry<string> configRecipe;

		private GameObject currentPiece;

		private static RequirementConfig[] ParseRequirements()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			string[] array = configRecipe.Value.Split(',');
			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(':');
				array2[num++] = new RequirementConfig
				{
					Item = array4[0],
					Amount = int.Parse(array4[1]),
					Recover = true
				};
			}
			return array2;
		}

		public void UpdateCopiedPrefab(AssetBundle assetBundle)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0066: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			Sprite icon = LoadAdvancedIcon(assetBundle.LoadAsset<Sprite>("seed_totem_icon"));
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("piece_seed_totem_auto_field", "SeedTotem");
			ConfigureAutoFieldPrefab(val, assetBundle);
			PieceManager.Instance.AddPiece(new CustomPiece(val, true, new PieceConfig
			{
				PieceTable = "Hammer",
				CraftingStation = "piece_artisanstation",
				Requirements = ParseRequirements(),
				Icon = icon
			}));
		}

		private static void ConfigureAutoFieldPrefab(GameObject autoFieldPrefab, AssetBundle assetBundle)
		{
			if (!Object.op_Implicit((Object)(object)autoFieldPrefab))
			{
				Logger.LogError((object)"Could not prepare the Advanced Seed Totem: normal Seed Totem clone was not created");
				return;
			}
			SeedTotem seedTotem = autoFieldPrefab.GetComponent<SeedTotem>() ?? autoFieldPrefab.AddComponent<SeedTotem>();
			seedTotem.m_shape = SeedTotem.FieldShape.Rectangle;
			seedTotem.m_pinkGlow = true;
			Piece component = autoFieldPrefab.GetComponent<Piece>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_name = "$piece_seed_totem_auto_field_name";
				component.m_description = "$piece_seed_totem_auto_field_description";
			}
			GuidePoint[] componentsInChildren = autoFieldPrefab.GetComponentsInChildren<GuidePoint>(true);
			foreach (GuidePoint obj in componentsInChildren)
			{
				obj.m_text.m_key = "auto_field";
				obj.m_text.m_topic = "$tutorial_auto_field_topic";
				obj.m_text.m_text = "$tutorial_auto_field_text";
				obj.m_text.m_label = "$tutorial_auto_field_label";
			}
			Transform val = autoFieldPrefab.transform.Find("AreaMarker");
			if (Object.op_Implicit((Object)(object)val))
			{
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
			}
			GameObject val2 = assetBundle.LoadAsset<GameObject>("piece_seed_totem_auto_field");
			Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.transform.Find("AreaMarker") : null);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				Logger.LogError((object)"Could not prepare the Advanced Seed Totem rectangle marker: AreaMarker is missing");
				return;
			}
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, autoFieldPrefab.transform);
			((Object)val4).name = "AreaMarker";
			RectangleProjector rectangleProjector = val4.GetComponent<RectangleProjector>() ?? val4.AddComponent<RectangleProjector>();
			seedTotem.m_rectangleProjector = rectangleProjector;
			Transform obj2 = autoFieldPrefab.transform.Find("new/default");
			seedTotem.m_model = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshRenderer>() : null);
			SetLayerRecursively(val4, LayerMask.NameToLayer("piece"));
			Logger.LogInfo((object)("Advanced Seed Totem uses normal model: " + (Object.op_Implicit((Object)(object)seedTotem.m_model) ? "renderer found" : "renderer missing")));
		}

		private static Sprite LoadAdvancedIcon(Sprite fallback)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0060: 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)
			string assetPath = SeedTotemMod.GetAssetPath("Icons/advanced_seed_totem_icon.png");
			if (assetPath != null)
			{
				try
				{
					byte[] array = File.ReadAllBytes(assetPath);
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, false);
					if (ImageConversion.LoadImage(val, array, true))
					{
						((Object)val).name = "advanced_seed_totem_icon";
						((Texture)val).filterMode = (FilterMode)1;
						((Texture)val).wrapMode = (TextureWrapMode)1;
						return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 64f);
					}
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("Could not load the Advanced Seed Totem icon: " + ex.Message));
				}
			}
			return fallback;
		}

		private static GameObject ClonePart(Transform source, Transform parent, string name, Vector3 position, Quaternion rotation, Vector3 scale)
		{
			//IL_002b: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)parent))
			{
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(((Component)source).gameObject, parent);
			((Object)obj).name = name;
			obj.transform.localPosition = position;
			obj.transform.localRotation = rotation;
			obj.transform.localScale = scale;
			return obj;
		}

		private static void SetLayerRecursively(GameObject root, int layer)
		{
			if (Object.op_Implicit((Object)(object)root) && layer >= 0)
			{
				Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = layer;
				}
			}
		}

		internal void UpdatePieceLocation()
		{
			Logger.LogDebug((object)("Moving Seed totem to " + 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 (configLocation.Value == SeedTotemMod.PieceLocation.Cultivator)
			{
				GetPieceTable(configLocation.Value).m_pieces.Insert(2, currentPiece);
			}
			else
			{
				GetPieceTable(configLocation.Value).m_pieces.Add(currentPiece);
			}
		}

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

		[HarmonyPatch(typeof(WearNTear), "Damage")]
		private static class WearNTearDamagePatch
		{
			private static bool Prefix(WearNTear __instance, HitData hit)
			{
				SeedTotem seedTotem = default(SeedTotem);
				if (hit.GetTotalDamage() > 0f && ((Component)__instance).TryGetComponent<SeedTotem>(ref seedTotem))
				{
					SeedTotem seedTotem2 = seedTotem;
					Character attacker = hit.GetAttacker();
					seedTotem2.OnDamaged((Player)(object)((attacker is Player) ? attacker : null));
					return false;
				}
				return true;
			}
		}

		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;

		internal bool m_pinkGlow;

		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 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_pinkGlow = true;
				Transform val = ((Component)this).transform.Find("AreaMarker");
				m_rectangleProjector = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<RectangleProjector>() : null);
				m_animator = ((Component)this).GetComponent<Animator>();
				Transform obj = ((Component)this).transform.Find("new/pivot_left/gear_left");
				m_gearLeft = ((obj != null) ? ((Component)obj).GetComponent<MeshRenderer>() : null);
				Transform obj2 = ((Component)this).transform.Find("new/pivot_right/gear_right");
				m_gearRight = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshRenderer>() : null);
			}
			if (!Object.op_Implicit((Object)(object)m_enabledEffect))
			{
				Transform val2 = ((Component)this).transform.Find("WayEffect");
				m_enabledEffect = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).gameObject : null);
			}
			if (!Object.op_Implicit((Object)(object)m_model))
			{
				Transform obj3 = ((Component)this).transform.Find("new/default");
				m_model = ((obj3 != null) ? ((Component)obj3).GetComponent<MeshRenderer>() : null);
			}
			if (!Object.op_Implicit((Object)(object)m_areaMarker))
			{
				Transform obj4 = ((Component)this).transform.Find("AreaMarker");
				m_areaMarker = ((obj4 != null) ? ((Component)obj4).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;
			try
			{
				PieceManager instance = PieceManager.Instance;
				PieceTable val = ((instance != null) ? instance.GetPieceTable("_CultivatorPieceTable") : null);
				if ((Object)(object)val == (Object)null || val.m_pieces == null)
				{
					Logger.LogWarning((object)"Cultivator piece table is not available yet; no seed types were registered.");
					return;
				}
				foreach (GameObject piece in val.m_pieces)
				{
					if (!Object.op_Implicit((Object)(object)piece))
					{
						continue;
					}
					Plant component = piece.GetComponent<Plant>();
					Piece component2 = piece.GetComponent<Piece>();
					if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || component2.m_resources == null || component2.m_resources.Length != 1)
					{
						if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2) && component2.m_resources != null && component2.m_resources.Length > 1)
						{
							Logger.LogWarning((object)("  Multiple seeds required for " + component.m_name + "? Skipping"));
						}
						continue;
					}
					ItemDrop resItem = component2.m_resources[0].m_resItem;
					if (Object.op_Implicit((Object)(object)resItem) && resItem.m_itemData != null && resItem.m_itemData.m_shared != null)
					{
						string name = resItem.m_itemData.m_shared.m_name;
						if (!seedPrefabMap.ContainsKey(name))
						{
							Logger.LogDebug((object)("Looking for Prefab of " + name + " -> " + ((Object)((Component)resItem).gameObject).name));
							ItemConversion itemConversion = new ItemConversion
							{
								seedDrop = resItem,
								plantPiece = component2,
								plant = component
							};
							Logger.LogDebug((object)("Registering seed type: " + itemConversion));
							seedPrefabMap.Add(name, itemConversion);
						}
					}
				}
			}
			finally
			{
				scanningCultivator = false;
			}
		}

		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 != FieldShape.Circle && 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			Logger.LogDebug((object)("Updating color of SeedTotem at " + ((object)((Component)this).transform.position/*cast due to .constrained prefix*/).ToString()));
			if (!Object.op_Implicit((Object)(object)m_model) || !Object.op_Implicit((Object)(object)m_enabledEffect))
			{
				Logger.LogWarning((object)("Seed Totem model or effect is missing on " + ((Object)this).name));
				return;
			}
			Material[] materials = ((Renderer)m_model).materials;
			Color val = (Color)(m_pinkGlow ? new Color(1f, 0.05f, 0.65f, 1f) : configGlowColor.Value);
			Material[] array = materials;
			foreach (Material val2 in array)
			{
				string value = "Guardstone_OdenGlow_mat";
				if (((Object)val2).name.StartsWith(value))
				{
					val2.SetColor("_EmissionColor", val);
				}
			}
			EffectData[] effectPrefabs = m_disperseEffects.m_effectPrefabs;
			for (int i = 0; i < effectPrefabs.Length; i++)
			{
				ColorOverLifetimeModule colorOverLifetime = effectPrefabs[i].m_prefab.GetComponent<ParticleSystem>().colorOverLifetime;
				Gradient val3 = new Gradient();
				val3.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
				{
					new GradientColorKey(val, 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(val3);
			}
			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(val, val * 0.2f);
			Light component2 = ((Component)m_enabledEffect.transform.Find("Point light")).gameObject.GetComponent<Light>();
			component2.color = (Color)(m_pinkGlow ? new Color(1f, 0.05f, 0.65f, 1f) : 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((Color)(m_pinkGlow ? new Color(1f, 0.05f, 0.65f, 1f) : 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)
		{
			if (Object.op_Implicit((Object)(object)m_enabledEffect))
			{
				m_enabledEffect.SetActive(active);
			}
			if (Object.op_Implicit((Object)(object)m_animator))
			{
				((Behaviour)m_animator).enabled = active;
				if (Object.op_Implicit((Object)(object)m_gearLeft))
				{
					SetEmission(((Renderer)m_gearLeft).materials, active);
				}
				if (Object.op_Implicit((Object)(object)m_gearRight))
				{
					SetEmission(((Renderer)m_gearRight).materials, active);
				}
			}
			if (Object.op_Implicit((Object)(object)m_model))
			{
				SetEmission(((Renderer)m_model).materials, active);
			}
		}

		private static void SetEmission(Material[] materials, bool active)
		{
			foreach (Material val in materials)
			{
				if (Object.op_Implicit((Object)(object)val) && ((Object)val).name.StartsWith("Guardstone_OdenGlow_mat"))
				{
					if (active)
					{
						val.EnableKeyword("_EMISSION");
					}
					else
					{
						val.DisableKeyword("_EMISSION");
					}
				}
			}
		}

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

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

		public float GetHoverOffset()
		{
			return 0f;
		}

		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, false);
				return false;
			}
			if (configMaxSeeds.Value > 0 && GetTotalSeedCount() >= configMaxSeeds.Value)
			{
				((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false);
				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, false);
			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, false);
						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, false);
				return true;
			}
			string text = ((!(restrict == "")) ? restrict : "$message_seed_totem_seed_generic_plural");
			((Character)user).Message((MessageType)2, "$msg_donthaveany " + text, 0, (Sprite)null, false);
			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, false);
					return false;
				}
				text = "";
				((Character)user).Message((MessageType)2, "$message_seed_totem_unrestricted", 0, (Sprite)null, false);
			}
			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_0176: 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_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, default(ZDOID));
				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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			Heightmap val = Heightmap.FindHeightmap(p);
			if (Object.op_Implicit((Object)(object)val))
			{
				return (val.GetBiome(p, 0.02f, false) & 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)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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, default(ZDOID));
			}
		}

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

		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 = 1; i < queueSize; i++)
			{
				int num = i - 1;
				string text = m_nview.GetZDO().GetString("item" + i, "");
				m_nview.GetZDO().Set("item" + num, text);
				int num2 = m_nview.GetZDO().GetInt("item" + i + "count", 0);
				m_nview.GetZDO().Set("item" + num + "count", num2);
				int num3 = m_nview.GetZDO().GetInt("item" + i + "status", 0);
				m_nview.GetZDO().Set("item" + num + "status", num3);
			}
			int num4 = queueSize - 1;
			m_nview.GetZDO().Set("item" + num4, "");
			m_nview.GetZDO().Set("item" + num4 + "count", 0);
			m_nview.GetZDO().Set("item" + num4 + "status", 0);
			m_nview.GetZDO().Set("queued", num4);
		}

		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();
			bool flag = string.IsNullOrEmpty(restrict);
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < queueSize; i++)
			{
				string queuedSeed = GetQueuedSeed(i);
				int queuedSeedCount = GetQueuedSeedCount(i);
				if (!string.IsNullOrEmpty(queuedSeed) && queuedSeedCount > 0 && (flag || queuedSeed == restrict))
				{
					PlacementStatus queuedStatus = GetQueuedStatus(i);
					m_nview.GetZDO().Set("item" + num2, queuedSeed);
					m_nview.GetZDO().Set("item" + num2 + "count", queuedSeedCount);
					m_nview.GetZDO().Set("item" + num2 + "status", (int)queuedStatus);
					num += queuedSeedCount;
					num2++;
				}
				else
				{
					DropSeeds(queuedSeed, queuedSeedCount);
				}
			}
			for (int j = num2; j < queueSize; j++)
			{
				m_nview.GetZDO().Set("item" + j, "");
				m_nview.GetZDO().Set("item" + j + "count", 0);
				m_nview.GetZDO().Set("item" + j + "status", 0);
			}
			m_nview.GetZDO().Set("queued", num2);
			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(i);
			}
			SetTotalSeedCount(num);
		}

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

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

		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", "Swmarly Valheim Seed Totem", "4.3.13")]
	[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 = "Swmarly Valheim Seed Totem";

		public const string PluginVersion = "4.3.13";

		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
			harmony = new Harmony("marcopogo.SeedTotem");
			harmony.PatchAll();
			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)
			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);
			SeedTotemPrefabConfig.configLocation = ((BaseUnityPlugin)this).Config.Bind<PieceLocation>("UI", "Build menu", PieceLocation.Hammer, "In which build menu is the Seed totem located");
			RemoveObsoleteConfiguration();
		}

		private void RemoveObsoleteConfiguration()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			ConfigDefinition val = new ConfigDefinition("General", "NexusID");
			((BaseUnityPlugin)this).Config.Remove(val);
			(typeof(ConfigFile).GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(((BaseUnityPlugin)this).Config, null) as IDictionary)?.Remove(val);
			((BaseUnityPlugin)this).Config.Save();
		}

		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;
		}
	}
	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";

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

		internal static ConfigEntry<SeedTotemMod.PieceLocation> configLocation;

		internal static ConfigEntry<string> configRecipe;

		private GameObject currentPiece;

		private GameObject Prefab;

		private static RequirementConfig[] ParseRequirements()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			string[] array = configRecipe.Value.Split(',');
			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(':');
				array2[num++] = new RequirementConfig
				{
					Item = array4[0],
					Amount = int.Parse(array4[1]),
					Recover = true
				};
			}
			return array2;
		}

		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_0057: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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 = ParseRequirements()
			}));
		}

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

		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)
		{
			m_length = Mathf.Max(2f, m_length);
			m_width = Mathf.Max(2f, m_width);
			cubesPerLength = Mathf.Max(1, Mathf.FloorToInt(m_length / 2f));
			cubesPerWidth = Mathf.Max(1, 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 cubes100 = (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 + cubes100);
					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);
			}
		}
	}
}