Decompiled source of PlantEverything v1.16.5

Advize_PlantEverything.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Advize_PlantEverything.Configuration;
using Advize_PlantEverything.Framework;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using ServerSync;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;

[assembly: AssemblyFileVersion("1.16.5.0")]
[assembly: Guid("85f3bb36-d51d-4e6c-a523-feb593b3156f")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyProduct("Valheim Game Modification")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("Advize_PlantEverything")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.16.5.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<c75b9b4b-5050-43e8-a4ec-9c55df45e18a>Embedded]
	internal sealed class <c75b9b4b-5050-43e8-a4ec-9c55df45e18a>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[<c75b9b4b-5050-43e8-a4ec-9c55df45e18a>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <2c5aa66a-a271-4227-838c-a746fbb80658>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <2c5aa66a-a271-4227-838c-a746fbb80658>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <2c5aa66a-a271-4227-838c-a746fbb80658>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<c75b9b4b-5050-43e8-a4ec-9c55df45e18a>Embedded]
	[CompilerGenerated]
	internal sealed class <77b86206-05ce-438b-a28e-c1d9601e8658>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <77b86206-05ce-438b-a28e-c1d9601e8658>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Advize_PlantEverything
{
	[BepInPlugin("advize.PlantEverything", "PlantEverything", "1.16.5")]
	public class PlantEverything : BaseUnityPlugin
	{
		[HarmonyPatch]
		public static class ModInitPatches
		{
			[HarmonyPatch(typeof(ObjectDB), "Awake")]
			public static void Postfix()
			{
				Dbgl("ObjectDBAwake", forceLog: false, (LogLevel)16);
				InitPrefabRefs();
			}

			[HarmonyPatch(typeof(ZNetScene), "Awake")]
			public static void Postfix(ZNetScene __instance)
			{
				Dbgl("ZNetSceneAwake", forceLog: false, (LogLevel)16);
				FinalInit(__instance);
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			[HarmonyPatch(typeof(ZNetScene), "Awake")]
			public static void LastPostfix(ZNetScene __instance)
			{
				if (resolveMissingReferences)
				{
					Dbgl("ZNetSceneAwake2", forceLog: false, (LogLevel)16);
					Dbgl("Performing final attempt to resolve missing references for configured ExtraResources", forceLog: true, (LogLevel)16);
					resolveMissingReferences = false;
					if (InitExtraResourceRefs(__instance, logErrors: true))
					{
						Dbgl("One or more missing references for configured ExtraResources were successfully resolved", forceLog: true, (LogLevel)16);
						PieceSettingChanged(null, null);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "CheckCanRemovePiece")]
		public static class PlayerCheckCanRemovePiece
		{
			private static bool Prefix(Piece piece, ref bool __result)
			{
				if (IsModdedPrefab((Component)(object)piece))
				{
					return __result = false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		public static class PieceDropResources
		{
			internal static void Prefix(Piece __instance, out Requirement[] __state)
			{
				__state = null;
				Pickable pickable = default(Pickable);
				if (config.RecoverResources && IsModdedPrefab((Component)(object)__instance) && ((Component)__instance).TryGetComponent<Pickable>(ref pickable))
				{
					__state = __instance.m_resources;
					__instance.m_resources = RemovePickableDropFromRequirements(__instance.m_resources, pickable);
				}
			}

			internal static void Postfix(Piece __instance, Requirement[] __state)
			{
				if (__state != null)
				{
					__instance.m_resources = __state;
				}
			}

			private static Requirement[] RemovePickableDropFromRequirements(Requirement[] requirements, Pickable pickable)
			{
				ItemData itemData = pickable.m_itemPrefab.GetComponent<ItemDrop>().m_itemData;
				for (int i = 0; i < requirements.Length; i++)
				{
					Requirement val = requirements[i];
					if (val.m_resItem.m_itemData.m_shared.m_name == itemData.m_shared.m_name)
					{
						Requirement[] array = (Requirement[])(object)new Requirement[requirements.Length];
						requirements.CopyTo(array, 0);
						int scaledPickableDropAmount = GetScaledPickableDropAmount(pickable);
						array[i].m_amount = Mathf.Clamp(val.m_amount - scaledPickableDropAmount, 0, val.m_amount);
						return array;
					}
				}
				return requirements;
			}

			private static int GetScaledPickableDropAmount(Pickable pickable)
			{
				if (!pickable.m_dontScale)
				{
					return Mathf.Max(pickable.m_minAmountScaled, Game.instance.ScaleDrops(pickable.m_itemPrefab, pickable.m_amount));
				}
				return pickable.m_amount;
			}
		}

		[HarmonyPatch(typeof(Player), "RemovePiece")]
		public static class PlayerRemovePiece
		{
			public static bool Prefix(Player __instance, ref bool __result)
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				if (((Humanoid)__instance).GetRightItem().m_shared.m_name == "$item_cultivator")
				{
					Transform transform = ((Component)GameCamera.instance).transform;
					RaycastHit val = default(RaycastHit);
					if (Physics.Raycast(transform.position, transform.forward, ref val, 50f, LayerMask.op_Implicit(GetRemovalMask())) && Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)__instance).m_eye.position) < __instance.m_maxPlaceDistance)
					{
						Piece componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>();
						if (IsModdedPrefab((Component)(object)componentInParent))
						{
							if (!CanRemove(componentInParent, __instance))
							{
								return false;
							}
							RemoveObject(componentInParent, __instance);
							__result = true;
						}
					}
					return false;
				}
				return true;
			}

			private static LayerMask GetRemovalMask()
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				return LayerMask.op_Implicit(LayerMask.GetMask(StaticContent.layersForPieceRemoval));
			}

			private static bool CanRemove(Piece piece, Player instance)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				bool flag = piece.m_canBeRemoved;
				if (flag && !PrivateArea.CheckAccess(((Component)piece).transform.position, 0f, true, false))
				{
					((Character)instance).Message((MessageType)2, "$msg_privatezone", 0, (Sprite)null);
					flag = false;
				}
				return flag;
			}

