Decompiled source of Pumpkin v0.2.1

BepInEx/plugins/SmeagsPumpkin/SmeagsPumpkin.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
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.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SmeagsPumpkin")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1")]
[assembly: AssemblyProduct("SmeagsPumpkin")]
[assembly: AssemblyTitle("SmeagsPumpkin")]
[assembly: AssemblyVersion("0.2.1.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 SmeagsPumpkin
{
	[BepInPlugin("smeagsmods.pumpkin", "Smeags Pumpkin", "0.2.1")]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class FoodBalance
		{
			internal ConfigEntry<float> health;

			internal ConfigEntry<float> stamina;

			internal ConfigEntry<float> duration;

			internal ConfigEntry<float> regen;

			internal ConfigEntry<int>[] costs;

			internal GameObject item;

			internal Recipe recipe;
		}

		public const string Id = "smeagsmods.pumpkin";

		public static Plugin Instance;

		public ConfigEntry<float> GrowMin;

		public ConfigEntry<float> GrowMax;

		public ConfigEntry<float> Radius;

		public ConfigEntry<float> StarterChance;

		public ConfigEntry<int> FruitYield;

		public ConfigEntry<int> SeedYield;

		public ConfigEntry<bool> StarterDrops;

		internal GameObject fruit;

		internal GameObject seed;

		internal GameObject fruitPlant;

		internal GameObject seedPlant;

		internal GameObject fruitHarvest;

		internal GameObject seedHarvest;

		private Harmony harmony;

		private bool dirty;

		public const string MashId = "SmeagsPumpkin_HoneyedMash";

		public const string StewId = "SmeagsPumpkin_VenisonStew";

		public const string CarvedId = "SmeagsPumpkin_CarvedPumpkin";

		public const string LanternId = "SmeagsPumpkin_Lantern";

		public const string RoastedSeedsId = "SmeagsPumpkin_RoastedSeeds";

		private FoodBalance mash;

		private FoodBalance stew;

		private FoodBalance roasted;

		private ConfigEntry<float> fuelSeconds;

		private ConfigEntry<int> maxFuel;

		private ConfigEntry<int> carveCost;

		private GameObject carved;

		private GameObject lantern;

		private Recipe carvingRecipe;

		public bool Ready { get; private set; }

		private ConfigEntry<T> Entry<T>(string section, string key, T value, string description, AcceptableValueBase range = null)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private void Awake()
		{
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			Instance = this;
			BindKitchen();
			GrowMin = Entry("Farming", "GrowthSecondsMin", 4000f, "Initial crop growth minimum; native midpoint switches flowers to green fruit. Plant Everything may override.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 86400f));
			GrowMax = Entry("Farming", "GrowthSecondsMax", 5000f, "Native maximum, clamped no lower than minimum. Plant Everything may override.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 86400f));
			Radius = Entry("Farming", "GrowRadius", 0.7f, "Native spacing radius in metres. Plant Everything may override.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 3f));
			FruitYield = Entry("Farming", "PumpkinsPerHarvest", 1, "Base yield; native world drop modifiers and farming bonuses still apply.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20));
			SeedYield = Entry("Farming", "SeedsPerHarvest", 3, "Base seed yield; one pumpkin plants a seed crop.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50));
			StarterDrops = Entry("Acquisition", "BruteSeedDrops", value: true, "Add a renewable starter seed drop to Greydwarf Brutes. Disabling never unregisters existing items/crops.");
			StarterChance = Entry("Acquisition", "BruteSeedChance", 0.1f, "Chance for one seed per brute before native level/drop scaling. Initial configurable balance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f));
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				dirty = true;
			};
			harmony = new Harmony("smeagsmods.pumpkin");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += Register;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Slice 0.2.1: original art, native crops, food recipes and resin lantern; all peers require same mod version.");
		}

		private void Update()
		{
			if (dirty && Ready)
			{
				dirty = false;
				ApplyBalance();
			}
		}

		internal void Note(string s)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)s);
		}

		private GameObject Native(string name)
		{
			return PrefabManager.Instance.GetPrefab(name) ?? throw new InvalidOperationException("Missing native donor " + name);
		}

		private GameObject Clone(string name, GameObject donor)
		{
			return PrefabManager.Instance.CreateClonedPrefab(name, donor);
		}

		private void Register()
		{
			if (Ready)
			{
				return;
			}
			try
			{
				OriginalArt.NativeMaterial = Native("CarrotSeeds").GetComponentsInChildren<MeshRenderer>(true).SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials).First((Material m) => Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)m.shader));
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Original art native material: " + ((Object)OriginalArt.NativeMaterial).name + " / " + ((Object)OriginalArt.NativeMaterial.shader).name));
				seed = CreateItem("SmeagsPumpkin_Seeds", "CarrotSeeds", "Pumpkin seeds", "Plant with a Cultivator in cultivated soil.", "SeedItem", "SeedIcon", 0.1f);
				fruit = CreateItem("SmeagsPumpkin_Pumpkin", "CarrotSeeds", "Pumpkin", "A ripe pumpkin. Replant one to grow pumpkin seeds.", "PumpkinItem", "PumpkinIcon", 2f);
				GameObject val = Native("sapling_carrot");
				GameObject val2 = Native("sapling_seedcarrot");
				fruitHarvest = CreateHarvest("SmeagsPumpkin_FruitHarvest", val.GetComponent<Plant>().m_grownPrefabs[0], fruit, "FruitMature_Healthy", FruitYield.Value);
				seedHarvest = CreateHarvest("SmeagsPumpkin_SeedHarvest", val2.GetComponent<Plant>().m_grownPrefabs[0], seed, "SeedMature_Healthy", SeedYield.Value);
				fruitPlant = CreatePlant("SmeagsPumpkin_FruitPlant", val, seed, fruitHarvest, "Pumpkin", "Flowering vine, then green fruit, then ripe pumpkin.", "FruitFlowering", "FruitGrowing", "SeedIcon");
				seedPlant = CreatePlant("SmeagsPumpkin_SeedPlant", val2, fruit, seedHarvest, "Seed pumpkin", "Grow an older, mottled pumpkin to replenish seeds.", "SeedGrowing", "SeedMature", "PumpkinIcon");
				RegisterKitchen();
				Ready = true;
				ApplyBalance();
				PrefabManager.OnVanillaPrefabsAvailable -= Register;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered six inventory items, four crop prefabs, four recipes and one Hammer lantern.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Pumpkin registration failed: " + ex));
				throw;
			}
		}

		private GameObject CreateItem(string name, string donor, string label, string description, string model, string icon, float weight)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_0175: Expected O, but got Unknown
			GameObject val = Clone(name, Native(donor));
			OriginalArt.HideDonor(val);
			GameObject val2 = OriginalArt.Add(val, model);
			if (model == "SeedItem")
			{
				val2.transform.localScale = Vector3.one * 3f;
			}
			else
			{
				val2.transform.localPosition = new Vector3(-0.055f, 0f, 0.075f);
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			component.m_itemData.m_dropPrefab = val;
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = label;
			shared.m_description = description;
			shared.m_itemType = (ItemType)1;
			shared.m_food = (shared.m_foodStamina = (shared.m_foodEitr = 0f));
			shared.m_weight = weight;
			shared.m_maxStackSize = 50;
			shared.m_icons = (Sprite[])(object)new Sprite[1] { OriginalArt.Icon(icon) };
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			CapsuleCollider val3 = val.AddComponent<CapsuleCollider>();
			val3.radius = ((model == "SeedItem") ? 0.06f : 0.2f);
			val3.height = ((model == "SeedItem") ? 0.08f : 0.4f);
			val3.center = Vector3.up * (val3.height * 0.5f);
			if (!ItemManager.Instance.AddItem(new CustomItem(val, false)))
			{
				throw new Exception("Item registration " + name);
			}
			return val;
		}

		private GameObject CreateHarvest(string name, GameObject donor, GameObject output, string model, int amount)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00b7: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			GameObject val = Clone(name, donor);
			OriginalArt.HideDonor(val);
			OriginalArt.Add(val, model);
			Pickable component = val.GetComponent<Pickable>();
			component.m_itemPrefab = output;
			component.m_amount = amount;
			component.m_minAmountScaled = 1;
			component.m_dontScale = false;
			component.m_respawnTimeMinutes = 0f;
			component.m_hideWhenPicked = null;
			component.m_overrideName = output.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			component.m_spawnOffset = 0.35f;
			component.m_extraDrops = new DropTable();
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			CapsuleCollider obj = val.AddComponent<CapsuleCollider>();
			obj.radius = 0.24f;
			obj.height = 0.45f;
			obj.center = Vector3.up * 0.22f;
			PrefabManager.Instance.AddPrefab(new CustomPrefab(val, false));
			return val;
		}

		private GameObject CreatePlant(string name, GameObject donor, GameObject resource, GameObject mature, string label, string description, string early, string late, string icon)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			GameObject val = Clone(name, donor);
			OriginalArt.HideDonor(val);
			Plant component = val.GetComponent<Plant>();
			string[] array = new string[4] { "m_healthy", "m_unhealthy", "m_healthyGrown", "m_unhealthyGrown" };
			foreach (string text in array)
			{
				GameObject val2 = (GameObject)AccessTools.Field(typeof(Plant), text).GetValue(component);
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.SetActive(false);
				}
			}
			GameObject value = OriginalArt.Add(val, early + "_Healthy");
			GameObject val3 = OriginalArt.Add(val, early + "_Unhealthy");
			GameObject val4 = OriginalArt.Add(val, late + "_Healthy");
			GameObject val5 = OriginalArt.Add(val, late + "_Unhealthy");
			val3.SetActive(false);
			val4.SetActive(false);
			val5.SetActive(false);
			AccessTools.Field(typeof(Plant), "m_healthy").SetValue(component, value);
			AccessTools.Field(typeof(Plant), "m_unhealthy").SetValue(component, val3);
			AccessTools.Field(typeof(Plant), "m_healthyGrown").SetValue(component, val4);
			AccessTools.Field(typeof(Plant), "m_unhealthyGrown").SetValue(component, val5);
			component.m_name = label;
			component.m_grownPrefabs = (GameObject[])(object)new GameObject[1] { mature };
			component.m_minScale = (component.m_maxScale = 1f);
			component.m_needCultivatedGround = true;
			component.m_destroyIfCantGrow = false;
			component.m_growRadius = Radius.Value;
			component.m_growTime = GrowMin.Value;
			component.m_growTimeMax = Math.Max(GrowMin.Value, GrowMax.Value);
			Piece component2 = val.GetComponent<Piece>();
			component2.m_name = label;
			component2.m_description = description;
			component2.m_icon = OriginalArt.Icon(icon);
			component2.m_resources = (Requirement[])(object)new Requirement[1]
			{
				new Requirement
				{
					m_resItem = resource.GetComponent<ItemDrop>(),
					m_amount = 1,
					m_recover = false
				}
			};
			component2.m_cultivatedGroundOnly = true;
			component2.m_canBeRemoved = false;
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			CapsuleCollider obj = val.AddComponent<CapsuleCollider>();
			obj.radius = 0.16f;
			obj.height = 0.24f;
			obj.center = Vector3.up * 0.12f;
			PieceManager.Instance.AddPiece(new CustomPiece(val, "Cultivator", false));
			return val;
		}

		private void ApplyBalance()
		{
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			if (!Ready)
			{
				return;
			}
			ApplyKitchenBalance();
			fruitHarvest.GetComponent<Pickable>().m_amount = FruitYield.Value;
			seedHarvest.GetComponent<Pickable>().m_amount = SeedYield.Value;
			bool flag = Compatibility.PlantEverythingOverrides();
			GameObject[] array = (GameObject[])(object)new GameObject[2] { fruitPlant, seedPlant };
			foreach (GameObject val in array)
			{
				if (!flag)
				{
					Plant component = val.GetComponent<Plant>();
					component.m_growTime = GrowMin.Value;
					component.m_growTimeMax = Math.Max(GrowMin.Value, GrowMax.Value);
					component.m_growRadius = Radius.Value;
				}
			}
			Plant[] array2 = Object.FindObjectsByType<Plant>((FindObjectsSortMode)0);
			foreach (Plant val2 in array2)
			{
				if (CropPolicy.OwnPlant(Utils.GetPrefabName(((Component)val2).gameObject)) && !flag)
				{
					val2.m_growTime = GrowMin.Value;
					val2.m_growTimeMax = Math.Max(GrowMin.Value, GrowMax.Value);
					val2.m_growRadius = Radius.Value;
				}
			}
			Pickable[] array3 = Object.FindObjectsByType<Pickable>((FindObjectsSortMode)0);
			foreach (Pickable val3 in array3)
			{
				string prefabName = Utils.GetPrefabName(((Component)val3).gameObject);
				if (prefabName == "SmeagsPumpkin_FruitHarvest")
				{
					val3.m_amount = FruitYield.Value;
				}
				else if (prefabName == "SmeagsPumpkin_SeedHarvest")
				{
					val3.m_amount = SeedYield.Value;
				}
			}
			CharacterDrop component2 = Native("Greydwarf_Elite").GetComponent<CharacterDrop>();
			foreach (CharacterDrop item in (from d in Object.FindObjectsByType<CharacterDrop>((FindObjectsSortMode)0)
				where Utils.GetPrefabName(((Component)d).gameObject) == "Greydwarf_Elite"
				select d).Concat((IEnumerable<CharacterDrop>)(object)new CharacterDrop[1] { component2 }).Distinct())
			{
				item.m_drops.RemoveAll((Drop x) => (Object)(object)x.m_prefab == (Object)(object)seed);
				if (StarterDrops.Value && StarterChance.Value > 0f)
				{
					item.m_drops.Add(new Drop
					{
						m_prefab = seed,
						m_amountMin = 1,
						m_amountMax = 1,
						m_chance = StarterChance.Value,
						m_levelMultiplier = true,
						m_onePerPlayer = false
					});
				}
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private FoodBalance BindFood(string section, float health, float stamina, int[] costs, string[] ingredientLabels = null, float duration = 1200f, float regen = 2f)
		{
			return new FoodBalance
			{
				health = Entry(section, "Health", health, "Initial food health bonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)),
				stamina = Entry(section, "Stamina", stamina, "Initial food stamina bonus.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)),
				duration = Entry(section, "DurationSeconds", duration, "Food duration in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 3600f)),
				regen = Entry(section, "HealthRegen", regen, "Native food health regeneration.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f)),
				costs = costs.Select((int n, int i) => Entry(section, "Ingredient" + (i + 1) + "Amount", n, (ingredientLabels != null) ? ingredientLabels[i] : ((i == 0) ? "Pumpkins per serving." : ((section == "Honeyed Mash") ? "Honey per serving." : ((i == 1) ? "Raw deer meat per serving." : "Mushrooms per serving."))), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20))).ToArray()
			};
		}

		private void BindKitchen()
		{
			mash = BindFood("Honeyed Mash", 14f, 42f, new int[2] { 1, 2 });
			stew = BindFood("Venison Stew", 40f, 14f, new int[3] { 1, 1, 1 });
			roasted = BindFood("Roasted Seeds", 10f, 30f, new int[1] { 3 }, new string[1] { "Raw planting seeds per serving. Roasting consumes these seeds; the roasted food cannot be planted." }, 900f, 1f);
			carveCost = Entry("Lantern", "PumpkinsToCarve", 1, "Pumpkins consumed at a level-one workbench for one reusable carved pumpkin.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20));
			maxFuel = Entry("Lantern", "MaximumResin", 6, "Maximum resin capacity. Placement always starts empty; dismantling discards fuel.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20));
			fuelSeconds = Entry("Lantern", "SecondsPerResin", 20000f, "Native burn time per resin. No resin is returned on dismantling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 86400f));
		}

		private Recipe AddKitchenRecipe(GameObject item, string station, params string[] ingredients)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			Recipe val = ScriptableObject.CreateInstance<Recipe>();
			((Object)val).name = "Recipe_" + ((Object)item).name;
			val.m_item = item.GetComponent<ItemDrop>();
			val.m_amount = 1;
			val.m_enabled = true;
			val.m_minStationLevel = 1;
			val.m_craftingStation = Native(station).GetComponent<CraftingStation>();
			val.m_resources = ((IEnumerable<string>)ingredients).Select((Func<string, Requirement>)((string n) => new Requirement
			{
				m_resItem = Native(n).GetComponent<ItemDrop>(),
				m_amount = 1,
				m_recover = false
			})).ToArray();
			if (!ItemManager.Instance.AddRecipe(new CustomRecipe(val, false, false)))
			{
				throw new Exception("Recipe registration " + ((Object)val).name);
			}
			return val;
		}

		private void RegisterFood(FoodBalance b, string id, string label, string description, string model, params string[] ingredients)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			b.item = CreateItem(id, "CarrotSeeds", label, description, model, model + "Icon", 1f);
			SharedData shared = b.item.GetComponent<ItemDrop>().m_itemData.m_shared;
			shared.m_itemType = (ItemType)2;
			shared.m_maxStackSize = 10;
			shared.m_foodEatAnimTime = 1f;
			b.recipe = AddKitchenRecipe(b.item, "piece_cauldron", ingredients);
		}

		private void RegisterKitchen()
		{
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Expected O, but got Unknown
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			RegisterFood(mash, "SmeagsPumpkin_HoneyedMash", "Honeyed pumpkin mash", "Earthy pumpkin sweetened with honey. A warming meal for a long day.", "HoneyedMash", "SmeagsPumpkin_Pumpkin", "Honey");
			RegisterFood(stew, "SmeagsPumpkin_VenisonStew", "Pumpkin & venison stew", "Pumpkin, venison and mushrooms simmered into a hearty stew.", "VenisonStew", "SmeagsPumpkin_Pumpkin", "DeerMeat", "Mushroom");
			RegisterFood(roasted, "SmeagsPumpkin_RoastedSeeds", "Roasted pumpkin seeds", "A handful of toasted pumpkin seeds. A simple snack for the road; these seeds can no longer be planted.", "RoastedSeeds", "SmeagsPumpkin_Seeds");
			SharedData shared = roasted.item.GetComponent<ItemDrop>().m_itemData.m_shared;
			shared.m_maxStackSize = 20;
			shared.m_weight = 0.2f;
			carved = CreateItem("SmeagsPumpkin_CarvedPumpkin", "CarrotSeeds", "Carved pumpkin", "A hollow pumpkin with a candle. Place with a Hammer, then add resin. Dismantling returns this pumpkin, but discards fuel.", "CarvedLantern", "CarvedLanternIcon", 2f);
			carved.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize = 10;
			carvingRecipe = AddKitchenRecipe(carved, "piece_workbench", "SmeagsPumpkin_Pumpkin");
			lantern = Clone("SmeagsPumpkin_Lantern", Native("piece_jackoturnip"));
			OriginalArt.HideDonor(lantern);
			GameObject val = OriginalArt.Add(lantern, "CarvedLantern");
			Collider[] componentsInChildren = lantern.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren)
			{
				if (!val2.isTrigger)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			CapsuleCollider obj = lantern.AddComponent<CapsuleCollider>();
			obj.radius = 0.24f;
			obj.height = 0.38f;
			obj.center = Vector3.up * 0.19f;
			Piece component = lantern.GetComponent<Piece>();
			component.m_enabled = true;
			component.m_name = "Pumpkin lantern";
			component.m_description = "A carved pumpkin candle lantern. Add resin after placement; dismantling returns the carved pumpkin and discards fuel.";
			component.m_icon = OriginalArt.Icon("CarvedLanternIcon");
			component.m_resources = (Requirement[])(object)new Requirement[1]
			{
				new Requirement
				{
					m_resItem = carved.GetComponent<ItemDrop>(),
					m_amount = 1,
					m_recover = true
				}
			};
			WearNTear component2 = lantern.GetComponent<WearNTear>();
			component2.m_new = (component2.m_worn = (component2.m_broken = val));
			component2.m_wet = null;
			component2.m_fragmentRoots = (GameObject[])(object)new GameObject[1] { val };
			component2.m_burnable = false;
			Fireplace component3 = lantern.GetComponent<Fireplace>();
			component3.m_name = "Pumpkin lantern";
			component3.m_startFuel = 0f;
			component3.m_infiniteFuel = false;
			component3.m_igniteInterval = 0f;
			component3.m_firePrefab = null;
			component3.m_checkTerrainOffset = 0.16f;
			component3.m_coverCheckOffset = 0.18f;
			component3.m_enabledObject.transform.localPosition = Vector3.up * 0.13f;
			Transform[] componentsInChildren2 = component3.m_enabledObject.GetComponentsInChildren<Transform>(true);
			foreach (Transform val3 in componentsInChildren2)
			{
				if (!((Object)(object)val3 == (Object)(object)component3.m_enabledObject.transform))
				{
					if (((Object)val3).name == "Point light")
					{
						val3.localPosition = Vector3.zero;
					}
					else if (((Object)val3).name == "flames (1)")
					{
						val3.localPosition = Vector3.zero;
						val3.localScale = Vector3.one * 0.22f;
					}
					else if (((Object)val3).name == "flare")
					{
						val3.localPosition = Vector3.zero;
						val3.localScale = Vector3.one * 0.35f;
					}
				}
			}
			Renderer[] componentsInChildren3 = component3.m_enabledObject.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				componentsInChildren3[i].enabled = true;
			}
			if (!PieceManager.Instance.AddPiece(new CustomPiece(lantern, "Hammer", false)))
			{
				throw new Exception("Lantern registration");
			}
		}

		private void ApplyKitchenBalance()
		{
			FoodBalance[] array = new FoodBalance[3] { mash, stew, roasted };
			foreach (FoodBalance foodBalance in array)
			{
				SharedData shared = foodBalance.item.GetComponent<ItemDrop>().m_itemData.m_shared;
				shared.m_food = foodBalance.health.Value;
				shared.m_foodStamina = foodBalance.stamina.Value;
				shared.m_foodBurnTime = foodBalance.duration.Value;
				shared.m_foodRegen = foodBalance.regen.Value;
				for (int j = 0; j < foodBalance.costs.Length; j++)
				{
					foodBalance.recipe.m_resources[j].m_amount = foodBalance.costs[j].Value;
				}
			}
			carvingRecipe.m_resources[0].m_amount = carveCost.Value;
			foreach (Fireplace item in (from f in Object.FindObjectsByType<Fireplace>((FindObjectsSortMode)0)
				where Utils.GetPrefabName(((Component)f).gameObject) == "SmeagsPumpkin_Lantern"
				select f).Concat((IEnumerable<Fireplace>)(object)new Fireplace[1] { lantern.GetComponent<Fireplace>() }))
			{
				item.m_maxFuel = maxFuel.Value;
				item.m_secPerFuel = fuelSeconds.Value;
			}
		}
	}
	internal static class OriginalArt
	{
		private sealed class Part
		{
			internal Mesh mesh;

			internal Material material;
		}

		internal static Material NativeMaterial;

		private static readonly Dictionary<string, Part[]> models = new Dictionary<string, Part[]>();

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

		private static readonly Dictionary<string, Material> materials = new Dictionary<string, Material>();

		private static Stream Resource(string n)
		{
			return Assembly.GetExecutingAssembly().GetManifestResourceStream("SmeagsPumpkin.Art." + n) ?? throw new InvalidDataException("Missing original art " + n);
		}

		private static Texture2D Texture(string name)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (textures.TryGetValue(name, out var value))
			{
				return value;
			}
			using Stream stream = Resource(name);
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			value = new Texture2D(2, 2, (TextureFormat)4, true);
			MethodInfo method = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true).GetMethod("LoadImage", new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			});
			if (method == null || !(bool)method.Invoke(null, new object[3] { value, array, false }))
			{
				throw new InvalidDataException(name);
			}
			((Object)value).name = name;
			((Texture)value).filterMode = (FilterMode)0;
			((Texture)value).wrapMode = (TextureWrapMode)0;
			textures.Add(name, value);
			return value;
		}

		internal static Sprite Icon(string name)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = Texture(name + ".png");
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		private static Part[] Read(string name)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			if (models.TryGetValue(name, out var value))
			{
				return value;
			}
			using (BinaryReader binaryReader = new BinaryReader(Resource(name + ".spmesh")))
			{
				if (new string(binaryReader.ReadChars(4)) != "SPM1")
				{
					throw new InvalidDataException("Mesh header");
				}
				int num = binaryReader.ReadInt32();
				if (num < 1 || num > 8)
				{
					throw new InvalidDataException("Mesh groups");
				}
				value = new Part[num];
				for (int i = 0; i < num; i++)
				{
					int num2 = binaryReader.ReadInt32();
					if (num2 < 1 || num2 > 256)
					{
						throw new InvalidDataException("Texture name");
					}
					string text = Encoding.UTF8.GetString(binaryReader.ReadBytes(num2));
					int num3 = binaryReader.ReadInt32();
					int num4 = binaryReader.ReadInt32();
					if (num3 < 3 || num3 > 65000 || num4 < 3 || num4 > 100000 || num4 % 3 != 0)
					{
						throw new InvalidDataException("Mesh budget");
					}
					Vector3[] array = (Vector3[])(object)new Vector3[num3];
					Vector3[] array2 = (Vector3[])(object)new Vector3[num3];
					Vector2[] array3 = (Vector2[])(object)new Vector2[num3];
					for (int j = 0; j < num3; j++)
					{
						array[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
						array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
						array3[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					}
					int[] array4 = new int[num4];
					for (int k = 0; k < num4; k++)
					{
						array4[k] = binaryReader.ReadInt32();
						if (array4[k] < 0 || array4[k] >= num3)
						{
							throw new InvalidDataException("Mesh index");
						}
					}
					Mesh val = new Mesh
					{
						name = "SmeagsPumpkin_" + name + "_" + i,
						vertices = array,
						normals = array2,
						uv = array3,
						triangles = array4
					};
					val.RecalculateBounds();
					if (!materials.TryGetValue(text, out var value2))
					{
						if (!Object.op_Implicit((Object)(object)NativeMaterial))
						{
							throw new InvalidOperationException("Native donor material unavailable");
						}
						value2 = new Material(NativeMaterial)
						{
							name = "SmeagsPumpkin_" + text,
							mainTexture = (Texture)(object)Texture(text),
							color = Color.white
						};
						value2.mainTextureOffset = Vector2.zero;
						value2.mainTextureScale = Vector2.one;
						if (value2.HasProperty("_EmissionColor"))
						{
							value2.SetColor("_EmissionColor", Color.black);
						}
						if (value2.HasProperty("_Glossiness"))
						{
							value2.SetFloat("_Glossiness", 0.12f);
						}
						if (value2.HasProperty("_Metallic"))
						{
							value2.SetFloat("_Metallic", 0f);
						}
						materials.Add(text, value2);
					}
					value[i] = new Part
					{
						mesh = val,
						material = value2
					};
				}
			}
			models[name] = value;
			return value;
		}

		internal static GameObject Add(GameObject parent, string model)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(model);
			val.transform.SetParent(parent.transform, false);
			Part[] array = Read(model);
			foreach (Part part in array)
			{
				GameObject val2 = new GameObject(((Object)part.mesh).name)
				{
					layer = parent.layer
				};
				val2.transform.SetParent(val.transform, false);
				val2.AddComponent<MeshFilter>().sharedMesh = part.mesh;
				((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = part.material;
			}
			return val;
		}

		internal static void HideDonor(GameObject root)
		{
			LODGroup[] componentsInChildren = root.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
		}
	}
	internal static class Compatibility
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		internal static class ReplantAliases
		{
			[HarmonyPostfix]
			[HarmonyPriority(-100)]
			[HarmonyAfter(new string[] { "advize.PlantEasily" })]
			private static void Postfix()
			{
				if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !Plugin.Instance.Ready || !Chainloader.PluginInfos.TryGetValue("advize.PlantEasily", out var value))
				{
					return;
				}
				if (value.Metadata.Version.ToString() != "2.3.1")
				{
					Plugin.Instance.Note("Plant Easily " + value.Metadata.Version?.ToString() + ": replant alias bridge not validated for this version; skipped.");
					return;
				}
				try
				{
					Assembly assembly = ((object)value.Instance).GetType().Assembly;
					Type? type = assembly.GetType("Advize_PlantEasily.ReplantDB");
					Type type2 = assembly.GetType("Advize_PlantEasily.ModContext") ?? assembly.GetType("ModContext");
					IDictionary dictionary = AccessTools.Field(type, "Registry")?.GetValue(null) as IDictionary;
					IDictionary dictionary2 = AccessTools.Field(type2, "PrefabRefs")?.GetValue(null) as IDictionary;
					if (dictionary == null || dictionary2 == null)
					{
						throw new Exception("Expected 2.3.1 registry unavailable");
					}
					string[] array = new string[2] { "SmeagsPumpkin_FruitHarvest", "SmeagsPumpkin_SeedHarvest" };
					foreach (string text in array)
					{
						string text2 = CropPolicy.PlantForHarvest(text);
						if (!dictionary.Contains(text2))
						{
							throw new Exception("Plant Easily did not detect " + text2);
						}
						if (dictionary.Contains(text))
						{
							Plugin.Instance.Note("Plant Easily mature mapping already present: " + text);
							continue;
						}
						dictionary[text] = dictionary[text2];
						dictionary2[text] = ZNetScene.instance.GetPrefab(text);
						Plugin.Instance.Note("Plant Easily 2.3.1 scoped mature alias added: " + text + " -> " + text2);
					}
				}
				catch (Exception ex)
				{
					Plugin.Instance.Note("Plant Easily replant bridge failed; normal planting remains native: " + ex.Message);
				}
			}
		}

		internal static bool PlantEverythingOverrides()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.TryGetValue("advize.PlantEverything", out var value))
			{
				return false;
			}
			ConfigFile config = value.Instance.Config;
			ConfigEntry<bool> val = default(ConfigEntry<bool>);
			ConfigEntry<bool> val2 = default(ConfigEntry<bool>);
			if (config.TryGetEntry<bool>(new ConfigDefinition("Crops", "EnableCropOverrides"), ref val) && val.Value && config.TryGetEntry<bool>(new ConfigDefinition("Crops", "OverrideModdedCrops"), ref val2))
			{
				return val2.Value;
			}
			return false;
		}
	}
	public static class CropPolicy
	{
		public const string Seed = "SmeagsPumpkin_Seeds";

		public const string Fruit = "SmeagsPumpkin_Pumpkin";

		public const string FruitPlant = "SmeagsPumpkin_FruitPlant";

		public const string SeedPlant = "SmeagsPumpkin_SeedPlant";

		public const string FruitPickable = "SmeagsPumpkin_FruitHarvest";

		public const string SeedPickable = "SmeagsPumpkin_SeedHarvest";

		public static bool OwnPlant(string n)
		{
			if (!(n == "SmeagsPumpkin_FruitPlant"))
			{
				return n == "SmeagsPumpkin_SeedPlant";
			}
			return true;
		}

		public static string PlantForHarvest(string n)
		{
			if (!(n == "SmeagsPumpkin_FruitHarvest"))
			{
				if (!(n == "SmeagsPumpkin_SeedHarvest"))
				{
					return null;
				}
				return "SmeagsPumpkin_SeedPlant";
			}
			return "SmeagsPumpkin_FruitPlant";
		}
	}
}