Decompiled source of Fertilizer v1.2.0

Fertilizer.dll

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

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Fertilizer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+7d1b52e75c7e338fb536dd62114732132e31b572")]
[assembly: AssemblyProduct("Fertilizer")]
[assembly: AssemblyTitle("Fertilizer")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Fertilizer
{
	internal class FertilizedScale : MonoBehaviour
	{
	}
	internal static class Fertilization
	{
		internal static void Apply(Plant plant)
		{
			if ((Object)(object)plant == (Object)null || !ModConfig.EnableMod.Value || (Object)(object)((Component)plant).GetComponent<FertilizedScale>() != (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)plant).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO == null)
			{
				return;
			}
			int num = zDO.GetInt(FertilizerPiece.FertilizedHash, 0);
			if (num > 0)
			{
				Tier tier = Tier.ByLevel(num);
				if (tier?.Reduction != null)
				{
					float num2 = 1f - Mathf.Clamp(tier.Reduction.Value, 0f, 99f) / 100f;
					plant.m_growTime *= num2;
					plant.m_growTimeMax *= num2;
					((Component)plant).gameObject.AddComponent<FertilizedScale>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(Plant), "GetHoverText")]
	internal static class PlantHoverTextPatch
	{
		private static void Postfix(Plant __instance, ref string __result)
		{
			if (!ModConfig.EnableMod.Value || string.IsNullOrEmpty(__result))
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			int num = component.GetZDO().GetInt(FertilizerPiece.FertilizedHash, 0);
			if (num > 0)
			{
				Tier tier = Tier.ByLevel(num);
				if (tier != null)
				{
					__result = __result + "\n" + tier.DisplayName;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Plant), "Awake")]
	internal static class PlantAwakePatch
	{
		private static void Postfix(Plant __instance)
		{
			Fertilization.Apply(__instance);
		}
	}
	[HarmonyPatch(typeof(Plant), "SUpdate")]
	internal static class PlantSUpdatePatch
	{
		private static void Prefix(Plant __instance)
		{
			Fertilization.Apply(__instance);
		}
	}
	internal class FertilizerPiece : MonoBehaviour, IPlaced
	{
		internal static readonly int FertilizedHash = StringExtensionMethods.GetStableHashCode("jelaw_fert_tier");

		internal static readonly Func<Plant, float> GetGrowTime = AccessTools.MethodDelegate<Func<Plant, float>>(AccessTools.Method(typeof(Plant), "GetGrowTime", (Type[])null, (Type[])null), (object)null, true);

		private static int _mask;

		private static int Mask
		{
			get
			{
				if (_mask == 0)
				{
					return _mask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "item" });
				}
				return _mask;
			}
		}

		internal static float Radius()
		{
			Player localPlayer = Player.m_localPlayer;
			float num = (((Object)(object)localPlayer != (Object)null) ? ((Character)localPlayer).GetSkillFactor((SkillType)106) : 0f);
			return Mathf.Lerp(ModConfig.RadiusAtSkill0.Value, ModConfig.RadiusAtSkill100.Value, num);
		}

		private void Awake()
		{
		}

		public void OnPlaced()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMod.Value)
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
				return;
			}
			int currentTier = Plugin.CurrentTier;
			float num = Radius();
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, num, Mask);
			for (int i = 0; i < array.Length; i++)
			{
				Plant componentInParent = ((Component)array[i]).GetComponentInParent<Plant>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					continue;
				}
				if ((int)componentInParent.GetStatus() != 0)
				{
					num3++;
					continue;
				}
				ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					continue;
				}
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				if (!component.IsOwner())
				{
					num6++;
					continue;
				}
				ZDO zDO = component.GetZDO();
				if (zDO.GetInt(FertilizedHash, 0) != 0)
				{
					num4++;
					Float(componentInParent, (TextType)0, "$jelaw_already_fertilized");
					continue;
				}
				long ticks = zDO.GetLong(ZDOVars.s_plantTime, ZNet.instance.GetTime().Ticks);
				if ((ZNet.instance.GetTime() - new DateTime(ticks)).TotalSeconds >= (double)GetGrowTime(componentInParent))
				{
					num5++;
					continue;
				}
				zDO.Set(FertilizedHash, currentTier, false);
				Fertilization.Apply(componentInParent);
				Float(componentInParent, (TextType)7, $"+{PercentFor(currentTier):0}%");
				num2++;
			}
			if (num2 > 0)
			{
				PlayEffect();
			}
			else
			{
				Refund(currentTier);
			}
			if (ModConfig.DebugLogging.Value)
			{
				float num7 = PercentFor(currentTier);
				Logger.LogInfo((object)($"Tier {currentTier} ({num7:0}%) fertilized {num2} plant(s) within {num:0.0}m " + $"(skipped: {num4} already fertilized, {num3} unhealthy, " + $"{num5} fully grown, {num6} not owned)"));
			}
			ZNetScene.instance.Destroy(((Component)this).gameObject);
		}

		private static void Refund(int tierLevel)
		{
			Player localPlayer = Player.m_localPlayer;
			ItemDrop val = Tier.ByLevel(tierLevel)?.Drop;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)val == (Object)null))
			{
				if (!((Humanoid)localPlayer).GetInventory().AddItem(((Component)val).gameObject, 1))
				{
					Logger.LogWarning((object)"Nothing was fertilized and the bone meal could not be returned - inventory full.");
				}
				else if (ModConfig.DebugLogging.Value)
				{
					Logger.LogInfo((object)"Nothing fertilized; bone meal returned.");
				}
			}
		}

		private static float PercentFor(int tierLevel)
		{
			return (Tier.ByLevel(tierLevel)?.Reduction?.Value).GetValueOrDefault();
		}

		private static void Float(Plant plant, TextType type, string text)
		{
			//IL_0020: 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)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.ShowFloatingText.Value && !((Object)(object)DamageText.instance == (Object)null))
			{
				DamageText.instance.ShowText(type, ((Component)plant).transform.position + Vector3.up * 0.4f, Localization.instance.Localize(text), true);
			}
		}

		private void PlayEffect()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			string value = ModConfig.PlaceEffect.Value;
			if (string.IsNullOrEmpty(value))
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(value);
			if ((Object)(object)prefab == (Object)null)
			{
				if (ModConfig.DebugLogging.Value)
				{
					Logger.LogWarning((object)("Effect prefab '" + value + "' not found."));
				}
			}
			else
			{
				Object.Instantiate<GameObject>(prefab, ((Component)this).transform.position, Quaternion.identity);
			}
		}
	}
	internal static class Icons
	{
		internal static Sprite Recolour(Sprite source, Color tint)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			Texture2D texture = source.texture;
			Rect textureRect = source.textureRect;
			int num = Mathf.Max(1, (int)((Rect)(ref textureRect)).width);
			int num2 = Mathf.Max(1, (int)((Rect)(ref textureRect)).height);
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)5, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				Color[] pixels = val.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val2 = pixels[i];
					float num3 = val2.r * 0.299f + val2.g * 0.587f + val2.b * 0.114f;
					pixels[i] = new Color(num3 * tint.r, num3 * tint.g, num3 * tint.b, val2.a);
				}
				val.SetPixels(pixels);
				val.Apply();
				return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), source.pixelsPerUnit);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Could not tint icon, keeping the original: " + ex.Message));
				return null;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}
	}
	internal static class ModConfig
	{
		internal static ConfigEntry<bool> EnableMod;

		internal static ConfigEntry<float> RadiusAtSkill0;

		internal static ConfigEntry<float> RadiusAtSkill100;

		internal static ConfigEntry<bool> ShowFloatingText;

		internal static ConfigEntry<string> PlaceEffect;

		internal static ConfigEntry<string> BasePrefab;

		internal static ConfigEntry<bool> DebugLogging;

		private static ConfigurationManagerAttributes Synced => new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};

		internal static void Bind(ConfigFile cfg)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			EnableMod = cfg.Bind<bool>("General", "EnableMod", true, new ConfigDescription("Master switch.", (AcceptableValueBase)null, new object[1] { Synced }));
			RadiusAtSkill0 = cfg.Bind<float>("Area", "RadiusAtSkill0", 1.5f, new ConfigDescription("Radius in metres covered at Farming skill 0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), new object[1] { Synced }));
			RadiusAtSkill100 = cfg.Bind<float>("Area", "RadiusAtSkill100", 4f, new ConfigDescription("Radius in metres covered at Farming skill 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), new object[1] { Synced }));
			float[] array = new float[3] { 25f, 50f, 75f };
			Tier[] all = Tier.All;
			foreach (Tier tier in all)
			{
				tier.Reduction = cfg.Bind<float>("Fertilizer", $"Reduction{tier.Level} - {tier.DisplayName}", array[tier.Level - 1], new ConfigDescription("Percent of remaining grow time removed by " + tier.DisplayName + ".", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[1] { Synced }));
			}
			ShowFloatingText = cfg.Bind<bool>("Feedback", "ShowFloatingText", true, "Shows a floating figure over each plant as it is fertilized, and over any that were already done.");
			PlaceEffect = cfg.Bind<string>("Feedback", "PlaceEffect", "vfx_Place_replant", "Vanilla effect prefab played where the fertilizer is spread. Blank for none.");
			BasePrefab = cfg.Bind<string>("Appearance", "BasePrefab", "cultivate_v2,cultivate,wood_pole", "Which in-game object the placeable borrows its look and ground indicator from, as a comma-separated list - the first one that exists is used. There is rarely any reason to change this.");
			DebugLogging = cfg.Bind<bool>("Debug", "DebugLogging", false, "Logs how many plants each placement affected, and why any were skipped.");
		}
	}
	[BepInPlugin("elric.Fertilizer", "Fertilizer", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "elric.Fertilizer";

		public const string PluginName = "Fertilizer";

		public const string PluginVersion = "1.2.0";

		private const string ItemBasePrefab = "PowderedDragonEgg";

		private const string PiecePrefabName = "jelaw_fertilizer_piece";

		internal static int CurrentTier = 1;

		private static int _lastLoggedTier = -1;

		private static float _nativeRadius = 2f;

		private static Vector3 _nativeGhostScale = Vector3.one;

		private static readonly FieldRef<Player, GameObject> GhostOf = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost");

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			new Harmony("elric.Fertilizer").PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += AddContent;
		}

		private void Update()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Tier tier = Selected(localPlayer) ?? Tier.All[0];
			CurrentTier = tier.Level;
			if ((Object)(object)tier.Drop == (Object)null)
			{
				return;
			}
			Piece selectedPiece = localPlayer.GetSelectedPiece();
			if ((Object)(object)selectedPiece == (Object)null || Utils.GetPrefabName(((Component)selectedPiece).gameObject) != "jelaw_fertilizer_piece")
			{
				return;
			}
			if (selectedPiece.m_resources == null || selectedPiece.m_resources.Length == 0)
			{
				selectedPiece.m_resources = (Requirement[])(object)new Requirement[1]
				{
					new Requirement()
				};
				if (ModConfig.DebugLogging.Value)
				{
					Logger.LogInfo((object)"Fertilizer piece had no requirements; created one.");
				}
			}
			Requirement val = selectedPiece.m_resources[0];
			if (val == null)
			{
				val = new Requirement();
				selectedPiece.m_resources[0] = val;
			}
			val.m_resItem = tier.Drop;
			val.m_amount = 1;
			val.m_amountPerLevel = 0;
			val.m_recover = false;
			if (ModConfig.DebugLogging.Value && _lastLoggedTier != tier.Level)
			{
				_lastLoggedTier = tier.Level;
				Logger.LogInfo((object)("Held piece '" + Utils.GetPrefabName(((Component)selectedPiece).gameObject) + "' cost set to " + $"'{((Object)tier.Drop).name}' (tier {tier.Level})"));
			}
			ScaleGhost(localPlayer);
		}

		private static Tier Selected(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return null;
			}
			ItemData val = ((Humanoid)player).GetAmmoItem();
			if (val != null && (!inventory.ContainsItem(val) || val.m_shared.m_ammoType != "$ammo_fertilizer"))
			{
				val = null;
			}
			val = val ?? inventory.GetAmmoItem("$ammo_fertilizer", (string)null);
			if (val == null || (Object)(object)val.m_dropPrefab == (Object)null)
			{
				return null;
			}
			return Tier.ByItemName(((Object)val.m_dropPrefab).name);
		}

		private static string FirstExisting(string names)
		{
			if (string.IsNullOrEmpty(names))
			{
				return null;
			}
			string[] array = names.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && (Object)(object)Resolve(text) != (Object)null)
				{
					return text;
				}
			}
			return null;
		}

		private static void CaptureIndicatorScale(GameObject prefab)
		{
			//IL_006f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			TerrainOp componentInChildren = prefab.GetComponentInChildren<TerrainOp>(true);
			if ((Object)(object)componentInChildren != (Object)null && componentInChildren.GetRadius() > 0f)
			{
				_nativeRadius = componentInChildren.GetRadius();
			}
			else
			{
				TerrainModifier componentInChildren2 = prefab.GetComponentInChildren<TerrainModifier>(true);
				if ((Object)(object)componentInChildren2 != (Object)null && componentInChildren2.GetRadius() > 0f)
				{
					_nativeRadius = componentInChildren2.GetRadius();
				}
			}
			Transform val = prefab.transform.Find("_GhostOnly");
			if ((Object)(object)val != (Object)null)
			{
				_nativeGhostScale = val.localScale;
			}
			if (ModConfig.DebugLogging.Value)
			{
				Logger.LogInfo((object)($"Indicator native radius {_nativeRadius:0.##}m at scale {_nativeGhostScale}" + (((Object)(object)val == (Object)null) ? " (no _GhostOnly child found)" : "")));
			}
		}

		internal static GameObject Resolve(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab;
			}
			if (ZNetScene.instance?.m_prefabs == null)
			{
				return null;
			}
			foreach (GameObject prefab2 in ZNetScene.instance.m_prefabs)
			{
				if ((Object)(object)prefab2 != (Object)null && ((Object)prefab2).name == name)
				{
					return prefab2;
				}
			}
			return null;
		}

		private static void ScaleGhost(Player player)
		{
			//IL_0049: 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)
			GameObject val = GhostOf.Invoke(player);
			if (!((Object)(object)val == (Object)null))
			{
				Transform val2 = val.transform.Find("_GhostOnly");
				if (!((Object)(object)val2 == (Object)null))
				{
					float num = FertilizerPiece.Radius() / Mathf.Max(_nativeRadius, 0.01f);
					val2.localScale = _nativeGhostScale * num;
				}
			}
		}

		private void AddContent()
		{
			AddLocalization();
			Tier[] all = Tier.All;
			for (int i = 0; i < all.Length; i++)
			{
				AddMeal(all[i]);
			}
			AddPlaceable();
			PrefabManager.OnVanillaPrefabsAvailable -= AddContent;
		}

		private static void AddMeal(Tier tier)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(tier.ItemName, "PowderedDragonEgg");
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)("Could not clone 'PowderedDragonEgg' for " + tier.DisplayName + "."));
				return;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			component.m_itemData.m_shared.m_name = "$" + tier.ItemName;
			component.m_itemData.m_shared.m_description = "$" + tier.ItemName + "_desc";
			component.m_itemData.m_shared.m_itemType = (ItemType)9;
			component.m_itemData.m_shared.m_ammoType = "$ammo_fertilizer";
			component.m_itemData.m_shared.m_maxStackSize = 50;
			Sprite[] icons = component.m_itemData.m_shared.m_icons;
			if (icons != null && icons.Length != 0)
			{
				Sprite val2 = Icons.Recolour(icons[0], tier.Tint);
				if ((Object)(object)val2 != (Object)null)
				{
					component.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
				}
			}
			ItemConfig val3 = new ItemConfig
			{
				Amount = 2,
				CraftingStation = CraftingStations.Workbench,
				Requirements = ((IEnumerable<(string, int)>)tier.Ingredients).Select((Func<(string, int), RequirementConfig>)(((string Item, int Amount) i) => new RequirementConfig(i.Item, i.Amount, 0, true))).ToArray()
			};
			ItemManager.Instance.AddItem(new CustomItem(val, false, val3));
			tier.Drop = component;
		}

		private static void AddPlaceable()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			PieceConfig val = new PieceConfig();
			val.Name = "$jelaw_fertilize";
			val.Description = "$jelaw_fertilize_desc";
			val.PieceTable = PieceTables.Cultivator;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1]
			{
				new RequirementConfig(Tier.All[0].ItemName, 1, 0, true)
			};
			PieceConfig val2 = val;
			string text = FirstExisting(ModConfig.BasePrefab.Value);
			bool num = text != null;
			if (ModConfig.DebugLogging.Value)
			{
				Logger.LogInfo((object)("Fertilizer base prefab: " + (text ?? "none - using a cube")));
			}
			CustomPiece val3;
			if (num)
			{
				val3 = new CustomPiece("jelaw_fertilizer_piece", text, val2);
			}
			else
			{
				Logger.LogWarning((object)("Base prefab '" + text + "' not found; falling back to a plain cube."));
				val3 = new CustomPiece("jelaw_fertilizer_piece", true, val2);
			}
			if ((Object)(object)val3.PiecePrefab == (Object)null)
			{
				Logger.LogError((object)"Could not create the fertilizer placeable.");
				return;
			}
			CaptureIndicatorScale(val3.PiecePrefab);
			StripInheritedBehaviour(val3.PiecePrefab);
			val3.PiecePrefab.AddComponent<FertilizerPiece>();
			PieceManager.Instance.AddPiece(val3);
			Piece component = val3.PiecePrefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				ItemDrop drop = Tier.All[0].Drop;
				if ((Object)(object)drop != (Object)null)
				{
					component.m_resources = (Requirement[])(object)new Requirement[1]
					{
						new Requirement
						{
							m_resItem = drop,
							m_amount = 1,
							m_amountPerLevel = 0,
							m_recover = false
						}
					};
				}
			}
			if (ModConfig.DebugLogging.Value && (Object)(object)component != (Object)null)
			{
				Requirement[] resources = component.m_resources;
				int num2 = ((resources != null) ? resources.Length : 0);
				string arg = ((num2 > 0 && (Object)(object)component.m_resources[0]?.m_resItem != (Object)null) ? ((Object)component.m_resources[0].m_resItem).name : "none");
				Logger.LogInfo((object)$"Fertilizer piece registered with {num2} requirement(s), first = {arg}");
			}
			if ((Object)(object)component != (Object)null)
			{
				component.m_craftingStation = null;
				component.m_groundOnly = false;
				component.m_notOnFloor = false;
				component.m_noInWater = false;
				component.m_onlyInTeleportArea = false;
				component.m_allowedInDungeons = true;
			}
		}

		private static void StripInheritedBehaviour(GameObject prefab)
		{
			PrivateArea[] componentsInChildren = prefab.GetComponentsInChildren<PrivateArea>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			Container[] componentsInChildren2 = prefab.GetComponentsInChildren<Container>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren2[i]);
			}
			CraftingStation[] componentsInChildren3 = prefab.GetComponentsInChildren<CraftingStation>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren3[i]);
			}
			TerrainOp[] componentsInChildren4 = prefab.GetComponentsInChildren<TerrainOp>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren4[i]);
			}
			TerrainModifier[] componentsInChildren5 = prefab.GetComponentsInChildren<TerrainModifier>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren5[i]);
			}
		}

		private static void AddLocalization()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "ammo_fertilizer", "Fertilizer" },
				{ "jelaw_fertilize", "Fertilize" },
				{ "jelaw_already_fertilized", "Already Fertilized" },
				{ "jelaw_fertilize_desc", "Spreads the selected bone meal. Covers a wider area as Farming rises." }
			};
			Tier[] all = Tier.All;
			foreach (Tier tier in all)
			{
				dictionary[tier.ItemName] = tier.DisplayName;
				dictionary[tier.ItemName + "_desc"] = tier.Description;
			}
			string text = "English";
			localization.AddTranslation(ref text, dictionary);
		}
	}
	internal class Tier
	{
		internal const string AmmoType = "$ammo_fertilizer";

		internal int Level;

		internal string ItemName;

		internal string DisplayName;

		internal string Description;

		internal ConfigEntry<float> Reduction;

		internal Color Tint;

		internal (string Item, int Amount)[] Ingredients;

		internal ItemDrop Drop;

		internal static readonly Tier[] All = new Tier[3]
		{
			new Tier
			{
				Level = 1,
				ItemName = "jelaw_bonemeal",
				DisplayName = "Bone Meal",
				Description = "Ground bone. Hastens a crop a little.",
				Tint = new Color(1f, 0.97f, 0.9f),
				Ingredients = new(string, int)[1] { ("BoneFragments", 5) }
			},
			new Tier
			{
				Level = 2,
				ItemName = "jelaw_bonemeal_enriched",
				DisplayName = "Enriched Bone Meal",
				Description = "Bone meal ground with fang and charcoal.",
				Tint = new Color(0.62f, 0.6f, 0.58f),
				Ingredients = new(string, int)[3]
				{
					("jelaw_bonemeal", 1),
					("WolfFang", 1),
					("Coal", 1)
				}
			},
			new Tier
			{
				Level = 3,
				ItemName = "jelaw_bonemeal_enhanced",
				DisplayName = "Enhanced Bone Meal",
				Description = "Bone meal ground with charred bone and sap.",
				Tint = new Color(0.22f, 0.31f, 0.2f),
				Ingredients = new(string, int)[3]
				{
					("jelaw_bonemeal", 1),
					("CharredBone", 1),
					("Sap", 1)
				}
			}
		};

		internal static Tier ByItemName(string prefabName)
		{
			Tier[] all = All;
			foreach (Tier tier in all)
			{
				if (tier.ItemName == prefabName)
				{
					return tier;
				}
			}
			return null;
		}

		internal static Tier ByLevel(int level)
		{
			Tier[] all = All;
			foreach (Tier tier in all)
			{
				if (tier.Level == level)
				{
					return tier;
				}
			}
			return All[0];
		}
	}
}