			private static void RemoveObject(Piece piece, Player player)
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				ZNetView component = ((Component)piece).GetComponent<ZNetView>();
				WearNTear component2 = ((Component)piece).GetComponent<WearNTear>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					player.m_removeEffects.Create(((Component)piece).transform.position, Quaternion.identity, (Transform)null, 1f, -1);
					component2.Remove();
				}
				else
				{
					component.ClaimOwnership();
					piece.DropResources();
					piece.m_placeEffect.Create(((Component)piece).transform.position, ((Component)piece).transform.rotation, (Transform)null, 1f, -1);
					if (Object.op_Implicit((Object)(object)((Component)piece).GetComponent<Pickable>()))
					{
						component.InvokeRPC("Pick", Array.Empty<object>());
					}
					ZNetScene.instance.Destroy(((Component)piece).gameObject);
				}
				player.FaceLookDirection();
				((Character)player).m_zanim.SetTrigger(((Humanoid)player).GetRightItem().m_shared.m_attack.m_attackAnimation);
			}
		}

		[HarmonyPatch(typeof(Piece), "SetCreator")]
		public static class PieceSetCreator
		{
			public static void Postfix(Piece __instance)
			{
				if (!IsModdedPrefabOrSapling(__instance))
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (config.ResourcesSpawnEmpty && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Pickable>()) && !__instance.m_name.Contains("Stone"))
				{
					component.InvokeRPC(ZNetView.Everybody, "SetPicked", new object[1] { true });
				}
				if (config.PlaceAnywhere)
				{
					StaticPhysics component2 = ((Component)__instance).GetComponent<StaticPhysics>();
					if (Object.op_Implicit((Object)(object)component2))
					{
						component2.m_fall = false;
						component.GetZDO().Set("pe_placeAnywhere", true);
					}
				}
			}
		}

		[HarmonyPatch]
		public static class CheckZDOPatches
		{
			[HarmonyPatch(typeof(Piece), "Awake")]
			public static void Postfix(Piece __instance)
			{
				CheckZDO((Component)(object)__instance);
			}

			[HarmonyPatch(typeof(TreeBase), "Awake")]
			public static void Postfix(TreeBase __instance)
			{
				CheckZDO((Component)(object)__instance);
			}

			public static void CheckZDO(Component instance)
			{
				ZNetView component = instance.GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.GetZDO() != null && component.GetZDO().GetBool("pe_placeAnywhere", false))
				{
					instance.GetComponent<StaticPhysics>().m_fall = false;
				}
			}
		}

		[HarmonyPatch(typeof(Plant), "HaveRoof")]
		public static class PlantHaveRoof
		{
			public static bool Prefix(Plant __instance, ref bool __result)
			{
				if ((!config.CropRequireSunlight && __instance.m_name.StartsWith("$piece_sapling")) || (config.PlaceAnywhere && IsModdedPrefabOrSapling(__instance)))
				{
					return __result = false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Plant), "HaveGrowSpace")]
		public static class PlantHaveGrowSpace
		{
			public static bool Prefix(Plant __instance, ref bool __result)
			{
				if ((!config.CropRequireGrowthSpace && __instance.m_name.StartsWith("$piece_sapling")) || (config.PlaceAnywhere && IsModdedPrefabOrSapling(__instance)))
				{
					__result = true;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Plant), "Grow")]
		public static class PlantGrow
		{
			private static readonly MethodInfo ModifyGrowMethod = AccessTools.Method(typeof(PlantGrow), "ModifyGrow", (Type[])null, (Type[])null);

			public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: 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_0022: Expected O, but got Unknown
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Expected O, but got Unknown
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Expected O, but got Unknown
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Expected O, but got Unknown
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Expected O, but got Unknown
				return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Stloc_3, (object)null, (string)null)
				}).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null)
				}).Advance(-1)
					.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
					{
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Ldloc_3, (object)null),
						new CodeInstruction(OpCodes.Call, (object)ModifyGrowMethod)
					})
					.InstructionEnumeration();
			}

			private static void ModifyGrow(Plant plant, TreeBase treeBase)
			{
				ZNetView val = ((plant != null) ? ((Component)plant).GetComponent<ZNetView>() : null);
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)treeBase))
				{
					Dbgl("ModifyGrow not executed, a reference is null", forceLog: true, (LogLevel)2);
				}
				else if (val.GetZDO().GetBool("pe_placeAnywhere", false))
				{
					StaticPhysics component = ((Component)treeBase).GetComponent<StaticPhysics>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.m_fall = false;
						((Component)treeBase).GetComponent<ZNetView>().GetZDO().Set("pe_placeAnywhere", true);
					}
				}
			}
		}

		[HarmonyPatch]
		public static class HoverTextPatches
		{
			[HarmonyPatch(typeof(Pickable), "GetHoverText")]
			public static void Postfix(Pickable __instance, ref string __result)
			{
				if (__instance.m_picked && config.EnablePickableTimers && __instance.m_nview.GetZDO() != null && __instance.m_respawnTimeMinutes != 0)
				{
					float growthTime = __instance.m_respawnTimeMinutes * 60;
					DateTime placedTime = new DateTime(__instance.m_nview.GetZDO().GetLong(ZDOVars.s_pickedTime, 0L));
					string text = FormatTimeString(growthTime, placedTime);
					__result = Localization.instance.Localize(__instance.GetHoverName()) + "\n" + text;
				}
			}

			[HarmonyPatch(typeof(Plant), "GetHoverText")]
			public static void Postfix(Plant __instance, ref string __result)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				if (config.EnablePlantTimers && (int)__instance.m_status == 0 && __instance.m_nview.GetZDO() != null)
				{
					float growTime = __instance.GetGrowTime();
					DateTime placedTime = new DateTime(__instance.m_nview.GetZDO().GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks));
					string text = FormatTimeString(growTime, placedTime);
					__result = __result + "\n" + text;
				}
			}

			public static string FormatTimeString(float growthTime, DateTime placedTime)
			{
				TimeSpan timeSpan = ZNet.instance.GetTime() - placedTime;
				TimeSpan timeSpan2 = TimeSpan.FromSeconds((double)growthTime - timeSpan.TotalSeconds);
				double num = (double)(growthTime / 60f) - timeSpan.TotalMinutes;
				double num2 = num / (double)(growthTime / 60f);
				int num3 = Math.Min((int)(timeSpan.TotalSeconds * 100.0 / (double)growthTime), 100);
				string text = "red";
				if (num2 < 0.0)
				{
					text = "#00FFFF";
				}
				else if (num2 < 0.25)
				{
					text = "#32CD32";
				}
				else if (num2 < 0.5)
				{
					text = "yellow";
				}
				else if (num2 < 0.75)
				{
					text = "orange";
				}
				string text2 = ((timeSpan2.Hours > 0) ? $"{timeSpan2.Hours:D2}h {timeSpan2.Minutes:D2}m {timeSpan2.Seconds:D2}s" : ((timeSpan2.Minutes <= 0) ? $"{timeSpan2.Seconds:D2}s" : $"{timeSpan2.Minutes:D2}m {timeSpan2.Seconds:D2}s"));
				if (!config.GrowthAsPercentage)
				{
					if (!(num < 0.0))
					{
						return "(Ready in <color=" + text + ">" + text2 + "</color>)";
					}
					return "(<color=" + text + ">Ready any second now</color>)";
				}
				return $"(<color={text}>{num3}%</color>)";
			}
		}

		[HarmonyPatch]
		public static class ShowPickableSpawnerPatches
		{
			[HarmonyPatch(typeof(Pickable), "Awake")]
			public static void Postfix(Pickable __instance)
			{
				TogglePickedMesh(__instance, __instance.m_picked);
			}

			[HarmonyPatch(typeof(Pickable), "SetPicked")]
			public static void Postfix(Pickable __instance, bool picked)
			{
				TogglePickedMesh(__instance, picked);
			}

			public static void TogglePickedMesh(Pickable instance, bool picked)
			{
				Transform obj = ((Component)instance).transform.root.Find("PE_Picked");
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(picked);
				}
			}
		}

		public const string PluginID = "advize.PlantEverything";

		public const string PluginName = "PlantEverything";

		public const string Version = "1.16.5";

		private readonly Harmony harmony = new Harmony("advize.PlantEverything");

		public static ManualLogSource PELogger = new ManualLogSource(" PlantEverything");

		internal static readonly Dictionary<string, GameObject> prefabRefs = new Dictionary<string, GameObject>();

		private static List<PieceDB> pieceRefs = new List<PieceDB>();

		private static List<SaplingDB> saplingRefs = new List<SaplingDB>();

		internal static List<ExtraResource> deserializedExtraResources = new List<ExtraResource>();

		private static bool piecesInitialized = false;

		private static bool saplingsInitialized = false;

		internal static bool resolveMissingReferences = false;

		private static AssetBundle assetBundle;

		private static readonly Dictionary<string, Texture2D> cachedTextures = new Dictionary<string, Texture2D>();

		private static readonly Dictionary<Texture2D, Sprite> cachedSprites = new Dictionary<Texture2D, Sprite>();

		internal static ModConfig config;

		public void Awake()
		{
			Runtime.MakeAllAssetsLoadable();
			Logger.Sources.Add((ILogSource)(object)PELogger);
			assetBundle = LoadAssetBundle("planteverything");
			config = new ModConfig(((BaseUnityPlugin)this).Config, new ConfigSync("advize.PlantEverything")
			{
				DisplayName = "PlantEverything",
				CurrentVersion = "1.16.5",
				MinimumRequiredVersion = "1.16.5"
			});
			SetupWatcher();
			if (config.EnableExtraResources)
			{
				ExtraResourcesFileOrSettingChanged(null, null);
			}
			if (config.EnableLocalization)
			{
				LoadLocalizedStrings();
			}
			harmony.PatchAll();
			Game.isModded = true;
			Dbgl("PlantEverything has loaded. Set [General]EnableDebugMessages to false to disable these messages.", forceLog: false, (LogLevel)8);
		}

		private static string ModConfigDirectory()
		{
			string text = Path.Combine(Paths.ConfigPath, "PlantEverything");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			return text;
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(ModConfigDirectory(), "PlantEverything_ExtraResources.cfg");
			fileSystemWatcher.Changed += ExtraResourcesFileOrSettingChanged;
			fileSystemWatcher.Created += ExtraResourcesFileOrSettingChanged;
			fileSystemWatcher.Renamed += ExtraResourcesFileOrSettingChanged;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		internal static void ExtraResourcesFileOrSettingChanged(object sender, EventArgs e)
		{
			Dbgl("ExtraResources file or setting has changed", forceLog: false, (LogLevel)16);
			if (config.IsSourceOfTruth)
			{
				if (config.EnableExtraResources)
				{
					Dbgl("IsSourceOfTruth: true, loading extra resources from disk", forceLog: false, (LogLevel)16);
					LoadExtraResources();
				}
				else
				{
					config.SyncedExtraResources.AssignLocalValue(new List<string>());
				}
			}
			else
			{
				Dbgl("IsSourceOfTruth: false, extra resources will not be loaded from disk", forceLog: false, (LogLevel)16);
			}
		}

		private static string SerializeExtraResource(ExtraResource extraResource, bool prettyPrint = true)
		{
			return JsonUtility.ToJson((object)extraResource, prettyPrint);
		}

		private static ExtraResource DeserializeExtraResource(string extraResource)
		{
			return JsonUtility.FromJson<ExtraResource>(extraResource);
		}

		private static void SaveExtraResources()
		{
			string text = Path.Combine(ModConfigDirectory(), "PlantEverything_ExtraResources.cfg");
			Dbgl($"deserializedExtraResources.Count is {deserializedExtraResources.Count}", forceLog: false, (LogLevel)16);
			string text2 = "";
			text2 = text2 + SerializeExtraResource(deserializedExtraResources[0]) + ";\n\n";
			text2 = text2 + SerializeExtraResource(deserializedExtraResources[1], prettyPrint: false) + ";\n";
			File.WriteAllText(text, text2);
			Dbgl("Serialized extraResources to " + text, forceLog: true, (LogLevel)16);
		}

		private static void LoadExtraResources()
		{
			Dbgl("LoadExtraResources", forceLog: false, (LogLevel)16);
			deserializedExtraResources.Clear();
			string text = "PlantEverything_ExtraResources.cfg";
			string text2 = Path.Combine(ModConfigDirectory(), text);
			try
			{
				string[] array = File.ReadAllText(text2).Split(new char[1] { ';' });
				foreach (string text3 in array)
				{
					if (!Utility.IsNullOrWhiteSpace(text3))
					{
						ExtraResource item = DeserializeExtraResource(text3);
						if (item.IsValid())
						{
							deserializedExtraResources.Add(item);
						}
						else if (!item.prefabName.StartsWith("PE_Fake"))
						{
							Dbgl("Invalid resource, " + item.prefabName + ", configured in " + text + ", skipping entry", forceLog: true, (LogLevel)4);
						}
					}
				}
				Dbgl("Loaded extra resources from " + text2, forceLog: true, (LogLevel)16);
				Dbgl("Assigning local value from deserializedExtraResources", forceLog: false, (LogLevel)16);
				List<string> resourcesToSync = new List<string>();
				deserializedExtraResources.ForEach(delegate(ExtraResource er)
				{
					resourcesToSync.Add(SerializeExtraResource(er));
				});
				config.SyncedExtraResources.AssignLocalValue(resourcesToSync);
			}
			catch (Exception ex)
			{
				if (ex is FileNotFoundException)
				{
					Dbgl("Error loading data from " + text + ". Generating new file with example values", forceLog: true, (LogLevel)4);
					deserializedExtraResources = StaticContent.GenerateExampleResources();
					SaveExtraResources();
				}
				else
				{
					Dbgl("Error loading data from " + text + ". Additional resources have not been added", forceLog: false, (LogLevel)4);
					deserializedExtraResources.Clear();
				}
			}
		}

		internal static void ExtraResourcesChanged()
		{
			Dbgl("ExtraResourcesChanged", forceLog: false, (LogLevel)16);
			deserializedExtraResources.Clear();
			foreach (string item2 in config.SyncedExtraResources.Value)
			{
				ExtraResource item = DeserializeExtraResource(item2);
				deserializedExtraResources.Add(item);
			}
			if (Object.op_Implicit((Object)(object)ZNetScene.s_instance))
			{
				InitExtraResourceRefs(ZNetScene.s_instance);
				PieceSettingChanged(null, null);
			}
		}

		private void LoadLocalizedStrings()
		{
			string path = config.Language + "_PlantEverything.json";
			string text = Path.Combine(ModConfigDirectory(), path);
			try
			{
				foreach (string localizedString in JsonUtility.FromJson<ModLocalization>(File.ReadAllText(text)).LocalizedStrings)
				{
					string[] array = localizedString.Split(new char[1] { ':' });
					StaticContent.DefaultLocalizedStrings.Remove(array[0]);
					StaticContent.DefaultLocalizedStrings.Add(array[0], array[1]);
				}
				Dbgl("Loaded localized strings from " + text, forceLog: false, (LogLevel)16);
				return;
			}
			catch
			{
				Dbgl("EnableLocalization is true but unable to load localized text file, generating new one from default English values", forceLog: true, (LogLevel)16);
			}
			SerializeDict();
		}

		private void SerializeDict()
		{
			string text = Path.Combine(ModConfigDirectory(), "english_PlantEverything.json");
			ModLocalization modLocalization = new ModLocalization();
			foreach (KeyValuePair<string, string> defaultLocalizedString in StaticContent.DefaultLocalizedStrings)
			{
				modLocalization.LocalizedStrings.Add(defaultLocalizedString.Key + ":" + defaultLocalizedString.Value);
			}
			File.WriteAllText(text, JsonUtility.ToJson((object)modLocalization, true));
			Dbgl("Saved english localized strings to " + text, forceLog: false, (LogLevel)16);
		}

		internal static void Dbgl(string message, bool forceLog = false, LogLevel level = 16)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			if (!forceLog && !config.EnableDebugMessages)
			{
				return;
			}
			if ((int)level <= 8)
			{
				switch (level - 1)
				{
				case 1:
					PELogger.LogError((object)message);
					return;
				case 3:
					PELogger.LogWarning((object)message);
					return;
				case 0:
					PELogger.LogFatal((object)message);
					return;
				case 2:
					return;
				}
				if ((int)level == 8)
				{
					PELogger.LogMessage((object)message);
				}
			}
			else if ((int)level != 16)
			{
				if ((int)level == 32)
				{
					PELogger.LogDebug((object)message);
				}
			}
			else
			{
				PELogger.LogInfo((object)message);
			}
		}

		private static AssetBundle LoadAssetBundle(string fileName)
		{
			return AssetBundle.LoadFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("Advize_PlantEverything.Assets." + fileName));
		}

		private static GameObject CreatePrefab(string name)
		{
			GameObject obj = assetBundle.LoadAsset<GameObject>(name);
			obj.SetActive(true);
			return obj;
		}

		private static Piece GetOrAddPieceComponent(GameObject go)
		{
			return go.GetComponent<Piece>() ?? go.AddComponent<Piece>();
		}

		private static string GetPrefabName(Component c)
		{
			return ((Object)c.transform.root).name.Replace("(Clone)", "");
		}

		private static bool IsModdedPrefab(Component c)
		{
			if (Object.op_Implicit((Object)(object)c))
			{
				return prefabRefs.ContainsKey(GetPrefabName(c));
			}
			return false;
		}

		private static bool IsModdedPrefabOrSapling(Piece p)
		{
			if (!p.m_name.StartsWith("$pe"))
			{
				return p.m_name.EndsWith("_sapling");
			}
			return true;
		}

		private static bool IsModdedPrefabOrSapling(Plant p)
		{
			if (!p.m_name.StartsWith("$pe"))
			{
				return p.m_name.EndsWith("_sapling");
			}
			return true;
		}

		internal static Piece CreatePiece(PieceDB pdb)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			Piece orAddPieceComponent = GetOrAddPieceComponent(prefabRefs[pdb.key]);
			orAddPieceComponent.m_name = (pdb.extraResource ? pdb.pieceName : ("$pe" + pdb.Name + "Name"));
			orAddPieceComponent.m_description = (pdb.extraResource ? pdb.pieceDescription : ("$pe" + pdb.Name + "Description"));
			orAddPieceComponent.m_category = (PieceCategory)0;
			orAddPieceComponent.m_cultivatedGroundOnly = (pdb.key.Contains("berryBush") || pdb.key.Contains("Pickable")) && config.RequireCultivation;
			bool num = pdb.isGrounded ?? (!config.PlaceAnywhere);
			bool groundOnly = num;
			orAddPieceComponent.m_groundPiece = num;
			orAddPieceComponent.m_groundOnly = groundOnly;
			orAddPieceComponent.m_canBeRemoved = pdb.canBeRemoved ?? true;
			orAddPieceComponent.m_targetNonPlayerBuilt = false;
			((StaticTarget)orAddPieceComponent).m_randomTarget = config.EnemiesTargetPieces;
			return orAddPieceComponent;
		}

		private static Sprite CreateSprite(string fileName, Rect spriteSection)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Texture2D val = LoadTexture(fileName);
				Sprite val2;
				if (cachedSprites.ContainsKey(val))
				{
					val2 = cachedSprites[val];
				}
				else
				{
					val2 = Sprite.Create(val, spriteSection, Vector2.zero);
					cachedSprites.Add(val, val2);
				}
				return val2;
			}
			catch
			{
				Dbgl("Unable to load texture", forceLog: true, (LogLevel)2);
			}
			return null;
		}

		private static Texture2D LoadTexture(string fileName)
		{
			//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_0056: Expected O, but got Unknown
			//IL_0058: Expected O, but got Unknown
			Texture2D val;
			if (cachedTextures.ContainsKey(fileName))
			{
				val = cachedTextures[fileName];
			}
			else
			{
				Stream? manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Advize_PlantEverything.Assets." + fileName);
				byte[] array = new byte[manifestResourceStream.Length];
				manifestResourceStream.Read(array, 0, array.Length);
				Texture2D val2 = new Texture2D(0, 0);
				ImageConversion.LoadImage(val2, array);
				val = val2;
				cachedTextures.Add(fileName, val);
			}
			return val;
		}

		private static void InitPrefabRefs()
		{
			//IL_00e2: 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)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Expected O, but got Unknown
			Dbgl("InitPrefabRefs", forceLog: false, (LogLevel)16);
			if (prefabRefs.Count > 0)
			{
				return;
			}
			Dictionary<string, AssetID> allAssetPathsInBundleMappedToAssetID = Runtime.GetAllAssetPathsInBundleMappedToAssetID();
			bool flag = false;
			StaticContent.VanillaPrefabRefs.ForEach(delegate(string s)
			{
				prefabRefs.Add(s, null);
			});
			StaticContent.VanillaPrefabRefs.Clear();
			deserializedExtraResources.ForEach(delegate(ExtraResource er)
			{
				prefabRefs[er.prefabName] = null;
			});
			SoftReference<GameObject> val = default(SoftReference<GameObject>);
			foreach (string key3 in allAssetPathsInBundleMappedToAssetID.Keys)
			{
				if (!key3.EndsWith(".prefab", StringComparison.Ordinal))
				{
					continue;
				}
				string key2 = key3.Split(new char[1] { '/' }).Last().Replace(".prefab", "");
				if (prefabRefs.ContainsKey(key2))
				{
					val..ctor(allAssetPathsInBundleMappedToAssetID[key3]);
					val.Load();
					prefabRefs[key2] = val.Asset;
					if (!prefabRefs.Any((KeyValuePair<string, GameObject> key) => !Object.op_Implicit((Object)(object)key.Value)))
					{
						Dbgl("Found all prefab references", forceLog: false, (LogLevel)16);
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				Dbgl("Could not find all prefab references", forceLog: false, (LogLevel)16);
				List<string> list = (from key in prefabRefs
					where !Object.op_Implicit((Object)(object)key.Value)
					select key into kvp
					select kvp.Key).ToList();
				if (!list.Any((string key) => !deserializedExtraResources.Select((ExtraResource x) => x.prefabName).ToList().Contains(key)))
				{
					Dbgl("All missing prefab references are configured as ExtraResources. Attempting alternate prefab detection method.", forceLog: false, (LogLevel)16);
					Object[] array = Resources.FindObjectsOfTypeAll(typeof(GameObject));
					for (int i = 0; i < array.Length; i++)
					{
						GameObject val2 = (GameObject)array[i];
						if (list.Contains(((Object)val2).name))
						{
							prefabRefs[((Object)val2).name] = val2;
							list.Remove(((Object)val2).name);
							if (!list.Any())
							{
								Dbgl("Found all prefab references", forceLog: false, (LogLevel)16);
								break;
							}
						}
					}
				}
				foreach (string item in list)
				{
					Dbgl("prefabRefs[" + item + "] value is null, removing key and value pair.", forceLog: false, (LogLevel)16);
					prefabRefs.Remove(item);
				}
			}
			StaticContent.CustomPrefabRefs.ForEach(delegate(string s)
			{
				prefabRefs.Add(s, CreatePrefab(s));
			});
			StaticContent.CustomPrefabRefs.Clear();
		}

		private static bool InitExtraResourceRefs(ZNetScene instance, bool logErrors = false)
		{
			Dbgl("InitExtraResourceRefs", forceLog: false, (LogLevel)16);
			bool result = false;
			foreach (ExtraResource deserializedExtraResource in deserializedExtraResources)
			{
				if (!prefabRefs.ContainsKey(deserializedExtraResource.prefabName) || !Object.op_Implicit((Object)(object)prefabRefs[deserializedExtraResource.prefabName]))
				{
					GameObject prefab = instance.GetPrefab(deserializedExtraResource.prefabName);
					if (Object.op_Implicit((Object)(object)prefab))
					{
						prefabRefs[deserializedExtraResource.prefabName] = prefab;
						Dbgl("Added " + deserializedExtraResource.prefabName + " to prefabRefs", forceLog: false, (LogLevel)16);
						result = true;
					}
					else
					{
						Dbgl("Could not find prefab reference for " + deserializedExtraResource.prefabName + ", skipping entry", logErrors || config.EnableDebugMessages, (LogLevel)4);
					}
				}
			}
			return result;
		}

		private static void InitPieceRefs()
		{
			Dbgl("InitPieceRefs", forceLog: false, (LogLevel)16);
			if (pieceRefs.Count > 0)
			{
				RemoveFromCultivator(pieceRefs.ConvertAll((Converter<PieceDB, PrefabDB>)((PieceDB x) => x)));
				pieceRefs.Clear();
			}
			pieceRefs = StaticContent.GeneratePieceRefs();
		}

		private static void InitPieces()
		{
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0129: Expected O, but got Unknown
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			Dbgl("InitPieces", forceLog: false, (LogLevel)16);
			foreach (PieceDB pdb in pieceRefs)
			{
				if (config.DisabledResourceNames.Contains(pdb.key))
				{
					Dbgl("Resource disabled: " + pdb.key + ", skipping", forceLog: false, (LogLevel)16);
					pdb.enabled = false;
				}
				ItemDrop component = ObjectDB.instance.GetItemPrefab(pdb.Resource.Key).GetComponent<ItemDrop>();
				if (pdb.Resources.Count > 0)
				{
					List<Requirement> list = new List<Requirement>();
					foreach (string key in pdb.Resources.Keys)
					{
						list.Add(new Requirement
						{
							m_resItem = ObjectDB.instance.GetItemPrefab(key).GetComponent<ItemDrop>(),
							m_amount = pdb.Resources[key],
							m_recover = pdb.recover
						});
					}
					pdb.Piece.m_resources = list.ToArray();
				}
				else
				{
					pdb.Piece.m_resources = (Requirement[])(object)new Requirement[1]
					{
						new Requirement
						{
							m_resItem = component,
							m_amount = pdb.ResourceCost,
							m_recover = pdb.recover
						}
					};
				}
				pdb.Piece.m_icon = (pdb.icon ? CreateSprite(pdb.key + "PieceIcon.png", new Rect(0f, 0f, 64f, 64f)) : component.m_itemData.GetIcon());
				pdb.Piece.m_placeEffect.m_effectPrefabs = (EffectData[])(object)new EffectData[2]
				{
					new EffectData
					{
						m_prefab = prefabRefs["vfx_Place_wood_pole"],
						m_enabled = true
					},
					new EffectData
					{
						m_prefab = prefabRefs["sfx_build_cultivator"],
						m_enabled = true
					}
				};
				if (pdb.points != null)
				{
					Transform val = pdb.Prefab.transform.Find("_snappoint");
					if (config.SnappableVines)
					{
						if (!Object.op_Implicit((Object)(object)val))
						{
							foreach (Vector3 point in pdb.points)
							{
								GameObject val2 = new GameObject("_snappoint")
								{
									tag = "snappoint"
								};
								val2.transform.position = point;
								val2.transform.SetParent(pdb.Prefab.transform);
								val2.SetActive(false);
							}
						}
					}
					else
					{
						while (Object.op_Implicit((Object)(object)val))
						{
							Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
							val = pdb.Prefab.transform.Find("_snappoint");
						}
					}
				}
				Pickable component2 = pdb.Prefab.GetComponent<Pickable>();
				if (!Object.op_Implicit((Object)(object)component2) || deserializedExtraResources.Any((ExtraResource x) => x.prefabName == pdb.key))
				{
					continue;
				}
				component2.m_respawnTimeMinutes = pdb.respawnTime;
				component2.m_amount = pdb.resourceReturn;
				pdb.Piece.m_onlyInBiome = pdb.biome;
				Transform val3 = pdb.Prefab.transform.Find("visual");
				if (!Object.op_Implicit((Object)(object)val3))
				{
					continue;
				}
				Transform val4 = prefabRefs[pdb.key + "_Picked"].transform.Find("PE_Picked");
				if (Object.op_Implicit((Object)(object)val4))
				{
					if (config.ShowPickableSpawners)
					{
						val4.SetParent(pdb.Prefab.transform);
					}
					if (!piecesInitialized)
					{
						MeshRenderer component3 = ((Component)val4).GetComponent<MeshRenderer>();
						MeshRenderer component4 = ((Component)val3).GetComponent<MeshRenderer>();
						((Renderer)component3).sharedMaterials = ((pdb.key == "Pickable_Thistle") ? ((Renderer)((Component)val3.Find("default")).GetComponent<MeshRenderer>()).sharedMaterials : ((Renderer)component4).sharedMaterials);
						if (pdb.key.Contains("Dandelion"))
						{
							Material val5 = ((Renderer)component4).sharedMaterials[0];
							((Renderer)component3).sharedMaterials = (Material[])(object)new Material[2] { val5, val5 };
						}
					}
				}
				else
				{
					Transform val6 = prefabRefs[pdb.key].transform.Find("PE_Picked");
					if (!config.ShowPickableSpawners && Object.op_Implicit((Object)(object)val6))
					{
						val6.SetParent(prefabRefs[pdb.key + "_Picked"].transform);
					}
				}
			}
			piecesInitialized = true;
		}

		private static void InitSaplingRefs()
		{
			Dbgl("InitSaplingRefs", forceLog: false, (LogLevel)16);
			if (saplingRefs.Count > 0)
			{
				RemoveFromCultivator(saplingRefs.ConvertAll((Converter<SaplingDB, PrefabDB>)((SaplingDB x) => x)));
				saplingRefs.Clear();
			}
			saplingRefs = StaticContent.GenerateCustomSaplingRefs();
		}

		private static void InitSaplings()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			Dbgl("InitSaplings", forceLog: false, (LogLevel)16);
			ModifyTreeDrops();
			AssetID val2 = default(AssetID);
			SoftReference<Shader> val3 = default(SoftReference<Shader>);
			foreach (SaplingDB item in StaticContent.GenerateVanillaSaplingRefs().Concat(saplingRefs))
			{
				Plant component = item.Prefab.GetComponent<Plant>();
				Piece component2 = item.Prefab.GetComponent<Piece>();
				component.m_growTime = (component.m_growTimeMax = item.growTime);
				component.m_growRadius = item.growRadius;
				component.m_minScale = item.minScale;
				component.m_maxScale = item.maxScale;
				component2.m_onlyInBiome = (component.m_biome = item.biome);
				component.m_destroyIfCantGrow = (component2.m_groundOnly = !config.PlaceAnywhere);
				if (!saplingRefs.Contains(item))
				{
					continue;
				}
				component.m_grownPrefabs = item.grownPrefabs;
				component2.m_resources[0].m_resItem = prefabRefs[item.resource].GetComponent<ItemDrop>();
				component2.m_resources[0].m_amount = item.resourceCost;
				if (config.DisabledResourceNames.Contains(item.key))
				{
					Dbgl("Resource disabled: " + item.key, forceLog: false, (LogLevel)16);
					item.enabled = false;
				}
				if (saplingsInitialized)
				{
					continue;
				}
				string[] array = new string[2] { "healthy", "unhealthy" };
				Transform val = prefabRefs["Birch_Sapling"].transform.Find(array[0]);
				string[] array2 = array;
				foreach (string text in array2)
				{
					((Component)item.Prefab.transform.Find(text)).GetComponent<MeshFilter>().mesh = ((Component)val.Find("Birch_Sapling")).GetComponent<MeshFilter>().mesh;
				}
				switch (item.source)
				{
				case "YggaShoot_small1":
				{
					string[] array5 = new string[6] { "birchleafs002", "birchleafs003", "birchleafs008", "birchleafs009", "birchleafs010", "birchleafs011" };
					Material[] sharedMaterials3 = (Material[])(object)new Material[1] { ((Renderer)((Component)prefabRefs[item.source].transform.Find("beech")).GetComponent<MeshRenderer>()).sharedMaterials[0] };
					Material[] sharedMaterials4 = (Material[])(object)new Material[1] { ((Renderer)((Component)prefabRefs[item.source].transform.Find("beech")).GetComponent<MeshRenderer>()).sharedMaterials[1] };
					array2 = array;
					foreach (string text5 in array2)
					{
						((Renderer)((Component)item.Prefab.transform.Find(text5)).GetComponent<MeshRenderer>()).sharedMaterials = sharedMaterials4;
					}
					array2 = array5;
					foreach (string text6 in array2)
					{
						string[] array4 = array;
						foreach (string text7 in array4)
						{
							((Component)item.Prefab.transform.Find(text7).Find(text6)).GetComponent<MeshFilter>().mesh = ((Component)val.Find(text6)).GetComponent<MeshFilter>().mesh;
							((Renderer)((Component)item.Prefab.transform.Find(text7).Find(text6)).GetComponent<MeshRenderer>()).sharedMaterials = sharedMaterials3;
						}
					}
					break;
				}
				case "SwampTree1":
				{
					Material[] array6 = (Material[])(object)new Material[1] { ((Renderer)((Component)prefabRefs[item.source].transform.Find("swamptree1")).GetComponent<MeshRenderer>()).sharedMaterials[0] };
					AssetID.TryParse("f6de4704e075b4095ae641aed283b641", ref val2);
					val3..ctor(val2);
					val3.Load();
					array6[0].shader = val3.Asset;
					array2 = array;
					foreach (string text8 in array2)
					{
						((Renderer)((Component)item.Prefab.transform.Find(text8)).GetComponent<MeshRenderer>()).sharedMaterials = array6;
					}
					break;
				}
				case "Birch1_aut":
				{
					string[] array3 = new string[6] { "birchleafs002", "birchleafs003", "birchleafs008", "birchleafs009", "birchleafs010", "birchleafs011" };
					Material[] sharedMaterials = (Material[])(object)new Material[1] { ((Renderer)((Component)prefabRefs[item.source].transform.Find("Lod0")).GetComponent<MeshRenderer>()).sharedMaterials[0] };
					Material[] sharedMaterials2 = (Material[])(object)new Material[1] { ((Renderer)((Component)val.Find("Birch_Sapling")).GetComponent<MeshRenderer>()).sharedMaterials[0] };
					array2 = array;
					foreach (string text2 in array2)
					{
						((Renderer)((Component)item.Prefab.transform.Find(text2)).GetComponent<MeshRenderer>()).sharedMaterials = sharedMaterials2;
					}
					array2 = array3;
					foreach (string text3 in array2)
					{
						string[] array4 = array;
						foreach (string text4 in array4)
						{
							((Component)item.Prefab.transform.Find(text4).Find(text3)).GetComponent<MeshFilter>().mesh = ((Component)val.Find(text3)).GetComponent<MeshFilter>().mesh;
							((Renderer)((Component)item.Prefab.transform.Find(text4).Find(text3)).GetComponent<MeshRenderer>()).sharedMaterials = sharedMaterials;
						}
					}
					break;
				}
				}
				component2.m_icon = (item.icon ? CreateSprite(item.key + "PieceIcon.png", new Rect(0f, 0f, 64f, 64f)) : component2.m_resources[0].m_resItem.m_itemData.GetIcon());
				component2.m_placeEffect.m_effectPrefabs[0].m_prefab = prefabRefs["vfx_Place_wood_pole"];
				component2.m_placeEffect.m_effectPrefabs[1].m_prefab = prefabRefs["sfx_build_cultivator"];
				item.Prefab.GetComponent<Destructible>().m_hitEffect.m_effectPrefabs = prefabRefs["Birch_Sapling"].GetComponent<Destructible>().m_hitEffect.m_effectPrefabs;
			}
			saplingsInitialized = true;
		}

		private static void ModifyTreeDrops()
		{
			//IL_0034: 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_0058: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!config.EnableSeedOverrides)
			{
				return;
			}
			foreach (KeyValuePair<GameObject, GameObject> treesToSeed in StaticContent.TreesToSeeds)
			{
				TreeBase component = treesToSeed.Key.GetComponent<TreeBase>();
				DropData item = default(DropData);
				bool flag = false;
				foreach (DropData drop in component.m_dropWhenDestroyed.m_drops)
				{
					if (((object)drop.m_item).Equals((object?)treesToSeed.Value))
					{
						flag = true;
						item = drop;
						break;
					}
				}
				if (flag)
				{
					component.m_dropWhenDestroyed.m_drops.Remove(item);
				}
				item.m_item = treesToSeed.Value;
				item.m_stackMin = config.SeedDropMin;
				item.m_stackMax = config.SeedDropMax;
				item.m_weight = 1f;
				component.m_dropWhenDestroyed.m_dropMin = config.TreeDropMin;
				component.m_dropWhenDestroyed.m_dropMax = config.TreeDropMax;
				component.m_dropWhenDestroyed.m_drops.Add(item);
				component.m_dropWhenDestroyed.m_dropChance = Mathf.Clamp(config.DropChance, 0f, 1f);
				component.m_dropWhenDestroyed.m_oneOfEach = config.OneOfEach;
			}
		}

		private static void InitCrops()
		{
			//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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			Dbgl("InitCrops", forceLog: false, (LogLevel)16);
			bool enableCropOverrides = config.EnableCropOverrides;
			foreach (PrefabDB item in StaticContent.GenerateCropRefs())
			{
				Piece component = item.Prefab.GetComponent<Piece>();
				Plant component2 = item.Prefab.GetComponent<Plant>();
				Pickable component3 = component2.m_grownPrefabs[0].GetComponent<Pickable>();
				component.m_resources[0].m_amount = item.resourceCost;
				((StaticTarget)component).m_primaryTarget = (((StaticTarget)component).m_randomTarget = config.EnemiesTargetCrops);
				component2.m_biome = item.biome;
				component2.m_minScale = (enableCropOverrides ? config.CropMinScale : 0.9f);
				component2.m_maxScale = (enableCropOverrides ? config.CropMaxScale : 1.1f);
				component2.m_growTime = (enableCropOverrides ? config.CropGrowTimeMin : 4000f);
				component2.m_growTimeMax = (enableCropOverrides ? config.CropGrowTimeMax : 5000f);
				component2.m_growRadius = (enableCropOverrides ? config.CropGrowRadius : 0.5f);
				component2.m_needCultivatedGround = (component.m_cultivatedGroundOnly = !enableCropOverrides || config.CropRequireCultivation);
				component3.m_amount = item.resourceReturn;
				component3.m_extraDrops.m_drops.Clear();
				if (item.extraDrops && !enableCropOverrides)
				{
					component3.m_extraDrops.m_drops.Add(new DropData
					{
						m_item = component3.m_itemPrefab,
						m_stackMin = 1,
						m_stackMax = 1,
						m_weight = 0f
					});
				}
			}
		}

		private static void InitCultivator()
		{
			Dbgl("InitCultivator", forceLog: false, (LogLevel)16);
			PieceTable buildPieces = prefabRefs["Cultivator"].GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			for (int i = 0; i < saplingRefs.Count; i++)
			{
				if (saplingRefs[i].enabled && !buildPieces.m_pieces.Contains(saplingRefs[i].Prefab))
				{
					buildPieces.m_pieces.Insert(16, saplingRefs[i].Prefab);
				}
			}
			for (int j = 0; j < pieceRefs.Count; j++)
			{
				if (pieceRefs[j].enabled && !buildPieces.m_pieces.Contains(pieceRefs[j].Prefab))
				{
					buildPieces.m_pieces.Add(pieceRefs[j].Prefab);
				}
			}
			buildPieces.m_canRemovePieces = true;
		}

		private static void RemoveFromCultivator(List<PrefabDB> prefabs)
		{
			Player localPlayer = Player.m_localPlayer;
			if (((localPlayer == null) ? null : ((Humanoid)localPlayer).GetRightItem()?.m_shared.m_name) == "$item_cultivator")
			{
				PELogger.LogWarning((object)"Cultivator updated through config change, unequipping cultivator");
				((Humanoid)Player.m_localPlayer).HideHandItems();
			}
			PieceTable pieceTable = prefabRefs["Cultivator"].GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			prefabs.ForEach(delegate(PrefabDB x)
			{
				pieceTable.m_pieces.Remove(x.Prefab);
			});
		}

		private static void FinalInit(ZNetScene instance)
		{
			Dbgl("Performing final mod initialization", forceLog: false, (LogLevel)16);
			InitExtraResourceRefs(instance);
			InitPieceRefs();
			InitPieces();
			InitSaplingRefs();
			InitSaplings();
			InitCrops();
			InitCultivator();
			if (StaticContent.DefaultLocalizedStrings.Count > 0)
			{
				InitLocalization();
			}
			for (int i = 0; i < saplingRefs.Count; i++)
			{
				GameObject prefab = saplingRefs[i].Prefab;
				if (!instance.m_prefabs.Contains(prefab))
				{
					instance.m_prefabs.Add(prefab);
					instance.m_namedPrefabs.Add(instance.GetPrefabHash(prefab), prefab);
				}
			}
		}

		internal static void CoreSettingChanged(object o, EventArgs e)
		{
			Dbgl("Config setting changed, re-initializing mod", forceLog: false, (LogLevel)16);
			InitPieceRefs();
			InitPieces();
			InitSaplingRefs();
			InitSaplings();
			InitCrops();
			InitCultivator();
		}

		internal static void PieceSettingChanged(object o, EventArgs e)
		{
			Dbgl("Config setting changed, re-initializing pieces", forceLog: false, (LogLevel)16);
			InitPieceRefs();
			InitPieces();
			InitCultivator();
		}

		internal static void SaplingSettingChanged(object o, EventArgs e)
		{
			Dbgl("Config setting changed, re-initializing saplings", forceLog: false, (LogLevel)16);
			InitSaplingRefs();
			InitSaplings();
			InitCultivator();
		}

		internal static void SeedSettingChanged(object o, EventArgs e)
		{
			Dbgl("Config setting changed, modifying TreeBase drop tables", forceLog: false, (LogLevel)16);
			ModifyTreeDrops();
		}

		internal static void CropSettingChanged(object o, EventArgs e)
		{
			Dbgl("Config setting changed, re-initializing crops", forceLog: false, (LogLevel)16);
			InitCrops();
		}

		public static void InitLocalization()
		{
			Dbgl("InitLocalization", forceLog: false, (LogLevel)16);
			foreach (KeyValuePair<string, string> defaultLocalizedString in StaticContent.DefaultLocalizedStrings)
			{
				Localization.instance.AddWord("pe" + defaultLocalizedString.Key, defaultLocalizedString.Value);
			}
			StaticContent.DefaultLocalizedStrings.Clear();
		}
	}
}
namespace Advize_PlantEverything.Configuration
{
	internal sealed class ModConfig
	{
		internal class ConfigurationManagerAttributes
		{
			public bool? Browsable;

			[<2c5aa66a-a271-4227-838c-a746fbb80658>Nullable(2)]
			public string Category;

			public int? Order;

			public bool? ReadOnly;
		}

		[<77b86206-05ce-438b-a28e-c1d9601e8658>NullableContext(2)]
		[<2c5aa66a-a271-4227-838c-a746fbb80658>Nullable(0)]
		internal class ConfigManagerHelper
		{
			private static Assembly BepinexConfigManager => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault([<77b86206-05ce-438b-a28e-c1d9601e8658>NullableContext(0)] (Assembly a) => a.GetName().Name == "ConfigurationManager");

			private static Type ConfigManagerType => BepinexConfigManager?.GetType("ConfigurationManager.ConfigurationManager");

			private static object ConfigManager
			{
				get
				{
					if (!(ConfigManagerType == null))
					{
						return Chainloader.ManagerObject.GetComponent(ConfigManagerType);
					}
					return null;
				}
			}

			internal static void ReloadConfigDisplay()
			{
				ConfigManager?.GetType().GetMethod("BuildSettingList").Invoke(ConfigManager, Array.Empty<object>());
			}
		}

		private readonly ConfigFile ConfigFile;

		private readonly ConfigSync ConfigSync;

		private readonly ConfigEntry<bool> serverConfigLocked;

		internal readonly ConfigEntry<int> nexusID;

		private readonly ConfigEntry<bool> enableDebugMessages;

		private readonly ConfigEntry<bool> showPickableSpawners;

		private readonly ConfigEntry<bool> enableMiscFlora;

		private readonly ConfigEntry<bool> enableExtraResources;

		private readonly ConfigEntry<bool> snappableVines;

		private readonly ConfigEntry<bool> enableLocalization;

		private readonly ConfigEntry<string> language;

		private readonly ConfigEntry<string> disabledResourceNames;

		private readonly ConfigEntry<bool> requireCultivation;

		private readonly ConfigEntry<bool> placeAnywhere;

		private readonly ConfigEntry<bool> enforceBiomes;

		private readonly ConfigEntry<bool> enforceBiomesVanilla;

		private readonly ConfigEntry<bool> recoverResources;

		private readonly ConfigEntry<bool> resourcesSpawnEmpty;

		private readonly ConfigEntry<bool> enemiesTargetPieces;

		private readonly ConfigEntry<int> raspberryCost;

		private readonly ConfigEntry<int> blueberryCost;

		private readonly ConfigEntry<int> cloudberryCost;

		private readonly ConfigEntry<int> raspberryRespawnTime;

		private readonly ConfigEntry<int> blueberryRespawnTime;

		private readonly ConfigEntry<int> cloudberryRespawnTime;

		private readonly ConfigEntry<int> raspberryReturn;

		private readonly ConfigEntry<int> blueberryReturn;

		private readonly ConfigEntry<int> cloudberryReturn;

		private readonly ConfigEntry<bool> enableCropOverrides;

		private readonly ConfigEntry<bool> cropRequireCultivation;

		private readonly ConfigEntry<bool> cropRequireSunlight;

		private readonly ConfigEntry<bool> cropRequireGrowthSpace;

		private readonly ConfigEntry<bool> enemiesTargetCrops;

		private readonly ConfigEntry<float> cropMinScale;

		private readonly ConfigEntry<float> cropMaxScale;

		private readonly ConfigEntry<float> cropGrowTimeMin;

		private readonly ConfigEntry<float> cropGrowTimeMax;

		private readonly ConfigEntry<float> cropGrowRadius;

		private readonly ConfigEntry<int> barleyCost;

		private readonly ConfigEntry<int> barleyReturn;

		private readonly ConfigEntry<int> carrotCost;

		private readonly ConfigEntry<int> carrotReturn;

		private readonly ConfigEntry<int> flaxCost;

		private readonly ConfigEntry<int> flaxReturn;

		private readonly ConfigEntry<int> onionCost;

		private readonly ConfigEntry<int> onionReturn;

		private readonly ConfigEntry<int> seedCarrotCost;

		private readonly ConfigEntry<int> seedCarrotReturn;

		private readonly ConfigEntry<int> seedOnionCost;

		private readonly ConfigEntry<int> seedOnionReturn;

		private readonly ConfigEntry<int> seedTurnipCost;

		private readonly ConfigEntry<int> seedTurnipReturn;

		private readonly ConfigEntry<int> turnipCost;

		private readonly ConfigEntry<int> turnipReturn;

		private readonly ConfigEntry<int> magecapCost;

		private readonly ConfigEntry<int> magecapReturn;

		private readonly ConfigEntry<int> jotunPuffsCost;

		private readonly ConfigEntry<int> jotunPuffsReturn;

		private readonly ConfigEntry<int> pickableBranchCost;

		private readonly ConfigEntry<int> pickableBranchReturn;

		private readonly ConfigEntry<int> pickableStoneCost;

		private readonly ConfigEntry<int> pickableStoneReturn;

		private readonly ConfigEntry<int> pickableFlintCost;

		private readonly ConfigEntry<int> pickableFlintReturn;

		private readonly ConfigEntry<int> mushroomCost;

		private readonly ConfigEntry<int> yellowMushroomCost;

		private readonly ConfigEntry<int> blueMushroomCost;

		private readonly ConfigEntry<int> mushroomRespawnTime;

		private readonly ConfigEntry<int> yellowMushroomRespawnTime;

		private readonly ConfigEntry<int> blueMushroomRespawnTime;

		private readonly ConfigEntry<int> mushroomReturn;

		private readonly ConfigEntry<int> yellowMushroomReturn;

		private readonly ConfigEntry<int> blueMushroomReturn;

		private readonly ConfigEntry<int> thistleCost;

		private readonly ConfigEntry<int> dandelionCost;

		private readonly ConfigEntry<int> thistleRespawnTime;

		private readonly ConfigEntry<int> dandelionRespawnTime;

		private readonly ConfigEntry<int> thistleReturn;

		private readonly ConfigEntry<int> dandelionReturn;

		private readonly ConfigEntry<float> birchMinScale;

		private readonly ConfigEntry<float> birchMaxScale;

		private readonly ConfigEntry<float> oakMinScale;

		private readonly ConfigEntry<float> oakMaxScale;

		private readonly ConfigEntry<float> ancientMinScale;

		private readonly ConfigEntry<float> ancientMaxScale;

		private readonly ConfigEntry<float> birchGrowthTime;

		private readonly ConfigEntry<float> oakGrowthTime;

		private readonly ConfigEntry<float> ancientGrowthTime;

		private readonly ConfigEntry<float> birchGrowRadius;

		private readonly ConfigEntry<float> oakGrowRadius;

		private readonly ConfigEntry<float> ancientGrowRadius;

		private readonly ConfigEntry<float> beechGrowthTime;

		private readonly ConfigEntry<float> pineGrowthTime;

		private readonly ConfigEntry<float> firGrowthTime;

		private readonly ConfigEntry<float> beechMinScale;

		private readonly ConfigEntry<float> beechMaxScale;

		private readonly ConfigEntry<float> pineMinScale;

		private readonly ConfigEntry<float> pineMaxScale;

		private readonly ConfigEntry<float> firMinScale;

		private readonly ConfigEntry<float> firMaxScale;

		private readonly ConfigEntry<float> beechGrowRadius;

		private readonly ConfigEntry<float> pineGrowRadius;

		private readonly ConfigEntry<float> firGrowRadius;

		private readonly ConfigEntry<float> yggaMinScale;

		private readonly ConfigEntry<float> yggaMaxScale;

		private readonly ConfigEntry<float> yggaGrowthTime;

		private readonly ConfigEntry<float> yggaGrowRadius;

		private readonly ConfigEntry<float> autumnBirchMinScale;

		private readonly ConfigEntry<float> autumnBirchMaxScale;

		private readonly ConfigEntry<float> autumnBirchGrowthTime;

		private readonly ConfigEntry<float> autumnBirchGrowRadius;

		private readonly ConfigEntry<bool> enableSeedOverrides;

		private readonly ConfigEntry<int> seedDropMin;

		private readonly ConfigEntry<int> seedDropMax;

		private readonly ConfigEntry<int> treeDropMin;

		private readonly ConfigEntry<int> treeDropMax;

		private readonly ConfigEntry<float> dropChance;

		private readonly ConfigEntry<bool> oneOfEach;

		private readonly ConfigEntry<bool> enablePickableTimers;

		private readonly ConfigEntry<bool> enablePlantTimers;

		private readonly ConfigEntry<bool> growthAsPercentage;

		private readonly CustomSyncedValue<List<string>> extraResources;

		private readonly ConfigurationManagerAttributes seedSettingAtrributes = new ConfigurationManagerAttributes();

		private readonly List<ConfigurationManagerAttributes> cropSettingAttributes = new List<ConfigurationManagerAttributes>
		{
			new ConfigurationManagerAttributes(),
			new ConfigurationManagerAttributes
			{
				Order = 27
			}
		};

		internal bool EnableDebugMessages => enableDebugMessages.Value;

		internal bool ShowPickableSpawners => showPickableSpawners.Value;

		internal bool EnableMiscFlora => enableMiscFlora.Value;

		internal bool EnableExtraResources => enableExtraResources.Value;

		internal bool SnappableVines => snappableVines.Value;

		internal bool EnableLocalization => enableLocalization.Value;

		internal string Language => language.Value;

		internal string[] DisabledResourceNames => disabledResourceNames.Value.Split(new char[1] { ',' });

		internal bool RequireCultivation => requireCultivation.Value;

		internal bool PlaceAnywhere => placeAnywhere.Value;

		internal bool EnforceBiomes => enforceBiomes.Value;

		internal bool EnforceBiomesVanilla => enforceBiomesVanilla.Value;

		internal bool RecoverResources => recoverResources.Value;

		internal bool ResourcesSpawnEmpty => resourcesSpawnEmpty.Value;

		internal bool EnemiesTargetPieces => enemiesTargetPieces.Value;

		internal int RaspberryCost => raspberryCost.Value;

		internal int BlueberryCost => blueberryCost.Value;

		internal int CloudberryCost => cloudberryCost.Value;

		internal int RaspberryRespawnTime => raspberryRespawnTime.Value;

		internal int BlueberryRespawnTime => blueberryRespawnTime.Value;

		internal int CloudberryRespawnTime => cloudberryRespawnTime.Value;

		internal int RaspberryReturn => raspberryReturn.Value;

		internal int BlueberryReturn => blueberryReturn.Value;

		internal int CloudberryReturn => cloudberryReturn.Value;

		internal bool EnableCropOverrides => enableCropOverrides.Value;

		internal float CropMinScale => cropMinScale.Value;

		internal float CropMaxScale => cropMaxScale.Value;

		internal float CropGrowTimeMin => Mathf.Max(cropGrowTimeMin.Value, 10f);

		internal float CropGrowTimeMax => Mathf.Max(cropGrowTimeMax.Value, 10f);

		internal float CropGrowRadius => cropGrowRadius.Value;

		internal bool CropRequireCultivation => cropRequireCultivation.Value;

		internal bool CropRequireSunlight => cropRequireSunlight.Value;

		internal bool CropRequireGrowthSpace => cropRequireGrowthSpace.Value;

		internal bool EnemiesTargetCrops => enemiesTargetCrops.Value;

		internal int BarleyCost => barleyCost.Value;

		internal int BarleyReturn => barleyReturn.Value;

		internal int CarrotCost => carrotCost.Value;

		internal int CarrotReturn => carrotReturn.Value;

		internal int FlaxCost => flaxCost.Value;

		internal int FlaxReturn => flaxReturn.Value;

		internal int OnionCost => onionCost.Value;

		internal int OnionReturn => onionReturn.Value;

		internal int SeedCarrotCost => seedCarrotCost.Value;

		internal int SeedCarrotReturn => seedCarrotReturn.Value;

		internal int SeedOnionCost => seedOnionCost.Value;

		internal int SeedOnionReturn => seedOnionReturn.Value;

		internal int SeedTurnipCost => seedTurnipCost.Value;

		internal int SeedTurnipReturn => seedTurnipReturn.Value;

		internal int TurnipCost => turnipCost.Value;

		internal int TurnipReturn => turnipReturn.Value;

		internal int MagecapCost => magecapCost.Value;

		internal int MagecapReturn => magecapReturn.Value;

		internal int JotunPuffsCost => jotunPuffsCost.Value;

		internal int JotunPuffsReturn => jotunPuffsReturn.Value;

		internal int PickableBranchCost => pickableBranchCost.Value;

		internal int PickableBranchReturn => pickableBranchReturn.Value;

		internal int PickableStoneCost => pickableStoneCost.Value;

		internal int PickableStoneReturn => pickableStoneReturn.Value;

		internal int PickableFlintCost => pickableFlintCost.Value;

		internal int PickableFlintReturn => pickableFlintReturn.Value;

		internal int MushroomCost => mushroomCost.Value;

		internal int YellowMushroomCost => yellowMushroomCost.Value;

		internal int BlueMushroomCost => blueMushroomCost.Value;

		internal int MushroomRespawnTime => mushroomRespawnTime.Value;

		internal int YellowMushroomRespawnTime => yellowMushroomRespawnTime.Value;

		internal int BlueMushroomRespawnTime => blueMushroomRespawnTime.Value;

		internal int MushroomReturn => mushroomReturn.Value;

		internal int YellowMushroomReturn => yellowMushroomReturn.Value;

		internal int BlueMushroomReturn => blueMushroomReturn.Value;

		internal int ThistleCost => thistleCost.Value;

		internal int DandelionCost => dandelionCost.Value;

		internal int ThistleRespawnTime => thistleRespawnTime.Value;

		internal int DandelionRespawnTime => dandelionRespawnTime.Value;

		internal int ThistleReturn => thistleReturn.Value;

		internal int DandelionReturn => dandelionReturn.Value;

		internal float BirchMinScale => birchMinScale.Value;

		internal float BirchMaxScale => birchMaxScale.Value;

		internal float OakMinScale => oakMinScale.Value;

		internal float OakMaxScale => oakMaxScale.Value;

		internal float AncientMinScale => ancientMinScale.Value;

		internal float AncientMaxScale => ancientMaxScale.Value;

		internal float BirchGrowthTime => Mathf.Max(birchGrowthTime.Value, 10f);

		internal float OakGrowthTime => Mathf.Max(oakGrowthTime.Value, 10f);

		internal float AncientGrowthTime => Mathf.Max(ancientGrowthTime.Value, 10f);

		internal float BirchGrowRadius => birchGrowRadius.Value;

		internal float OakGrowRadius => oakGrowRadius.Value;

		internal float AncientGrowRadius => ancientGrowRadius.Value;

		internal float BeechGrowthTime => Mathf.Max(beechGrowthTime.Value, 10f);

		internal float PineGrowthTime => Mathf.Max(pineGrowthTime.Value, 10f);

		internal float FirGrowthTime => Mathf.Max(firGrowthTime.Value, 10f);

		internal float BeechMinScale => beechMinScale.Value;

		internal float BeechMaxScale => beechMaxScale.Value;

		internal float PineMinScale => pineMinScale.Value;

		internal float PineMaxScale => pineMaxScale.Value;

		internal float FirMinScale => firMinScale.Value;

		internal float FirMaxScale => firMaxScale.Value;

		internal float BeechGrowRadius => beechGrowRadius.Value;

		internal float PineGrowRadius => pineGrowRadius.Value;

		internal float FirGrowRadius => firGrowRadius.Value;

		internal float YggaMinScale => yggaMinScale.Value;

		internal float YggaMaxScale => yggaMaxScale.Value;

		internal float YggaGrowthTime => yggaGrowthTime.Value;

		internal float YggaGrowRadius => yggaGrowRadius.Value;

		internal float AutumnBirchMinScale => autumnBirchMinScale.Value;

		internal float AutumnBirchMaxScale => autumnBirchMaxScale.Value;

		internal float AutumnBirchGrowthTime => autumnBirchGrowthTime.Value;

		internal float AutumnBirchGrowRadius => autumnBirchGrowRadius.Value;

		internal bool EnableSeedOverrides => enableSeedOverrides.Value;

		internal int SeedDropMin => seedDropMin.Value;

		internal int SeedDropMax => seedDropMax.Value;

		internal int TreeDropMin => treeDropMin.Value;

		internal int TreeDropMax => treeDropMax.Value;

		internal float DropChance => dropChance.Value;

		internal bool OneOfEach => oneOfEach.Value;

		internal bool EnablePickableTimers => enablePickableTimers.Value;

		internal bool EnablePlantTimers => enablePlantTimers.Value;

		internal bool GrowthAsPercentage => growthAsPercentage.Value;

		internal CustomSyncedValue<List<string>> SyncedExtraResources => extraResources;

		internal bool IsSourceOfTruth => ConfigSync.IsSourceOfTruth;

		private ConfigEntry<T> Config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			ConfigEntry<T> val = ConfigFile.Bind<T>(group, name, value, description);
			ConfigSync.AddConfigEntry<T>(val).SynchronizedConfig = synchronizedSetting;
			return val;
		}

		private ConfigEntry<T> Config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return Config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		internal ModConfig(ConfigFile configFile, ConfigSync configSync)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Expected O, but got Unknown
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Expected O, but got Unknown
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Expected O, but got Unknown
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Expected O, but got Unknown
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Expected O, but got Unknown
			//IL_0503: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Expected O, but got Unknown
			//IL_053b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0546: Expected O, but got Unknown
			//IL_0573: Unknown result type (might be due to invalid IL or missing references)
			//IL_057e: Expected O, but got Unknown
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b6: Expected O, but got Unknown
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ee: Expected O, but got Unknown
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Expected O, but got Unknown
			//IL_0653: Unknown result type (might be due to invalid IL or missing references)
			//IL_065e: Expected O, but got Unknown
			//IL_068b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0696: Expected O, but got Unknown
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ce: Expected O, but got Unknown
			//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0706: Expected O, but got Unknown
			//IL_0733: Unknown result type (might be due to invalid IL or missing references)
			//IL_073e: Expected O, but got Unknown
			//IL_076b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0776: Expected O, but got Unknown
			//IL_07a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ae: Expected O, but got Unknown
			//IL_07db: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e6: Expected O, but got Unknown
			//IL_0813: Unknown result type (might be due to invalid IL or missing references)
			//IL_081e: Expected O, but got Unknown
			//IL_084b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0856: Expected O, but got Unknown
			//IL_0883: Unknown result type (might be due to invalid IL or missing references)
			//IL_088e: Expected O, but got Unknown
			//IL_08bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c6: Expected O, but got Unknown
			//IL_08f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_08fe: Expected O, but got Unknown
			//IL_092b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0936: Expected O, but got Unknown
			//IL_0963: Unknown result type (might be due to invalid IL or missing references)
			//IL_096e: Expected O, but got Unknown
			//IL_099b: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a6: Expected O, but got Unknown
			//IL_09d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09de: Expected O, but got Unknown
			//IL_0a0b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a16: Expected O, but got Unknown
			//IL_0a43: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a4e: Expected O, but got Unknown
			//IL_1116: Unknown result type (might be due to invalid IL or missing references)
			//IL_1121: Expected O, but got Unknown
			//IL_1148: Unknown result type (might be due to invalid IL or missing references)
			//IL_1153: Expected O, but got Unknown
			//IL_117a: Unknown result type (might be due to invalid IL or missing references)
			//IL_1185: Expected O, but got Unknown
			//IL_11ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_11b7: Expected O, but got Unknown
			//IL_11de: Unknown result type (might be due to invalid IL or missing references)
			//IL_11e9: Expected O, but got Unknown
			//IL_1214: Unknown result type (might be due to invalid IL or missing references)
			//IL_121f: Expected O, but got Unknown
			//IL_1246: Unknown result type (might be due to invalid IL or missing references)
			//IL_1251: Expected O, but got Unknown
			ConfigFile = configFile;
			ConfigSync = configSync;
			configFile.SaveOnConfigSet = false;
			serverConfigLocked = Config("General", "LockConfiguration", value: true, "If on, the configuration is locked and can be changed by server admins only.");
			nexusID = Config("General", "NexusID", 1042, new ConfigDescription("Nexus mod ID for updates.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "Internal",
					ReadOnly = true
				}
			}), synchronizedSetting: false);
			enableDebugMessages = Config("General", "EnableDebugMessages", value: false, "Enable mod debug messages in console.", synchronizedSetting: false);
			showPickableSpawners = Config("General", "ShowPickableSpawners", value: true, "Continue to show mushroom, thistle, and dandelion spawners after being picked. (Requires world reload on client to take effect.)", synchronizedSetting: false);
			enableMiscFlora = Config("General", "EnableMiscFlora", value: true, "Enables small trees, bushes, shrubs, vines, and large mushrooms.");
			enableExtraResources = Config("General", "EnableExtraResources", value: false, "When set to true, the mod will attempt to make user-defined prefabs buildable with the cultivator. Prefabs are defined in PlantEverything_ExtraResources.cfg. If file is not present, an example one will be generated for you.");
			snappableVines = Config("General", "SnappableVines", value: true, "Enables snap points when placing vines adjacently.", synchronizedSetting: false);
			enableLocalization = Config("General", "EnableLocalization", value: false, "Enable this to attempt to load localized text data for the language set in the following setting.", synchronizedSetting: false);
			language = Config("General", "Language", "english", "Language to be used. If EnableLocalization is enabled, game will attempt to load localized text from a file named {language}_PlantEverything.json.", synchronizedSetting: false);
			disabledResourceNames = Config("General", "DisabledResourceNames", "", new ConfigDescription("To disable specific resources added by this mod (and not add them to the cultivator), list their prefab names here separated by a comma. Names are case-sensitive.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = -1
				}
			}));
			requireCultivation = Config("Difficulty", "RequireCultivation", value: false, "Pickable resources can only be planted on cultivated ground.");
			placeAnywhere = Config("Difficulty", "PlaceAnywhere", value: false, "Allow resources to be placed anywhere (not just on the ground). Does not apply to mushrooms or flowers.");
			enforceBiomes = Config("Difficulty", "EnforceBiomes", value: false, "Restrict modded plantables (pickables and saplings) to being placed in their respective biome.");
			enforceBiomesVanilla = Config("Difficulty", "EnforceBiomesVanilla", value: true, "Restrict vanilla plantables (crops and saplings) to being placed in their respective biome.");
			recoverResources = Config("Difficulty", "RecoverResources", value: false, "Recover resources when pickables are removed with the cultivator. Applies to berries, mushrooms, and flowers.");
			resourcesSpawnEmpty = Config("Difficulty", "ResourcesSpawnEmpty", value: false, "Specifies whether resources should spawn empty or full. Applies to berry bushes, mushrooms, flowers, and debris.");
			enemiesTargetPieces = Config("Difficulty", "EnemiesTargetPieces", value: true, "When enabled, enemies may target and attack player placed resources added by the mod. If this setting is changed, pre-existing placed pieces will not be affected until the world/server is reloaded.");
			raspberryCost = Config("Berries", "RaspberryCost", 5, "Number of raspberries required to place a raspberry bush. Set to 0 to disable the ability to plant this resource.");
			blueberryCost = Config("Berries", "BlueberryCost", 5, "Number of blueberries required to place a blueberry bush. Set to 0 to disable the ability to plant this resource.");
			cloudberryCost = Config("Berries", "CloudberryCost", 5, "Number of cloudberries required to place a cloudberry bush. Set to 0 to disable the ability to plant this resource.");
			raspberryRespawnTime = Config("Berries", "RaspberryRespawnTime", 300, "Number of minutes it takes for a raspberry bush to respawn berries.");
			blueberryRespawnTime = Config("Berries", "BlueberryRespawnTime", 300, "Number of minutes it takes for a blueberry bush to respawn berries.");
			cloudberryRespawnTime = Config("Berries", "CloudberryRespawnTime", 300, "Number of minutes it takes for a cloudberry bush to respawn berries.");
			raspberryReturn = Config("Berries", "RaspberryReturn", 1, "Number of berries a raspberry bush will spawn.");
			blueberryReturn = Config("Berries", "BlueberryReturn", 1, "Number of berries a blueberry bush will spawn.");
			cloudberryReturn = Config("Berries", "CloudberryReturn", 1, "Number of berries a cloudberry bush will spawn.");
			enableCropOverrides = Config("Crops", "EnableCropOverrides", value: false, new ConfigDescription("Enables the [Crops] section of this config.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 28
				}
			}));
			cropMinScale = Config("Crops", "CropMinScale", 0.9f, new ConfigDescription("The minimum scaling factor used to scale crops upon growth.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			cropMaxScale = Config("Crops", "CropMaxScale", 1.1f, new ConfigDescription("The maximum scaling factor used to scale crops upon growth.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			cropGrowTimeMin = Config("Crops", "CropGrowTimeMin", 4000f, new ConfigDescription("Minimum number of seconds it takes for crops to grow (will take at least 10 seconds after planting to grow).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			cropGrowTimeMax = Config("Crops", "CropGrowTimeMax", 5000f, new ConfigDescription("Maximum number of seconds it takes for crops to grow (will take at least 10 seconds after planting to grow).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			cropGrowRadius = Config("Crops", "CropGrowRadius", 0.5f, new ConfigDescription("Radius of free space required for crops to grow.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			cropRequireCultivation = Config("Crops", "CropsRequireCultivation", value: true, new ConfigDescription("Crops can only be planted on cultivated ground.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] }));
			cropRequireSunlight = Config("Crops", "CropsRequireSunlight", value: true, new ConfigDescription("Crops can only grow under an open sky.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] }));
			cropRequireGrowthSpace = Config("Crops", "CropsRequireGrowthSpace", value: true, new ConfigDescription("Crops require space to grow. This setting overrides the CropGrowRadius setting but without altering it, allowing grid spacing mods to continue functioning.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] }));
			enemiesTargetCrops = Config("Crops", "EnemiesTargetCrops", value: true, new ConfigDescription("Determines whether enemies will target and attack crops. If this setting is changed, pre-existing placed crops will not be affected until the world/server is reloaded.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[1] }));
			barleyCost = Config("Crops", "BarleyCost", 1, new ConfigDescription("Resource cost of planting barley.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			barleyReturn = Config("Crops", "BarleyReturn", 2, new ConfigDescription("Resources gained upon harvesting barley (does not apply to wild barley).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			carrotCost = Config("Crops", "CarrotCost", 1, new ConfigDescription("Resource cost of planting carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			carrotReturn = Config("Crops", "CarrotReturn", 1, new ConfigDescription("Resources gained upon harvesting carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			flaxCost = Config("Crops", "FlaxCost", 1, new ConfigDescription("Resource cost of planting flax.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			flaxReturn = Config("Crops", "FlaxReturn", 2, new ConfigDescription("Resources gained upon harvesting flax (does not apply to wild flax).", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			onionCost = Config("Crops", "OnionCost", 1, new ConfigDescription("Resource cost of planting onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			onionReturn = Config("Crops", "OnionReturn", 1, new ConfigDescription("Resources gained upon harvesting onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedCarrotCost = Config("Crops", "SeedCarrotCost", 1, new ConfigDescription("Resource cost of planting seed carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedCarrotReturn = Config("Crops", "SeedCarrotReturn", 3, new ConfigDescription("Resources gained upon harvesting seed carrots.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedOnionCost = Config("Crops", "SeedOnionCost", 1, new ConfigDescription("Resource cost of planting seed onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedOnionReturn = Config("Crops", "SeedOnionReturn", 3, new ConfigDescription("Resources gained upon harvesting seed onions.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedTurnipCost = Config("Crops", "SeedTurnipCost", 1, new ConfigDescription("Resource cost of planting seed turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			seedTurnipReturn = Config("Crops", "SeedTurnipReturn", 3, new ConfigDescription("Resources gained upon harvesting seed turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			turnipCost = Config("Crops", "TurnipCost", 1, new ConfigDescription("Resource cost of planting turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			turnipReturn = Config("Crops", "TurnipReturn", 1, new ConfigDescription("Resources gained upon harvesting turnips.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			magecapCost = Config("Crops", "MagecapCost", 1, new ConfigDescription("Resource cost of planting magecap.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			magecapReturn = Config("Crops", "MagecapReturn", 3, new ConfigDescription("Resources gained upon harvesting magecap.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			jotunPuffsCost = Config("Crops", "JotunPuffsCost", 1, new ConfigDescription("Resource cost of planting Jotun puffs.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			jotunPuffsReturn = Config("Crops", "JotunPuffsReturn", 3, new ConfigDescription("Resources gained upon harvesting Jotun puffs.", (AcceptableValueBase)null, new object[1] { cropSettingAttributes[0] }));
			pickableBranchCost = Config("Debris", "PickableBranchCost", 5, "Amount of wood required to place branch debris. Set to 0 to disable the ability to plant this resource.");
			pickableBranchReturn = Config("Debris", "PickableBranchReturn", 1, "Amount of wood that branch debris drops when picked.");
			pickableStoneCost = Config("Debris", "PickableStoneCost", 1, "Amount of stone required to place stone debris. Set to 0 to disable the ability to plant this resource.");
			pickableStoneReturn = Config("Debris", "PickableStoneReturn", 1, "Amount of stones that stone debris drops when picked.");
			pickableFlintCost = Config("Debris", "PickableFlintCost", 5, "Amount of flint required to place flint debris. Set to 0 to disable the ability to plant this resource.");
			pickableFlintReturn = Config("Debris", "PickableFlintReturn", 1, "Amount of flint that flint debris drops when picked.");
			mushroomCost = Config("Mushrooms", "MushroomCost", 5, "Number of mushrooms required to place a pickable mushroom spawner. Set to 0 to disable the ability to plant this resource.");
			yellowMushroomCost = Config("Mushrooms", "YellowMushroomCost", 5, "Number of yellow mushrooms required to place a pickable yellow mushroom spawner. Set to 0 to disable the ability to plant this resource.");
			blueMushroomCost = Config("Mushrooms", "BlueMushroomCost", 5, "Number of blue mushrooms required to place a pickable blue mushroom spawner. Set to 0 to disable the ability to plant this resource.");
			mushroomRespawnTime = Config("Mushrooms", "MushroomRespawnTime", 240, "Number of minutes it takes for mushrooms to respawn.");
			yellowMushroomRespawnTime = Config("Mushrooms", "YellowMushroomRespawnTime", 240, "Number of minutes it takes for yellow mushrooms to respawn.");
			blueMushroomRespawnTime = Config("Mushrooms", "BlueMushroomRespawnTime", 240, "Number of minutes it takes for blue mushrooms to respawn.");
			mushroomReturn = Config("Mushrooms", "MushroomReturn", 1, "Number of mushrooms a pickable mushroom spawner will spawn.");
			yellowMushroomReturn = Config("Mushrooms", "YellowMushroomReturn", 1, "Number of yellow mushrooms a pickable yellow mushroom spawner will spawn.");
			blueMushroomReturn = Config("Mushrooms", "BlueMushroomReturn", 1, "Number of blue mushrooms a pickable blue mushroom spawner will spawn.");
			thistleCost = Config("Flowers", "ThistleCost", 5, "Number of thistle required to place a pickable thistle spawner. Set to 0 to disable the ability to plant this resource.");
			dandelionCost = Config("Flowers", "DandelionCost", 5, "Number of dandelion required to place a pickable dandelion spawner. Set to 0 to disable the ability to plant this resource.");
			thistleRespawnTime = Config("Flowers", "ThistleRespawnTime", 240, "Number of minutes it takes for thistle to respawn.");
			dandelionRespawnTime = Config("Flowers", "DandelionRespawnTime", 240, "Number of minutes it takes for dandelion to respawn.");
			thistleReturn = Config("Flowers", "ThistleReturn", 1, "Number of thistle a pickable thistle spawner will spawn.");
			dandelionReturn = Config("Flowers", "DandelionReturn", 1, "Number of dandelion a pickable dandelion spawner will spawn.");
			birchMinScale = Config("Saplings", "BirchMinScale", 0.5f, "The minimum scaling factor used to scale a birch tree upon growth.");
			birchMaxScale = Config("Saplings", "BirchMaxScale", 1f, "The maximum scaling factor used to scale a birch tree upon growth.");
			oakMinScale = Config("Saplings", "OakMinScale", 0.7f, "The minimum scaling factor used to scale an oak tree upon growth.");
			oakMaxScale = Config("Saplings", "OakMaxScale", 0.9f, "The maximum scaling factor used to scale an oak tree upon growth.");
			ancientMinScale = Config("Saplings", "AncientMinScale", 0.5f, "The minimum scaling factor used to scale an ancient tree upon growth.");
			ancientMaxScale = Config("Saplings", "AncientMaxScale", 2f, "The maximum scaling factor used to scale an ancient tree upon growth.");
			birchGrowthTime = Config("Saplings", "BirchGrowthTime", 3000f, "Number of seconds it takes for a birch tree to grow from a birch sapling (will take at least 10 seconds after planting to grow).");
			oakGrowthTime = Config("Saplings", "OakGrowthTime", 3000f, "Number of seconds it takes for an oak tree to grow from an oak sapling (will take at least 10 seconds after planting to grow).");
			ancientGrowthTime = Config("Saplings", "AncientGrowthTime", 3000f, "Number of seconds it takes for an ancient tree to grow from an ancient sapling (will take at least 10 seconds after planting to grow).");
			birchGrowRadius = Config("Saplings", "BirchGrowRadius", 2f, "Radius of free space required for a birch sapling to grow.");
			oakGrowRadius = Config("Saplings", "OakGrowRadius", 3f, "Radius of free space required for an oak sapling to grow.");
			ancientGrowRadius = Config("Saplings", "AncientGrowRadius", 2f, "Radius of free space required for an ancient sapling to grow.");
			beechGrowthTime = Config("Saplings", "BeechGrowthTime", 3000f, "Number of seconds it takes for a beech tree to grow from a beech sapling (will take at least 10 seconds after planting to grow).");
			pineGrowthTime = Config("Saplings", "PineGrowthTime", 3000f, "Number of seconds it takes for a pine tree to grow from a pine sapling (will take at least 10 seconds after planting to grow).");
			firGrowthTime = Config("Saplings", "FirGrowthTime", 3000f, "Number of seconds it takes for a fir tree to grow from a fir sapling (will take at least 10 seconds after planting to grow).");
			beechMinScale = Config("Saplings", "BeechMinScale", 0.8f, "The minimum scaling factor used to scale a beech tree upon growth.");
			beechMaxScale = Config("Saplings", "BeechMaxScale", 1.5f, "The maximum scaling factor used to scale a beech tree upon growth.");
			pineMinScale = Config("Saplings", "PineMinScale", 1.5f, "The minimum scaling factor used to scale a pine tree upon growth.");
			pineMaxScale = Config("Saplings", "PineMaxScale", 2.5f, "The maximum scaling factor used to scale a pine tree upon growth.");
			firMinScale = Config("Saplings", "FirMinScale", 1f, "The minimum scaling factor used to scale a fir tree upon growth.");
			firMaxScale = Config("Saplings", "FirMaxScale", 2.5f, "The maximum scaling factor used to scale a fir tree upon growth.");
			beechGrowRadius = Config("Saplings", "BeechGrowRadius", 2f, "Radius of free space required for a beech sapling to grow.");
			pineGrowRadius = Config("Saplings", "PineGrowRadius", 2f, "Radius of free space required for a pine sapling to grow.");
			firGrowRadius = Config("Saplings", "FirGrowRadius", 2f, "Radius of free space required for a fir sapling to grow.");
			yggaMinScale = Config("Saplings", "YggaMinScale", 0.5f, "The minimum scaling factor used to scale a ygga tree upon growth.");
			yggaMaxScale = Config("Saplings", "YggaMaxScale", 2f, "The minimum scaling factor used to scale a ygga tree upon growth.");
			yggaGrowthTime = Config("Saplings", "YggaGrowthTime", 3000f, "Number of seconds it takes for a ygga tree to grow from a ygga sapling (will take at least 10 seconds after planting to grow).");
			yggaGrowRadius = Config("Saplings", "YggaGrowRadius", 2f, "Radius of free space required for a ygga sapling to grow.");
			autumnBirchMinScale = Config("Saplings", "AutumnBirchMinScale", 0.5f, "The minimum scaling factor used to scale an autumn birch tree upon growth.");
			autumnBirchMaxScale = Config("Saplings", "AutumnBirchMaxScale", 1f, "The minimum scaling factor used to scale an autumn birch tree upon growth.");
			autumnBirchGrowthTime = Config("Saplings", "AutumnBirchGrowthTime", 3000f, "Number of seconds it takes for an autumn birch tree to grow from an autumn birch sapling (will take at least 10 seconds after planting to grow).");
			autumnBirchGrowRadius = Config("Saplings", "AutumnBirchGrowRadius", 2f, "Radius of free space required for an autumn birch sapling to grow.");
			enableSeedOverrides = Config("Seeds", "EnableSeedOverrides", value: false, new ConfigDescription("Enables the [Seeds] section of this config.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 10
				}
			}));
			seedDropMin = Config("Seeds", "seedDropMin", 1, new ConfigDescription("Determines minimum amount of seeds that can drop when trees drop seeds.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			seedDropMax = Config("Seeds", "seedDropMax", 2, new ConfigDescription("Determines maximum amount of seeds that can drop when trees drop seeds.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			treeDropMin = Config("Seeds", "treeDropMin", 1, new ConfigDescription("Determines minimum amount of times a destroyed tree will attempt to select a drop from its drop table.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			treeDropMax = Config("Seeds", "treeDropMax", 3, new ConfigDescription("Determines (maximum amount of times - 1) a destroyed tree will attempt to select a drop from its drop table.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			dropChance = Config("Seeds", "dropChance", 0.5f, new ConfigDescription("Chance that items will drop from trees when destroyed. Default value 0.5f (50%). Set between 0 and 1f.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			oneOfEach = Config("Seeds", "oneOfEach", value: false, new ConfigDescription("When enabled, destroyed trees will not drop the same item from its drop table more than once.", (AcceptableValueBase)null, new object[1] { seedSettingAtrributes }));
			enablePickableTimers = Config("UI", "EnablePickableTimers", value: true, "Enables display of growth time remaining on pickable resources.", synchronizedSetting: false);
			enablePlantTimers = Config("UI", "EnablePlantTimers", value: true, "Enables display of growth time remaining on planted resources, such as crops and saplings.", synchronizedSetting: false);
			growthAsPercentage = Config("UI", "GrowthAsPercentage", value: false, "Enables display of growth time as a percentage instead of time remaining.", synchronizedSetting: false);
			configFile.Save();
			configFile.SaveOnConfigSet = true;
			showPickableSpawners.SettingChanged += PlantEverything.CoreSettingChanged;
			enableMiscFlora.SettingChanged += PlantEverything.CoreSettingChanged;
			snappableVines.SettingChanged += PlantEverything.CoreSettingChanged;
			enableExtraResources.SettingChanged += PlantEverything.ExtraResourcesFileOrSettingChanged;
			disabledResourceNames.SettingChanged += PlantEverything.CoreSettingChanged;
			requireCultivation.SettingChanged += PlantEverything.CoreSettingChanged;
			placeAnywhere.SettingChanged += PlantEverything.CoreSettingChanged;
			enforceBiomes.SettingChanged += PlantEverything.CoreSettingChanged;
			enforceBiomesVanilla.SettingChanged += PlantEverything.CoreSettingChanged;
			recoverResources.SettingChanged += PlantEverything.CoreSettingChanged;
			enemiesTargetPieces.SettingChanged += PlantEverything.PieceSettingChanged;
			raspberryCost.SettingChanged += PlantEverything.PieceSettingChanged;
			blueberryCost.SettingChanged += PlantEverything.PieceSettingChanged;
			cloudberryCost.SettingChanged += PlantEverything.PieceSettingChanged;
			raspberryRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			blueberryRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			cloudberryRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			raspberryReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			blueberryReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			cloudberryReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			enableCropOverrides.SettingChanged += PlantEverything.CropSettingChanged;
			cropMinScale.SettingChanged += PlantEverything.CropSettingChanged;
			cropMaxScale.SettingChanged += PlantEverything.CropSettingChanged;
			cropGrowTimeMin.SettingChanged += PlantEverything.CropSettingChanged;
			cropGrowTimeMax.SettingChanged += PlantEverything.CropSettingChanged;
			cropGrowRadius.SettingChanged += PlantEverything.CropSettingChanged;
			cropRequireCultivation.SettingChanged += PlantEverything.CropSettingChanged;
			enemiesTargetCrops.SettingChanged += PlantEverything.CropSettingChanged;
			barleyCost.SettingChanged += PlantEverything.CropSettingChanged;
			barleyReturn.SettingChanged += PlantEverything.CropSettingChanged;
			carrotCost.SettingChanged += PlantEverything.CropSettingChanged;
			carrotReturn.SettingChanged += PlantEverything.CropSettingChanged;
			flaxCost.SettingChanged += PlantEverything.CropSettingChanged;
			flaxReturn.SettingChanged += PlantEverything.CropSettingChanged;
			onionCost.SettingChanged += PlantEverything.CropSettingChanged;
			onionReturn.SettingChanged += PlantEverything.CropSettingChanged;
			seedCarrotCost.SettingChanged += PlantEverything.CropSettingChanged;
			seedCarrotReturn.SettingChanged += PlantEverything.CropSettingChanged;
			seedOnionCost.SettingChanged += PlantEverything.CropSettingChanged;
			seedOnionReturn.SettingChanged += PlantEverything.CropSettingChanged;
			seedTurnipCost.SettingChanged += PlantEverything.CropSettingChanged;
			seedTurnipReturn.SettingChanged += PlantEverything.CropSettingChanged;
			turnipCost.SettingChanged += PlantEverything.CropSettingChanged;
			turnipReturn.SettingChanged += PlantEverything.CropSettingChanged;
			pickableBranchCost.SettingChanged += PlantEverything.PieceSettingChanged;
			pickableBranchReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			pickableStoneCost.SettingChanged += PlantEverything.PieceSettingChanged;
			pickableStoneReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			pickableFlintCost.SettingChanged += PlantEverything.PieceSettingChanged;
			pickableFlintReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			mushroomCost.SettingChanged += PlantEverything.PieceSettingChanged;
			yellowMushroomCost.SettingChanged += PlantEverything.PieceSettingChanged;
			blueMushroomCost.SettingChanged += PlantEverything.PieceSettingChanged;
			mushroomRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			yellowMushroomRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			blueMushroomRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			mushroomReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			yellowMushroomReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			blueMushroomReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			thistleCost.SettingChanged += PlantEverything.PieceSettingChanged;
			dandelionCost.SettingChanged += PlantEverything.PieceSettingChanged;
			thistleRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			dandelionRespawnTime.SettingChanged += PlantEverything.PieceSettingChanged;
			thistleReturn.SettingChanged += PlantEverything.PieceSettingChanged;
			dandelion