Decompiled source of CorewoodAdditions v1.0.2

plugins/CorewoodAdditions.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using CorewoodAdditions.Producers;
using CorewoodAdditions.Updates;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CorewoodAdditions")]
[assembly: AssemblyDescription("https://www.nexusmods.com/profile/MagicMikeMods/mods")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MagicMike")]
[assembly: AssemblyProduct("CorewoodAdditions")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6b1f0c52-3d8e-4a47-9a21-5c7e2f90d4b3")]
[assembly: AssemblyFileVersion("1.0.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.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 CorewoodAdditions
{
	internal class AddPrefabs
	{
		private const string SmelterPrefabName = "mm_corewood_smelter";

		public static void LoadPieces()
		{
			PieceAssets.Init();
			CorewoodAdditionsMod.TryAddPiece(AddSerpentBait);
			CorewoodAdditionsMod.TryAddPiece(AddCompostBin);
			CorewoodAdditionsMod.TryAddPiece(AddBeeHive);
			CorewoodAdditionsMod.TryAddPiece(AddFishTrap);
			CorewoodAdditionsMod.TryAddPiece(AddFishTrapLarge);
			CorewoodAdditionsMod.TryAddPiece(AddFishTrapOcean);
			CorewoodAdditionsMod.TryAddPiece(AddBirdHouse);
		}

		public static void AddSerpentBait()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("SerpentBait");
			ItemManager.Instance.AddItem(new CustomItem(val, true));
		}

		public static void AddCompostBin()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_compost_bin");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "RoundLog",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 1,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			val.GetComponent<Piece>().m_placeEffect = PieceAssets.buildWood;
			WearNTear component = val.GetComponent<WearNTear>();
			component.m_destroyedEffect = PieceAssets.breakWood;
			component.m_hitEffect = PieceAssets.hitWood;
			if ((Object)(object)val.GetComponentInChildren<Container>(true) == (Object)null)
			{
				Container obj = val.AddComponent<Container>();
				obj.m_name = "$piece_mm_corewood_compost_bin";
				obj.m_width = 5;
				obj.m_height = 2;
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<CompostBin>()))
			{
				val.AddComponent<CompostBin>();
			}
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddBeeHive()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_beehive");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "RoundLog",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 4,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			val.GetComponent<Piece>().m_placeEffect = PieceAssets.buildWood;
			WearNTear component = val.GetComponent<WearNTear>();
			component.m_destroyedEffect = PieceAssets.breakWood;
			component.m_hitEffect = PieceAssets.hitWood;
			if ((Object)(object)val.GetComponentInChildren<Container>(true) == (Object)null)
			{
				Container obj = val.AddComponent<Container>();
				obj.m_name = "$piece_mm_corewood_beehive";
				obj.m_width = 5;
				obj.m_height = 2;
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<BeeHive>()))
			{
				val.AddComponent<BeeHive>();
			}
			ProducerVisuals.AssignSfxHash(val, "mm_corewood_beehive_sfx");
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddFishTrap()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_fishtrap");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "RoundLog",
					Amount = 2,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 2,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			Piece component = val.GetComponent<Piece>();
			component.m_placeEffect = PieceAssets.buildWood;
			component.m_waterPiece = false;
			component.m_noInWater = false;
			component.m_groundPiece = true;
			WearNTear component2 = val.GetComponent<WearNTear>();
			component2.m_destroyedEffect = PieceAssets.breakWood;
			component2.m_hitEffect = PieceAssets.hitWood;
			if ((Object)(object)val.GetComponentInChildren<Container>(true) == (Object)null)
			{
				Container obj = val.AddComponent<Container>();
				obj.m_name = "$piece_mm_corewood_fishtrap";
				obj.m_width = 5;
				obj.m_height = 4;
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<FishTrap>()))
			{
				val.AddComponent<FishTrap>();
			}
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddFishTrapLarge()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_fishtrap_large");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "RoundLog",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "LinenThread",
					Amount = 2,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			Piece component = val.GetComponent<Piece>();
			component.m_name = "$piece_mm_corewood_fishtrap_large";
			component.m_description = "$piece_mm_corewood_fishtrap_large_desc";
			component.m_placeEffect = PieceAssets.buildWood;
			component.m_waterPiece = false;
			component.m_noInWater = false;
			component.m_groundPiece = true;
			WearNTear component2 = val.GetComponent<WearNTear>();
			component2.m_destroyedEffect = PieceAssets.breakWood;
			component2.m_hitEffect = PieceAssets.hitWood;
			if ((Object)(object)val.GetComponentInChildren<Container>(true) == (Object)null)
			{
				Container obj = val.AddComponent<Container>();
				obj.m_name = "$piece_mm_corewood_fishtrap_large";
				obj.m_width = 5;
				obj.m_height = 4;
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<FishTrap>()))
			{
				val.AddComponent<FishTrap>();
			}
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddFishTrapOcean()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_fishtrap_ocean");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "AskBladder",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "LinenThread",
					Amount = 4,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			Piece component = val.GetComponent<Piece>();
			component.m_placeEffect = PieceAssets.buildWood;
			component.m_waterPiece = true;
			component.m_noInWater = false;
			component.m_groundPiece = false;
			component.m_groundOnly = false;
			WearNTear component2 = val.GetComponent<WearNTear>();
			component2.m_destroyedEffect = PieceAssets.breakWood;
			component2.m_hitEffect = PieceAssets.hitWood;
			component2.m_noSupportWear = false;
			Floating component3 = val.GetComponent<Floating>();
			if ((Object)(object)component3 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component3, true);
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<WaveBobber>()))
			{
				val.AddComponent<WaveBobber>();
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<FishTrap>()))
			{
				val.AddComponent<FishTrap>();
			}
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddBirdHouse()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_birdhouse");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[3]
			{
				PieceUsages.Building,
				PieceUsages.Crafting,
				PieceUsages.Storage
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "RoundLog",
					Amount = 2,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Wood",
					Amount = 4,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			val.GetComponent<Piece>().m_placeEffect = PieceAssets.buildWood;
			WearNTear component = val.GetComponent<WearNTear>();
			component.m_destroyedEffect = PieceAssets.breakWood;
			component.m_hitEffect = PieceAssets.hitWood;
			if ((Object)(object)val.GetComponentInChildren<Container>(true) == (Object)null)
			{
				Container obj = val.AddComponent<Container>();
				obj.m_name = "$piece_mm_corewood_birdhouse";
				obj.m_width = 5;
				obj.m_height = 4;
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<BirdHouse>()))
			{
				val.AddComponent<BirdHouse>();
			}
			ProducerVisuals.AssignSfxHash(val, "mm_corewood_birdhouse_sfx");
			PieceManager.Instance.AddPiece(val3);
		}

		public static void AddSmelter()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			GameObject val = CorewoodAdditionsMod.cwadditions.LoadAsset<GameObject>("mm_corewood_smelter");
			PieceConfig val2 = new PieceConfig();
			val2.CraftingStation = "piece_workbench";
			val2.PieceTable = "_HammerPieceTable";
			val2.Category = "CoreWood-Building";
			val2.Usage = new string[2]
			{
				PieceUsages.Building,
				PieceUsages.Crafting
			};
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "Stone",
					Amount = 20,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "SurtlingCore",
					Amount = 1,
					Recover = true
				}
			};
			CustomPiece val3 = new CustomPiece(val, true, val2);
			val.GetComponent<Piece>().m_placeEffect = PieceAssets.buildStone;
			WearNTear component = val.GetComponent<WearNTear>();
			component.m_destroyedEffect = PieceAssets.breakStone;
			component.m_hitEffect = PieceAssets.hitStone;
			Smelter component2 = val.GetComponent<Smelter>();
			component2.m_fuelItem = PieceAssets.fuelCoal;
			component2.m_oreAddedEffects = PieceAssets.addOreEffects;
			component2.m_fuelAddedEffects = PieceAssets.addFuelEffects;
			component2.m_produceEffects = PieceAssets.produceEffects;
			FixGuidePoints(val, Smelters.Smelter);
			PieceManager.Instance.AddPiece(val3);
			AddVanillaSmelterConversions();
		}

		private static void FixGuidePoints(GameObject prefab, string vanillaPrefabName)
		{
			GameObject prefab2 = PrefabManager.Instance.GetPrefab(vanillaPrefabName);
			GuidePoint val = ((prefab2 != null) ? prefab2.GetComponentInChildren<GuidePoint>(true) : null);
			GuidePoint[] componentsInChildren = prefab.GetComponentsInChildren<GuidePoint>(true);
			foreach (GuidePoint val2 in componentsInChildren)
			{
				if ((Object)(object)val2.m_ravenPrefab == (Object)null && (Object)(object)val != (Object)null)
				{
					val2.m_ravenPrefab = val.m_ravenPrefab;
				}
				if ((Object)(object)val2.m_ravenPrefab == (Object)null)
				{
					((Behaviour)val2).enabled = false;
				}
			}
		}

		private static void AddVanillaSmelterConversions()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00a4: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			GameObject prefab = PrefabManager.Instance.GetPrefab(Smelters.Smelter);
			Smelter val = ((prefab != null) ? prefab.GetComponent<Smelter>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"[CoreWoodAdditions] Could not find the vanilla smelter; mm_corewood_smelter has no conversions.");
				return;
			}
			foreach (ItemConversion item in val.m_conversion)
			{
				if (!((Object)(object)item?.m_from == (Object)null) && !((Object)(object)item.m_to == (Object)null))
				{
					ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new SmelterConversionConfig
					{
						Station = "mm_corewood_smelter",
						FromItem = ((Object)item.m_from).name,
						ToItem = ((Object)item.m_to).name
					}));
				}
			}
		}
	}
	internal class MainConfig
	{
		public static ConfigEntry<bool> modEnabled;

		public static ConfigEntry<bool> fishtrapShowPins;

		public static ConfigEntry<bool> serpentBaitEnabled;

		public static ConfigEntry<float> compostSecPerCycle;

		public static ConfigEntry<int> compostConsumablePerCycle;

		public static ConfigEntry<int> compostMaxBait;

		public static ConfigEntry<string>[] compostConsumables = new ConfigEntry<string>[0];

		public static ConfigEntry<bool> compostShowIcon;

		public static ConfigEntry<float> beehiveSecPerBatch;

		public static ConfigEntry<int> beehiveHoneyPerBatch;

		public static ConfigEntry<int> beehiveConsumablePerBatch;

		public static ConfigEntry<int> beehiveMaxHoney;

		public static ConfigEntry<string> beehiveConsumables;

		public static ConfigEntry<bool> beehiveSoundEnabled;

		public static ConfigEntry<bool> beehiveShowIcon;

		public static ConfigEntry<float> birdhouseSecPerBatch;

		public static ConfigEntry<int> birdhouseFeathersPerBatch;

		public static ConfigEntry<int> birdhouseConsumablePerBatch;

		public static ConfigEntry<int> birdhouseMaxFeathers;

		public static ConfigEntry<string> birdhouseConsumables;

		public static ConfigEntry<bool> birdhouseSoundEnabled;

		public static ConfigEntry<bool> birdhouseShowIcon;

		public static ConfigEntry<float> fishtrapSecPerFish;

		public static ConfigEntry<int> fishtrapMaxFish;

		public static ConfigEntry<float> fishtrapQualityChance;

		public static ConfigEntry<bool> fishtrapShowIcon;

		public static ConfigEntry<float> fishtrapLargeSecPerFish;

		public static ConfigEntry<int> fishtrapLargeMaxFish;

		public static ConfigEntry<float> fishtrapLargeQualityChance;

		public static ConfigEntry<bool> fishtrapLargeShowIcon;

		public static ConfigEntry<float> fishtrapOceanSecPerFish;

		public static ConfigEntry<int> fishtrapOceanMaxFish;

		public static ConfigEntry<float> fishtrapOceanQualityChance;

		public static ConfigEntry<bool> fishtrapOceanShowIcon;

		public static void InitConfigs(ConfigFile config)
		{
			modEnabled = ConfigFileExtensions.BindConfigInOrder<bool>(config, "General Settings", "Enable Plugin", true, "Enable the CoreWoodExtras plugin.\n(Restart required. It is read before connecting to a server, so it is a local setting).\n", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapShowPins = ConfigFileExtensions.BindConfigInOrder<bool>(config, "General Settings", "Show Fish Trap Map Pins", true, "Show a map pin for every fish trap you know about. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			serpentBaitEnabled = ConfigFileExtensions.BindConfigInOrder<bool>(config, "General Settings", "Enable Serpent Bait", true, "Allow the Compost Bin to make Serpent Bait from Bjorn meat, and the Ocean Fish Trap to catch Serpent Meat with it.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			compostSecPerCycle = ConfigFileExtensions.BindConfigInOrder<float>(config, "Compost Bin", "Seconds Per Cycle", 300f, "Seconds required to complete one production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			compostConsumablePerCycle = ConfigFileExtensions.BindConfigInOrder<int>(config, "Compost Bin", "Consumable Per Cycle", 1, "Amount of the consumable item consumed per production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			compostMaxBait = ConfigFileExtensions.BindConfigInOrder<int>(config, "Compost Bin", "Max Bait", 250, "Maximum bait (all types combined) stored inside the compost bin container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			compostConsumables = new ConfigEntry<string>[CompostBin.Baits.Length];
			for (int i = 0; i < CompostBin.Baits.Length; i++)
			{
				CompostBin.BaitDefinition baitDefinition = CompostBin.Baits[i];
				compostConsumables[i] = ConfigFileExtensions.BindConfigInOrder<string>(config, "Compost Bin", baitDefinition.ConfigLabel + " Consumable", baitDefinition.DefaultConsumable, "Prefab name of the consumable item that produces " + baitDefinition.ConfigLabel + ". Accepts 1 item.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			}
			compostShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Compost Bin", "Show Output Icon", true, "Show the rotating icon above the compost bin while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			compostShowIcon.SettingChanged += delegate
			{
				CompostBin.RefreshAllItemCrafted();
			};
			beehiveSecPerBatch = ConfigFileExtensions.BindConfigInOrder<float>(config, "Beehive", "Seconds Per Cycle", 600f, "Seconds required to complete one production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveHoneyPerBatch = ConfigFileExtensions.BindConfigInOrder<int>(config, "Beehive", "Honey Per Cycle", 1, "Honey produced per production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveConsumablePerBatch = ConfigFileExtensions.BindConfigInOrder<int>(config, "Beehive", "Consumable Per Cycle", 1, "Amount of valid consumable items consumed per production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveMaxHoney = ConfigFileExtensions.BindConfigInOrder<int>(config, "Beehive", "Max Honey", 250, "Maximum honey stored inside the beehive container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveConsumables = ConfigFileExtensions.BindConfigInOrder<string>(config, "Beehive", "Consumable Prefabs", "Dandelion", "Prefab names of valid consumable items for the beehive, separated by commas. Supports up to 10 items.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveSoundEnabled = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Beehive", "Enable Sound", true, "Play the buzzing sound while the beehive is working. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveSoundEnabled.SettingChanged += delegate
			{
				BeeHive.RefreshAllSfx();
			};
			beehiveShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Beehive", "Show Output Icon", true, "Show the rotating icon above the beehive while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			beehiveShowIcon.SettingChanged += delegate
			{
				BeeHive.RefreshAllItemCrafted();
			};
			birdhouseSecPerBatch = ConfigFileExtensions.BindConfigInOrder<float>(config, "Birdhouse", "Seconds Per Cycle", 300f, "Seconds required to complete one production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseFeathersPerBatch = ConfigFileExtensions.BindConfigInOrder<int>(config, "Birdhouse", "Feathers Per Cycle", 5, "Feathers produced per production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseConsumablePerBatch = ConfigFileExtensions.BindConfigInOrder<int>(config, "Birdhouse", "Consumable Per Cycle", 1, "Amount of valid consumable items consumed per production cycle.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseMaxFeathers = ConfigFileExtensions.BindConfigInOrder<int>(config, "Birdhouse", "Max Feathers", 250, "Maximum feathers stored inside the birdhouse container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseConsumables = ConfigFileExtensions.BindConfigInOrder<string>(config, "Birdhouse", "Consumable Prefabs", "TurnipSeeds,CarrotSeeds,OnionSeeds", "Prefab names of valid consumable items for the birdhouse, separated by commas. Supports up to 10 items.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseSoundEnabled = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Birdhouse", "Enable Sound", true, "Play the bird sound while the birdhouse is working. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseSoundEnabled.SettingChanged += delegate
			{
				BirdHouse.RefreshAllSfx();
			};
			birdhouseShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Birdhouse", "Show Output Icon", true, "Show the rotating icon above the birdhouse while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			birdhouseShowIcon.SettingChanged += delegate
			{
				BirdHouse.RefreshAllItemCrafted();
			};
			fishtrapSecPerFish = ConfigFileExtensions.BindConfigInOrder<float>(config, "Fish Trap", "Seconds Per Fish", 600f, "Seconds required to catch one fish.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapMaxFish = ConfigFileExtensions.BindConfigInOrder<int>(config, "Fish Trap", "Max Fish", 100, "Maximum fish stored inside the trap container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapQualityChance = ConfigFileExtensions.BindConfigInOrder<float>(config, "Fish Trap", "Chance To Increase Quality", 0.2f, "Chance to increase fish quality by one step per roll. Range: 0.0 to 1.0.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Fish Trap", "Show Output Icon", true, "Show the rotating icon above the fish trap while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapShowIcon.SettingChanged += delegate
			{
				FishTrap.RefreshAllItemCrafted();
			};
			fishtrapLargeSecPerFish = ConfigFileExtensions.BindConfigInOrder<float>(config, "Large Fish Trap", "Seconds Per Fish", 600f, "Seconds required to catch one fish.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapLargeMaxFish = ConfigFileExtensions.BindConfigInOrder<int>(config, "Large Fish Trap", "Max Fish", 150, "Maximum fish stored inside the trap container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapLargeQualityChance = ConfigFileExtensions.BindConfigInOrder<float>(config, "Large Fish Trap", "Chance To Increase Quality", 0.2f, "Chance to increase fish quality by one step per roll. Range: 0.0 to 1.0.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapLargeShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Large Fish Trap", "Show Output Icon", true, "Show the rotating icon above the large fish trap while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapLargeShowIcon.SettingChanged += delegate
			{
				FishTrap.RefreshAllItemCrafted();
			};
			fishtrapOceanSecPerFish = ConfigFileExtensions.BindConfigInOrder<float>(config, "Ocean Fish Trap", "Seconds Per Fish", 600f, "Seconds required to catch one fish.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapOceanMaxFish = ConfigFileExtensions.BindConfigInOrder<int>(config, "Ocean Fish Trap", "Max Fish", 200, "Maximum fish stored inside the trap container.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapOceanQualityChance = ConfigFileExtensions.BindConfigInOrder<float>(config, "Ocean Fish Trap", "Chance To Increase Quality", 0.2f, "Chance to increase fish quality by one step per roll. Range: 0.0 to 1.0.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapOceanShowIcon = ConfigFileExtensions.BindConfigInOrder<bool>(config, "Ocean Fish Trap", "Show Output Icon", true, "Show the rotating icon above the ocean fish trap while it holds output. Local setting.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			fishtrapOceanShowIcon.SettingChanged += delegate
			{
				FishTrap.RefreshAllItemCrafted();
			};
		}
	}
	internal static class PieceAssets
	{
		public static EffectList buildWood;

		public static EffectList breakWood;

		public static EffectList hitWood;

		public static EffectList buildStone;

		public static EffectList breakStone;

		public static EffectList hitStone;

		public static EffectList buildMetal;

		public static EffectList breakMetal;

		public static EffectList hitMetal;

		public static EffectList breakGlass;

		public static EffectList doorOpen;

		public static EffectList doorClose;

		public static EffectList gateOpen;

		public static EffectList gateClose;

		public static EffectList chestOpen;

		public static EffectList chestClose;

		public static EffectList bridgeOC;

		public static EffectList towerOC;

		public static EffectList elevator;

		public static EffectList elevatorLong;

		public static EffectList m_activateSFX;

		public static EffectList m_deactivateSFX;

		public static EffectList placeWorkbench;

		public static EffectList addEffects;

		public static EffectList harvestEffects;

		public static EffectList spawnEffects;

		public static EffectList addFuelEffects;

		public static EffectList addOreEffects;

		public static EffectList produceEffects;

		public static ItemDrop fuelCoal;

		public static ItemDrop fuelResin;

		private static bool s_built;

		public static void Init()
		{
			if (!s_built)
			{
				buildWood = Effects("sfx_build_hammer_wood");
				breakWood = Effects("sfx_wood_break");
				hitWood = Effects("sfx_wood_hit");
				buildStone = Effects("sfx_build_hammer_stone");
				breakStone = Effects("sfx_rock_destroyed");
				hitStone = Effects("sfx_rock_hit");
				buildMetal = Effects("sfx_build_hammer_metal");
				breakMetal = Effects("sfx_metal_blocked");
				hitMetal = Effects("sfx_metal_blocked");
				breakGlass = Effects("sfx_break_glass_mm");
				doorOpen = Effects("sfx_door_open");
				doorClose = Effects("sfx_door_close");
				gateOpen = Effects("sfx_open_gate_mm");
				gateClose = Effects("sfx_close_gate_mm");
				chestOpen = Effects("sfx_chest_open");
				chestClose = Effects("sfx_chest_close");
				bridgeOC = Effects("sfx_open_bridge_mm");
				towerOC = Effects("sfx_tower_bridge_mm");
				elevator = Effects("sfx_elevator_mm");
				elevatorLong = Effects("sfx_elevator_long_mm");
				m_activateSFX = Effects("fx_guardstone_activate");
				m_deactivateSFX = Effects("fx_guardstone_deactivate");
				placeWorkbench = Effects("vfx_Place_workbench");
				addEffects = Effects("vfx_fermenter_add");
				harvestEffects = Effects("sfx_pickable_pick");
				spawnEffects = Effects("vfx_lootspawn", "sfx_lootspawn");
				addFuelEffects = Effects("vfx_walltorch_addFuel", "sfx_FireAddFuel");
				addOreEffects = Effects("vfx_smelter_addore", "sfx_smelter_add");
				produceEffects = Effects("vfx_smelter_produce", "sfx_smelter_produce");
				fuelCoal = Cache.GetPrefab<GameObject>("Coal").GetComponent<ItemDrop>();
				fuelResin = Cache.GetPrefab<GameObject>("Resin").GetComponent<ItemDrop>();
				s_built = true;
			}
		}

		public static EffectList Effects(params string[] prefabNames)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_002d: 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_003a: Expected O, but got Unknown
			EffectData[] array = (EffectData[])(object)new EffectData[prefabNames.Length];
			for (int i = 0; i < prefabNames.Length; i++)
			{
				array[i] = new EffectData
				{
					m_prefab = Cache.GetPrefab<GameObject>(prefabNames[i])
				};
			}
			return new EffectList
			{
				m_effectPrefabs = array
			};
		}
	}
	internal class LocalisedText
	{
		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		public static void AddLocalisations()
		{
			CustomLocalization localization = Localization;
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "piece_mm_corewood_compost_bin", "Compost Bin" },
				{ "piece_mm_corewood_compost_bin_desc", "Turns food into fishing bait over time. The bait type depends on the item supplied." },
				{ "text_compostbin_working", "Producing bait" },
				{ "text_compostbin_no_consumable", "No consumable item" },
				{ "text_compostbin_full", "Inventory full" },
				{ "piece_mm_corewood_beehive", "Beehive" },
				{ "piece_mm_corewood_beehive_desc", "Produces honey over time when supplied with the configured item." },
				{ "text_beehive_working", "Producing honey" },
				{ "text_beehive_no_consumable", "No consumable item" },
				{ "text_beehive_full", "Inventory full" },
				{ "piece_mm_corewood_fishtrap", "Fish Trap" },
				{ "piece_mm_corewood_fishtrap_desc", "Catches fish over time when placed in shallow water (0.5 m to 1.5 m deep) and supplied with bait." },
				{ "piece_mm_corewood_fishtrap_large", "Large Fish Trap" },
				{ "piece_mm_corewood_fishtrap_large_desc", "A bigger fish trap that catches fish over time when placed in shallow water (0.5 m to 1.5 m deep) and supplied with bait." },
				{ "piece_mm_corewood_fishtrap_ocean", "Ocean Fish Trap" },
				{ "piece_mm_corewood_fishtrap_ocean_desc", "Floats on the sea and catches fish over time when supplied with bait. Build it from a boat on deep water in the Ocean biome." },
				{ "text_fishtrap_invalid_water", "Must be placed in shallow water." },
				{ "text_fishtrap_invalid_ocean", "Must be placed on deep water in the Ocean." },
				{ "text_fishtrap_working", "Fishing" },
				{ "text_fishtrap_wrong_biome", "No fish compatible with this biome" },
				{ "text_fishtrap_no_bait", "No valid bait found" },
				{ "text_fishtrap_full", "Inventory full" },
				{ "item_serpentbait", "Serpent Bait" },
				{ "item_serpentbait_desc", "Bait for catching sea serpents. Use it in an Ocean Fish Trap to catch Serpent Meat." },
				{ "piece_mm_corewood_birdhouse", "Birdhouse" },
				{ "piece_mm_corewood_birdhouse_desc", "Produces feathers over time when supplied with the configured items." },
				{ "text_birdhouse_working", "Producing feathers" },
				{ "text_birdhouse_no_consumable", "No consumable item" },
				{ "text_birdhouse_full", "Inventory full" }
			});
		}
	}
	internal class FileWatcher
	{
		private static readonly List<FileSystemWatcher> Watchers = new List<FileSystemWatcher>();

		public static void WatchFileChanges(string path, Action onChanged, bool includeSubdirectories = false)
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
			string directoryName = Path.GetDirectoryName(path);
			string fileName = Path.GetFileName(path);
			fileSystemWatcher.Path = directoryName;
			fileSystemWatcher.Filter = fileName;
			fileSystemWatcher.IncludeSubdirectories = includeSubdirectories;
			fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
			fileSystemWatcher.Changed += delegate
			{
				RaiseChanged(onChanged);
			};
			fileSystemWatcher.Deleted += delegate
			{
				RaiseChanged(onChanged);
			};
			fileSystemWatcher.Created += delegate
			{
				RaiseChanged(onChanged);
			};
			fileSystemWatcher.Renamed += delegate
			{
				RaiseChanged(onChanged);
			};
			fileSystemWatcher.EnableRaisingEvents = true;
			Watchers.Add(fileSystemWatcher);
		}

		public static void WatchTranslationChanges(string path, Action onChanged)
		{
			if (!Directory.Exists(CorewoodAdditionsMod.TranslationFilePath))
			{
				return;
			}
			try
			{
				WatchFileChanges(Path.Combine(path, "*.*"), onChanged, includeSubdirectories: true);
			}
			catch
			{
				Logger.LogError((object)"There was an issue loading Translation files!");
			}
		}

		private static void RaiseChanged(Action onChanged)
		{
			try
			{
				onChanged?.Invoke();
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("[CoreWoodAdditions] Failed to reload changed file: " + ex.Message));
			}
		}
	}
	[BepInPlugin("MagicMike.CorewoodAdditions", "CorewoodAdditions", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class CorewoodAdditionsMod : BaseUnityPlugin
	{
		internal const string PluginName = "CorewoodAdditions";

		internal const string PluginVersion = "1.0.2";

		internal const string PluginAuthor = "MagicMike";

		internal const string PluginGUID = "MagicMike.CorewoodAdditions";

		internal const string PluginLink = "https://www.nexusmods.com/profile/MagicMikeMods/mods";

		private static char pds = Path.DirectorySeparatorChar;

		public static readonly string _basePath = Paths.ConfigPath + pds + "CoreWoodAdditions";

		public static readonly string TranslationFilePath = _basePath + pds + "Translations";

		private CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		public static CorewoodAdditionsMod plugininstance;

		private readonly Harmony harmony = new Harmony("MagicMike.CorewoodAdditions");

		public static AssetBundle cwadditions;

		public static string additionsBundle = "corewood_additions";

		internal static ConfigFile ConfigFile;

		internal static ConfigFileWatcher ConfigFileWatcher;

		private volatile bool translationsChanged;

		private float translationReloadAt = -1f;

		public void Awake()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			plugininstance = this;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			MainConfig.InitConfigs(((BaseUnityPlugin)this).Config);
			UpdatePlugin();
			if (MainConfig.modEnabled.Value)
			{
				CheckForFolders();
				LocalisedText.AddLocalisations();
				LoadLocalisationData(TranslationFilePath);
				FileWatcher.WatchTranslationChanges(TranslationFilePath, delegate
				{
					translationsChanged = true;
				});
				LoadAssetBundles();
				PrefabManager.OnVanillaPrefabsAvailable += LoadCoreWoodAdditions;
				harmony.PatchAll(Assembly.GetExecutingAssembly());
				ConfigFileWatcher.OnConfigFileReloaded += delegate
				{
					UpdatePlugin(saveConfig: false);
				};
				SynchronizationManager.OnConfigurationWindowClosed += delegate
				{
					UpdatePlugin();
				};
				SynchronizationManager.OnConfigurationSynchronized += delegate
				{
					UpdatePlugin();
				};
				Game.isModded = true;
			}
		}

		public void Update()
		{
			ReloadTranslationsIfChanged();
		}

		private void ReloadTranslationsIfChanged()
		{
			if (translationsChanged)
			{
				translationsChanged = false;
				translationReloadAt = Time.time + 0.5f;
			}
			if (translationReloadAt >= 0f && Time.time >= translationReloadAt)
			{
				translationReloadAt = -1f;
				try
				{
					LoadLocalisationData(TranslationFilePath);
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("[CoreWoodAdditions] Could not reload the translation files: " + ex.Message));
				}
			}
		}

		public static void CheckForFolders()
		{
			if (!Directory.Exists(_basePath))
			{
				Logger.LogInfo((object)"Creating CoreWoodAdditions Directory");
				Directory.CreateDirectory(_basePath);
			}
			if (!Directory.Exists(TranslationFilePath))
			{
				Logger.LogInfo((object)"Creating Translations folder");
				Directory.CreateDirectory(TranslationFilePath);
			}
		}

		public void LoadLocalisationData(string directory)
		{
			string[] fileSystemEntries = Directory.GetFileSystemEntries(directory, "*.json", SearchOption.AllDirectories);
			foreach (string path in fileSystemEntries)
			{
				string name = new DirectoryInfo(Path.GetDirectoryName(path)).Name;
				Path.GetFileNameWithoutExtension(path);
				Localization.AddJsonFile(name, File.ReadAllText(path));
			}
		}

		public static void LoadAssetBundles()
		{
			cwadditions = AssetUtils.LoadAssetBundleFromResources(additionsBundle, Assembly.GetExecutingAssembly());
			if ((Object)(object)cwadditions == (Object)null)
			{
				Logger.LogError((object)("Failed to load asset bundle with name: " + additionsBundle));
			}
		}

		private void LoadCoreWoodAdditions()
		{
			try
			{
				AddPrefabs.LoadPieces();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Exception caught while loading CoreWood Additions: " + ex.Message));
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= LoadCoreWoodAdditions;
			}
		}

		public static void OnMainConfigChanged(object obj, EventArgs args)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name.Equals("main"))
			{
				UpdateMainSettings.MainSettingsChanged();
			}
		}

		private void UpdatePlugin(bool saveConfig = true)
		{
			if (saveConfig)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		internal static void TryAddPiece(Action addPiece)
		{
			try
			{
				addPiece();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Exception caught while adding " + addPiece.Method.Name + ": " + ex));
			}
		}
	}
}
namespace CorewoodAdditions.Updates
{
	internal class UpdateMainSettings
	{
		public static void MainSettingsChanged()
		{
		}
	}
}
namespace CorewoodAdditions.Producers
{
	internal sealed class BeeHive : MonoBehaviour
	{
		[HarmonyPatch(typeof(Container), "GetHoverName")]
		private static class Container_GetHoverName_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				BeeHive componentInParent = ((Component)__instance).GetComponentInParent<BeeHive>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent._name;
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		private static class Container_GetHoverText_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				BeeHive componentInParent = ((Component)__instance).GetComponentInParent<BeeHive>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent.BuildHoverText();
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Postfix()
			{
				_resolvedDb = null;
				_honeyItemPrefab = null;
				DisplayCache.Clear();
			}
		}

		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private static class Localization_SetupLanguage_Patch
		{
			private static void Postfix()
			{
				DisplayCache.Clear();
			}
		}

		internal const string PrefabName = "mm_corewood_beehive";

		private const string EnabledHiveChildName = "enabled_hive";

		private const string ItemCraftedChildName = "item_crafted";

		private const string SfxChildName = "SFX";

		private const string HoneyPrefabName = "Honey";

		private const string DefaultConsumable = "Dandelion";

		private const int MaxConsumableTypes = 10;

		private const string TokenWorking = "$text_beehive_working";

		private const string TokenNoConsumable = "$text_beehive_no_consumable";

		private const string TokenFull = "$text_beehive_full";

		private static readonly int ZdoStartTimeHash = StringExtensionMethods.GetStableHashCode("mm_beehive_starttime");

		private static readonly int ZdoAccTimeHash = StringExtensionMethods.GetStableHashCode("mm_beehive_acctime");

		private static ItemDrop _honeyItemPrefab;

		private static ObjectDB _resolvedDb;

		private static string _cachedConsumablesRaw;

		private static HashSet<string> _consumablePrefabNames = new HashSet<string>(StringComparer.Ordinal);

		private static readonly Dictionary<string, string> DisplayCache = new Dictionary<string, string>(StringComparer.Ordinal);

		private ZNetView _nview;

		private Piece _piece;

		private Container _container;

		private string _name = "$piece_container";

		private bool _productionTickRunning;

		private GameObject _enabledHive;

		private GameObject _itemCrafted;

		private GameObject _sfx;

		private Inventory _subscribedInventory;

		private bool _visualsDirty;

		private static float SecPerBatch => Mathf.Max(0.1f, MainConfig.beehiveSecPerBatch.Value);

		private static int ConsumablePerBatch => Mathf.Max(1, MainConfig.beehiveConsumablePerBatch.Value);

		private static int HoneyPerBatch => Mathf.Max(1, MainConfig.beehiveHoneyPerBatch.Value);

		private static int MaxHoney => Mathf.Max(1, MainConfig.beehiveMaxHoney.Value);

		private static ItemDrop GetHoneyPrefab()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)_resolvedDb)
			{
				_resolvedDb = instance;
				GameObject itemPrefab = instance.GetItemPrefab("Honey");
				_honeyItemPrefab = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			}
			return _honeyItemPrefab;
		}

		private static HashSet<string> GetConsumablePrefabNames()
		{
			string text = MainConfig.beehiveConsumables?.Value ?? string.Empty;
			if (string.Equals(_cachedConsumablesRaw, text, StringComparison.Ordinal))
			{
				return _consumablePrefabNames;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (!string.IsNullOrWhiteSpace(text2))
				{
					hashSet.Add(text2);
					if (hashSet.Count >= 10)
					{
						break;
					}
				}
			}
			if (hashSet.Count == 0)
			{
				hashSet.Add("Dandelion");
			}
			_cachedConsumablesRaw = text;
			_consumablePrefabNames = hashSet;
			return hashSet;
		}

		private static bool IsConsumable(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return GetConsumablePrefabNames().Contains(((Object)item.m_dropPrefab).name);
			}
			return false;
		}

		private static bool IsHoney(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name == "Honey";
			}
			return false;
		}

		private static string GetLocalizedItemName(string prefabName)
		{
			ObjectDB instance = ObjectDB.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				GameObject itemPrefab = instance.GetItemPrefab(prefabName);
				obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name);
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				return Localization.instance.Localize(text);
			}
			return prefabName;
		}

		private static string GetAcceptedLine()
		{
			HashSet<string> consumablePrefabNames = GetConsumablePrefabNames();
			string key = _cachedConsumablesRaw + "#" + ConsumablePerBatch + ":" + (((Object)(object)ObjectDB.instance != (Object)null) ? "1" : "0");
			if (DisplayCache.TryGetValue(key, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			foreach (string item in consumablePrefabNames)
			{
				list.Add(GetLocalizedItemName(item));
			}
			string text = "<color=yellow>" + GetLocalizedItemName("Honey") + "</color>: " + ConsumablePerBatch + "x " + string.Join(", ", list);
			DisplayCache[key] = text;
			return text;
		}

		private static int GetConsumableCount(Inventory inventory)
		{
			long num = 0L;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsConsumable(allItem))
				{
					num += allItem.m_stack;
					if (num >= int.MaxValue)
					{
						return int.MaxValue;
					}
				}
			}
			return (int)num;
		}

		private static bool HasEnoughConsumableForBatch(Inventory inventory)
		{
			return GetConsumableCount(inventory) >= ConsumablePerBatch;
		}

		private static bool TryConsumeConsumable(Inventory inventory, int amountNeeded)
		{
			int num = amountNeeded;
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				if (IsConsumable(item))
				{
					int num2 = Math.Min(item.m_stack, num);
					if (num2 > 0 && inventory.RemoveItem(item, num2))
					{
						num -= num2;
					}
					if (num <= 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryAddHoney(Inventory inventory, int amount)
		{
			ItemDrop honeyPrefab = GetHoneyPrefab();
			if ((Object)(object)honeyPrefab == (Object)null)
			{
				return false;
			}
			ItemData val = honeyPrefab.m_itemData.Clone();
			val.m_dropPrefab = ((Component)honeyPrefab).gameObject;
			val.m_stack = amount;
			val.m_quality = 1;
			return inventory.AddItem(val);
		}

		private static bool CanStackHoney(Inventory inventory)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsHoney(allItem) && allItem.m_stack < allItem.m_shared.m_maxStackSize)
				{
					return true;
				}
			}
			return false;
		}

		private int GetHoneyCount()
		{
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (val == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in val.GetAllItems())
			{
				if (IsHoney(allItem))
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_piece = ((Component)this).GetComponent<Piece>();
			_container = ((Component)this).GetComponent<Container>();
			if ((Object)(object)_container == (Object)null)
			{
				_container = ((Component)this).GetComponentInChildren<Container>(true);
			}
			if ((Object)(object)_piece != (Object)null && !string.IsNullOrEmpty(_piece.m_name))
			{
				_name = _piece.m_name;
			}
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && (Object)(object)_container != (Object)null && _container.GetInventory() != null)
			{
				InitializePersistentTimer();
				((MonoBehaviour)this).InvokeRepeating("UpdateOwnershipTick", 1f, 1f);
			}
		}

		private void Start()
		{
			_enabledHive = ProducerVisuals.FindChildRecursive(((Component)this).transform, "enabled_hive");
			_itemCrafted = ProducerVisuals.FindChildRecursive(((Component)this).transform, "item_crafted");
			ProducerVisuals.RouteAudioToSfx(_enabledHive);
			_sfx = (((Object)(object)_enabledHive != (Object)null) ? ProducerVisuals.FindChildRecursive(_enabledHive.transform, "SFX") : null);
			ApplySfxSetting();
			_subscribedInventory = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Combine(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
			}
			UpdateEnabledHiveVisual();
		}

		private void MarkVisualsDirty()
		{
			_visualsDirty = true;
		}

		private void LateUpdate()
		{
			if (_visualsDirty)
			{
				_visualsDirty = false;
				UpdateEnabledHiveVisual();
			}
		}

		private void OnDestroy()
		{
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Remove(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
				_subscribedInventory = null;
			}
		}

		internal static void RefreshAllSfx()
		{
			BeeHive[] array = Object.FindObjectsByType<BeeHive>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].ApplySfxSetting();
			}
		}

		private void ApplySfxSetting()
		{
			ProducerVisuals.SetSfxEnabled(_sfx, MainConfig.beehiveSoundEnabled.Value);
		}

		internal static void RefreshAllItemCrafted()
		{
			BeeHive[] array = Object.FindObjectsByType<BeeHive>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].UpdateItemCraftedVisual();
			}
		}

		private void UpdateItemCraftedVisual()
		{
			if (!((Object)(object)_itemCrafted == (Object)null))
			{
				bool flag = MainConfig.beehiveShowIcon.Value && GetHoneyCount() > 0;
				if (_itemCrafted.activeSelf != flag)
				{
					_itemCrafted.SetActive(flag);
				}
			}
		}

		private void UpdateEnabledHiveVisual()
		{
			UpdateItemCraftedVisual();
			if ((Object)(object)_enabledHive == (Object)null)
			{
				return;
			}
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			bool flag = val != null && val.NrOfItems() > 0;
			if (_enabledHive.activeSelf != flag)
			{
				if (!flag)
				{
					ProducerVisuals.UnregisterLoopingSfx(_enabledHive);
				}
				_enabledHive.SetActive(flag);
			}
		}

		private void UpdateOwnershipTick()
		{
			bool flag = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner();
			if (flag && !_productionTickRunning)
			{
				((MonoBehaviour)this).InvokeRepeating("UpdateBeeHive", 1f, 1f);
				_productionTickRunning = true;
			}
			else if (!flag && _productionTickRunning)
			{
				((MonoBehaviour)this).CancelInvoke("UpdateBeeHive");
				_productionTickRunning = false;
			}
		}

		private void UpdateBeeHive()
		{
			if (!_nview.IsValid() || !_nview.IsOwner())
			{
				return;
			}
			Inventory inventory = _container.GetInventory();
			if (inventory == null)
			{
				return;
			}
			if (!CanProduceOneBatchNow(inventory))
			{
				ResetProductionClock();
				return;
			}
			float num = GetAccumulator() + (float)GetDeltaTime();
			int num2 = ((num / SecPerBatch >= 2.1474836E+09f) ? int.MaxValue : Mathf.FloorToInt(num / SecPerBatch));
			int num3 = GetConsumableCount(inventory) / ConsumablePerBatch;
			int num4 = Mathf.Max(0, MaxHoney - GetHoneyCount()) / HoneyPerBatch;
			int num5 = Mathf.Min(num2, Mathf.Min(num3, num4));
			if (num5 <= 0)
			{
				SetAccumulator(num);
				return;
			}
			int num6 = 0;
			for (int i = 0; i < num5; i++)
			{
				if (!CanProduceOneBatchNow(inventory))
				{
					break;
				}
				if (!TryConsumeConsumable(inventory, ConsumablePerBatch))
				{
					break;
				}
				if (!TryAddHoney(inventory, HoneyPerBatch))
				{
					break;
				}
				num6++;
			}
			if (num6 <= 0)
			{
				ResetProductionClock();
				return;
			}
			num = Mathf.Max(0f, num - (float)num6 * SecPerBatch);
			if (!CanProduceOneBatchNow(inventory))
			{
				ResetProductionClock();
			}
			else
			{
				SetAccumulator(num);
			}
		}

		private bool CanProduceOneBatchNow(Inventory inventory)
		{
			if (HasEnoughConsumableForBatch(inventory) && !IsFullForProduction(inventory))
			{
				return (Object)(object)GetHoneyPrefab() != (Object)null;
			}
			return false;
		}

		private bool IsFullForProduction(Inventory inventory)
		{
			if (Mathf.Max(0, MaxHoney - GetHoneyCount()) < HoneyPerBatch)
			{
				return true;
			}
			if (!inventory.HaveEmptySlot())
			{
				return !CanStackHoney(inventory);
			}
			return false;
		}

		private string BuildHoverText()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			string acceptedLine = GetAcceptedLine();
			string text = Localization.instance.Localize(_name);
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
			{
				return Localization.instance.Localize(text + "\n" + acceptedLine + "\n$piece_noaccess");
			}
			string text2 = Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open");
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			string text3 = "red";
			string text4;
			if (val == null)
			{
				text4 = "$text_beehive_no_consumable";
			}
			else if (IsFullForProduction(val))
			{
				text4 = "$text_beehive_full";
			}
			else if (!HasEnoughConsumableForBatch(val))
			{
				text4 = "$text_beehive_no_consumable";
			}
			else
			{
				text4 = "$text_beehive_working";
				text3 = "orange";
			}
			string text5 = Localization.instance.Localize(text4);
			if (text4 == "$text_beehive_working")
			{
				text5 = text5 + " " + FormatCountdown(GetSecondsUntilNextBatch());
			}
			return $"{text} - ({GetHoneyCount()}/{MaxHoney})\n{acceptedLine}\n<color={text3}>{text5}</color>\n{text2}";
		}

		private float GetSecondsUntilNextBatch()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || (Object)(object)ZNet.instance == (Object)null)
			{
				return SecPerBatch;
			}
			DateTime time = ZNet.instance.GetTime();
			long num = _nview.GetZDO().GetLong(ZdoStartTimeHash, time.Ticks);
			DateTime minValue = DateTime.MinValue;
			double num2;
			if (num >= minValue.Ticks)
			{
				minValue = DateTime.MaxValue;
				if (num <= minValue.Ticks)
				{
					num2 = Math.Max(0.0, (time - new DateTime(num)).TotalSeconds);
					goto IL_00a6;
				}
			}
			num2 = 0.0;
			goto IL_00a6;
			IL_00a6:
			double num3 = num2;
			double num4 = (double)GetAccumulator() + num3;
			return Mathf.Max(0f, SecPerBatch - (float)num4);
		}

		private static string FormatCountdown(float seconds)
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(Mathf.CeilToInt(seconds));
			if (!(timeSpan.TotalHours >= 1.0))
			{
				return $"({timeSpan.Minutes:00}:{timeSpan.Seconds:00})";
			}
			return $"({(int)timeSpan.TotalHours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00})";
		}

		private void InitializePersistentTimer()
		{
			if (_nview.IsOwner())
			{
				ZDO zDO = _nview.GetZDO();
				if ((Object)(object)ZNet.instance != (Object)null && zDO.GetLong(ZdoStartTimeHash, 0L) == 0L)
				{
					zDO.Set(ZdoStartTimeHash, ZNet.instance.GetTime().Ticks);
				}
				float num = zDO.GetFloat(ZdoAccTimeHash, 0f);
				if (float.IsNaN(num) || float.IsInfinity(num) || num < 0f)
				{
					zDO.Set(ZdoAccTimeHash, 0f);
				}
			}
		}

		private double GetDeltaTime()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0.0;
			}
			DateTime time = ZNet.instance.GetTime();
			ZDO zDO = _nview.GetZDO();
			long num = zDO.GetLong(ZdoStartTimeHash, time.Ticks);
			DateTime minValue = DateTime.MinValue;
			DateTime dateTime;
			if (num >= minValue.Ticks)
			{
				minValue = DateTime.MaxValue;
				if (num <= minValue.Ticks)
				{
					dateTime = new DateTime(num);
					goto IL_0094;
				}
			}
			dateTime = time;
			goto IL_0094;
			IL_0094:
			DateTime dateTime2 = dateTime;
			double result = Math.Max(0.0, (time - dateTime2).TotalSeconds);
			zDO.Set(ZdoStartTimeHash, time.Ticks);
			return result;
		}

		private float GetAccumulator()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return 0f;
			}
			float num = _nview.GetZDO().GetFloat(ZdoAccTimeHash, 0f);
			if (!float.IsNaN(num) && !float.IsInfinity(num) && !(num < 0f))
			{
				return num;
			}
			return 0f;
		}

		private void SetAccumulator(float value)
		{
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner())
			{
				_nview.GetZDO().Set(ZdoAccTimeHash, (float.IsNaN(value) || float.IsInfinity(value) || value < 0f) ? 0f : value);
			}
		}

		private void ResetProductionClock()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner())
			{
				SetAccumulator(0f);
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					_nview.GetZDO().Set(ZdoStartTimeHash, ZNet.instance.GetTime().Ticks);
				}
			}
		}
	}
	internal sealed class BirdHouse : MonoBehaviour
	{
		[HarmonyPatch(typeof(Container), "GetHoverName")]
		private static class Container_GetHoverName_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				BirdHouse componentInParent = ((Component)__instance).GetComponentInParent<BirdHouse>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent._name;
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		private static class Container_GetHoverText_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				BirdHouse componentInParent = ((Component)__instance).GetComponentInParent<BirdHouse>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent.BuildHoverText();
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Postfix()
			{
				_resolvedDb = null;
				_featherItemPrefab = null;
				DisplayCache.Clear();
			}
		}

		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private static class Localization_SetupLanguage_Patch
		{
			private static void Postfix()
			{
				DisplayCache.Clear();
			}
		}

		internal const string PrefabName = "mm_corewood_birdhouse";

		private const string EnabledBirdboxChildName = "enabled_birdbox";

		private const string ItemCraftedChildName = "item_crafted";

		private const string SfxChildName = "SFX";

		private const string FeatherPrefabName = "Feathers";

		private const string DefaultConsumable = "TurnipSeeds";

		private const int MaxConsumableTypes = 10;

		private const string TokenWorking = "$text_birdhouse_working";

		private const string TokenNoConsumable = "$text_birdhouse_no_consumable";

		private const string TokenFull = "$text_birdhouse_full";

		private static readonly int ZdoStartTimeHash = StringExtensionMethods.GetStableHashCode("mm_birdhouse_starttime");

		private static readonly int ZdoAccTimeHash = StringExtensionMethods.GetStableHashCode("mm_birdhouse_acctime");

		private static ItemDrop _featherItemPrefab;

		private static ObjectDB _resolvedDb;

		private static string _cachedConsumablesRaw;

		private static HashSet<string> _consumablePrefabNames = new HashSet<string>(StringComparer.Ordinal);

		private static readonly Dictionary<string, string> DisplayCache = new Dictionary<string, string>(StringComparer.Ordinal);

		private ZNetView _nview;

		private Piece _piece;

		private Container _container;

		private string _name = "$piece_container";

		private bool _productionTickRunning;

		private GameObject _enabledBirdbox;

		private GameObject _itemCrafted;

		private GameObject _sfx;

		private Inventory _subscribedInventory;

		private bool _visualsDirty;

		private static float SecPerBatch => Mathf.Max(0.1f, MainConfig.birdhouseSecPerBatch.Value);

		private static int ConsumablePerBatch => Mathf.Max(1, MainConfig.birdhouseConsumablePerBatch.Value);

		private static int FeathersPerBatch => Mathf.Max(1, MainConfig.birdhouseFeathersPerBatch.Value);

		private static int MaxFeathers => Mathf.Max(1, MainConfig.birdhouseMaxFeathers.Value);

		private static ItemDrop GetFeatherPrefab()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)_resolvedDb)
			{
				_resolvedDb = instance;
				GameObject itemPrefab = instance.GetItemPrefab("Feathers");
				_featherItemPrefab = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			}
			return _featherItemPrefab;
		}

		private static HashSet<string> GetConsumablePrefabNames()
		{
			string text = MainConfig.birdhouseConsumables?.Value ?? string.Empty;
			if (string.Equals(_cachedConsumablesRaw, text, StringComparison.Ordinal))
			{
				return _consumablePrefabNames;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (!string.IsNullOrWhiteSpace(text2))
				{
					hashSet.Add(text2);
					if (hashSet.Count >= 10)
					{
						break;
					}
				}
			}
			if (hashSet.Count == 0)
			{
				hashSet.Add("TurnipSeeds");
			}
			_cachedConsumablesRaw = text;
			_consumablePrefabNames = hashSet;
			return hashSet;
		}

		private static bool IsConsumable(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return GetConsumablePrefabNames().Contains(((Object)item.m_dropPrefab).name);
			}
			return false;
		}

		private static bool IsFeather(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name == "Feathers";
			}
			return false;
		}

		private static string GetLocalizedItemName(string prefabName)
		{
			ObjectDB instance = ObjectDB.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				GameObject itemPrefab = instance.GetItemPrefab(prefabName);
				obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name);
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				return Localization.instance.Localize(text);
			}
			return prefabName;
		}

		private static string GetAcceptedLine()
		{
			HashSet<string> consumablePrefabNames = GetConsumablePrefabNames();
			string key = _cachedConsumablesRaw + "#" + ConsumablePerBatch + ":" + (((Object)(object)ObjectDB.instance != (Object)null) ? "1" : "0");
			if (DisplayCache.TryGetValue(key, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			foreach (string item in consumablePrefabNames)
			{
				list.Add(GetLocalizedItemName(item));
			}
			string text = "<color=yellow>" + GetLocalizedItemName("Feathers") + "</color>: " + ConsumablePerBatch + "x " + string.Join(", ", list);
			DisplayCache[key] = text;
			return text;
		}

		private static int GetConsumableCount(Inventory inventory)
		{
			long num = 0L;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsConsumable(allItem))
				{
					num += allItem.m_stack;
					if (num >= int.MaxValue)
					{
						return int.MaxValue;
					}
				}
			}
			return (int)num;
		}

		private static bool HasEnoughConsumableForBatch(Inventory inventory)
		{
			return GetConsumableCount(inventory) >= ConsumablePerBatch;
		}

		private static bool TryConsumeConsumable(Inventory inventory, int amountNeeded)
		{
			int num = amountNeeded;
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				if (IsConsumable(item))
				{
					int num2 = Math.Min(item.m_stack, num);
					if (num2 > 0 && inventory.RemoveItem(item, num2))
					{
						num -= num2;
					}
					if (num <= 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryAddFeathers(Inventory inventory, int amount)
		{
			ItemDrop featherPrefab = GetFeatherPrefab();
			if ((Object)(object)featherPrefab == (Object)null)
			{
				return false;
			}
			ItemData val = featherPrefab.m_itemData.Clone();
			val.m_dropPrefab = ((Component)featherPrefab).gameObject;
			val.m_stack = amount;
			val.m_quality = 1;
			return inventory.AddItem(val);
		}

		private static bool CanStackFeathers(Inventory inventory)
		{
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsFeather(allItem) && allItem.m_stack < allItem.m_shared.m_maxStackSize)
				{
					return true;
				}
			}
			return false;
		}

		private int GetFeatherCount()
		{
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (val == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in val.GetAllItems())
			{
				if (IsFeather(allItem))
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_piece = ((Component)this).GetComponent<Piece>();
			_container = ((Component)this).GetComponent<Container>();
			if ((Object)(object)_container == (Object)null)
			{
				_container = ((Component)this).GetComponentInChildren<Container>(true);
			}
			if ((Object)(object)_piece != (Object)null && !string.IsNullOrEmpty(_piece.m_name))
			{
				_name = _piece.m_name;
			}
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && (Object)(object)_container != (Object)null && _container.GetInventory() != null)
			{
				InitializePersistentTimer();
				((MonoBehaviour)this).InvokeRepeating("UpdateOwnershipTick", 1f, 1f);
			}
		}

		private void Start()
		{
			_enabledBirdbox = ProducerVisuals.FindChildRecursive(((Component)this).transform, "enabled_birdbox");
			_itemCrafted = ProducerVisuals.FindChildRecursive(((Component)this).transform, "item_crafted");
			ProducerVisuals.RouteAudioToSfx(_enabledBirdbox);
			_sfx = (((Object)(object)_enabledBirdbox != (Object)null) ? ProducerVisuals.FindChildRecursive(_enabledBirdbox.transform, "SFX") : null);
			ApplySfxSetting();
			_subscribedInventory = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Combine(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
			}
			UpdateEnabledBirdboxVisual();
		}

		private void MarkVisualsDirty()
		{
			_visualsDirty = true;
		}

		private void LateUpdate()
		{
			if (_visualsDirty)
			{
				_visualsDirty = false;
				UpdateEnabledBirdboxVisual();
			}
		}

		private void OnDestroy()
		{
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Remove(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
				_subscribedInventory = null;
			}
		}

		internal static void RefreshAllSfx()
		{
			BirdHouse[] array = Object.FindObjectsByType<BirdHouse>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].ApplySfxSetting();
			}
		}

		private void ApplySfxSetting()
		{
			ProducerVisuals.SetSfxEnabled(_sfx, MainConfig.birdhouseSoundEnabled.Value);
		}

		internal static void RefreshAllItemCrafted()
		{
			BirdHouse[] array = Object.FindObjectsByType<BirdHouse>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].UpdateItemCraftedVisual();
			}
		}

		private void UpdateItemCraftedVisual()
		{
			if (!((Object)(object)_itemCrafted == (Object)null))
			{
				bool flag = MainConfig.birdhouseShowIcon.Value && GetFeatherCount() > 0;
				if (_itemCrafted.activeSelf != flag)
				{
					_itemCrafted.SetActive(flag);
				}
			}
		}

		private void UpdateEnabledBirdboxVisual()
		{
			UpdateItemCraftedVisual();
			if ((Object)(object)_enabledBirdbox == (Object)null)
			{
				return;
			}
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			bool flag = val != null && val.NrOfItems() > 0;
			if (_enabledBirdbox.activeSelf != flag)
			{
				if (!flag)
				{
					ProducerVisuals.UnregisterLoopingSfx(_enabledBirdbox);
				}
				_enabledBirdbox.SetActive(flag);
			}
		}

		private void UpdateOwnershipTick()
		{
			bool flag = (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner();
			if (flag && !_productionTickRunning)
			{
				((MonoBehaviour)this).InvokeRepeating("UpdateBirdHouse", 1f, 1f);
				_productionTickRunning = true;
			}
			else if (!flag && _productionTickRunning)
			{
				((MonoBehaviour)this).CancelInvoke("UpdateBirdHouse");
				_productionTickRunning = false;
			}
		}

		private void UpdateBirdHouse()
		{
			if (!_nview.IsValid() || !_nview.IsOwner())
			{
				return;
			}
			Inventory inventory = _container.GetInventory();
			if (inventory == null)
			{
				return;
			}
			if (!CanProduceOneBatchNow(inventory))
			{
				ResetProductionClock();
				return;
			}
			float num = GetAccumulator() + (float)GetDeltaTime();
			int num2 = ((num / SecPerBatch >= 2.1474836E+09f) ? int.MaxValue : Mathf.FloorToInt(num / SecPerBatch));
			int num3 = GetConsumableCount(inventory) / ConsumablePerBatch;
			int num4 = Mathf.Max(0, MaxFeathers - GetFeatherCount()) / FeathersPerBatch;
			int num5 = Mathf.Min(num2, Mathf.Min(num3, num4));
			if (num5 <= 0)
			{
				SetAccumulator(num);
				return;
			}
			int num6 = 0;
			for (int i = 0; i < num5; i++)
			{
				if (!CanProduceOneBatchNow(inventory))
				{
					break;
				}
				if (!TryConsumeConsumable(inventory, ConsumablePerBatch))
				{
					break;
				}
				if (!TryAddFeathers(inventory, FeathersPerBatch))
				{
					break;
				}
				num6++;
			}
			if (num6 <= 0)
			{
				ResetProductionClock();
				return;
			}
			num = Mathf.Max(0f, num - (float)num6 * SecPerBatch);
			if (!CanProduceOneBatchNow(inventory))
			{
				ResetProductionClock();
			}
			else
			{
				SetAccumulator(num);
			}
		}

		private bool CanProduceOneBatchNow(Inventory inventory)
		{
			if (HasEnoughConsumableForBatch(inventory) && !IsFullForProduction(inventory))
			{
				return (Object)(object)GetFeatherPrefab() != (Object)null;
			}
			return false;
		}

		private bool IsFullForProduction(Inventory inventory)
		{
			if (Mathf.Max(0, MaxFeathers - GetFeatherCount()) < FeathersPerBatch)
			{
				return true;
			}
			if (!inventory.HaveEmptySlot())
			{
				return !CanStackFeathers(inventory);
			}
			return false;
		}

		private string BuildHoverText()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			string acceptedLine = GetAcceptedLine();
			string text = Localization.instance.Localize(_name);
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
			{
				return Localization.instance.Localize(text + "\n" + acceptedLine + "\n$piece_noaccess");
			}
			string text2 = Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open");
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			string text3 = "red";
			string text4;
			if (val == null)
			{
				text4 = "$text_birdhouse_no_consumable";
			}
			else if (IsFullForProduction(val))
			{
				text4 = "$text_birdhouse_full";
			}
			else if (!HasEnoughConsumableForBatch(val))
			{
				text4 = "$text_birdhouse_no_consumable";
			}
			else
			{
				text4 = "$text_birdhouse_working";
				text3 = "orange";
			}
			string text5 = Localization.instance.Localize(text4);
			if (text4 == "$text_birdhouse_working")
			{
				text5 = text5 + " " + FormatCountdown(GetSecondsUntilNextBatch());
			}
			return $"{text} - ({GetFeatherCount()}/{MaxFeathers})\n{acceptedLine}\n<color={text3}>{text5}</color>\n{text2}";
		}

		private float GetSecondsUntilNextBatch()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || (Object)(object)ZNet.instance == (Object)null)
			{
				return SecPerBatch;
			}
			DateTime time = ZNet.instance.GetTime();
			long num = _nview.GetZDO().GetLong(ZdoStartTimeHash, time.Ticks);
			DateTime minValue = DateTime.MinValue;
			double num2;
			if (num >= minValue.Ticks)
			{
				minValue = DateTime.MaxValue;
				if (num <= minValue.Ticks)
				{
					num2 = Math.Max(0.0, (time - new DateTime(num)).TotalSeconds);
					goto IL_00a6;
				}
			}
			num2 = 0.0;
			goto IL_00a6;
			IL_00a6:
			double num3 = num2;
			double num4 = (double)GetAccumulator() + num3;
			return Mathf.Max(0f, SecPerBatch - (float)num4);
		}

		private static string FormatCountdown(float seconds)
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(Mathf.CeilToInt(seconds));
			if (!(timeSpan.TotalHours >= 1.0))
			{
				return $"({timeSpan.Minutes:00}:{timeSpan.Seconds:00})";
			}
			return $"({(int)timeSpan.TotalHours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00})";
		}

		private void InitializePersistentTimer()
		{
			if (_nview.IsOwner())
			{
				ZDO zDO = _nview.GetZDO();
				if ((Object)(object)ZNet.instance != (Object)null && zDO.GetLong(ZdoStartTimeHash, 0L) == 0L)
				{
					zDO.Set(ZdoStartTimeHash, ZNet.instance.GetTime().Ticks);
				}
				float num = zDO.GetFloat(ZdoAccTimeHash, 0f);
				if (float.IsNaN(num) || float.IsInfinity(num) || num < 0f)
				{
					zDO.Set(ZdoAccTimeHash, 0f);
				}
			}
		}

		private double GetDeltaTime()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner() || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0.0;
			}
			DateTime time = ZNet.instance.GetTime();
			ZDO zDO = _nview.GetZDO();
			long num = zDO.GetLong(ZdoStartTimeHash, time.Ticks);
			DateTime minValue = DateTime.MinValue;
			DateTime dateTime;
			if (num >= minValue.Ticks)
			{
				minValue = DateTime.MaxValue;
				if (num <= minValue.Ticks)
				{
					dateTime = new DateTime(num);
					goto IL_0094;
				}
			}
			dateTime = time;
			goto IL_0094;
			IL_0094:
			DateTime dateTime2 = dateTime;
			double result = Math.Max(0.0, (time - dateTime2).TotalSeconds);
			zDO.Set(ZdoStartTimeHash, time.Ticks);
			return result;
		}

		private float GetAccumulator()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return 0f;
			}
			float num = _nview.GetZDO().GetFloat(ZdoAccTimeHash, 0f);
			if (!float.IsNaN(num) && !float.IsInfinity(num) && !(num < 0f))
			{
				return num;
			}
			return 0f;
		}

		private void SetAccumulator(float value)
		{
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner())
			{
				_nview.GetZDO().Set(ZdoAccTimeHash, (float.IsNaN(value) || float.IsInfinity(value) || value < 0f) ? 0f : value);
			}
		}

		private void ResetProductionClock()
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner())
			{
				SetAccumulator(0f);
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					_nview.GetZDO().Set(ZdoStartTimeHash, ZNet.instance.GetTime().Ticks);
				}
			}
		}
	}
	internal sealed class CompostBin : MonoBehaviour
	{
		internal sealed class BaitDefinition
		{
			public readonly string ConfigLabel;

			public readonly string[] PrefabCandidates;

			public readonly string[] Keywords;

			public readonly string DefaultConsumable;

			public int Amount;

			public ItemDrop ItemPrefab;

			public BaitDefinition(string configLabel, string[] prefabCandidates, string[] keywords, string defaultConsumable, int defaultAmount)
			{
				ConfigLabel = configLabel;
				PrefabCandidates = prefabCandidates;
				Keywords = keywords;
				DefaultConsumable = defaultConsumable;
				Amount = defaultAmount;
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverName")]
		private static class Container_GetHoverName_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				CompostBin componentInParent = ((Component)__instance).GetComponentInParent<CompostBin>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent._name;
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		private static class Container_GetHoverText_Patch
		{
			private static void Postfix(Container __instance, ref string __result)
			{
				CompostBin componentInParent = ((Component)__instance).GetComponentInParent<CompostBin>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					__result = componentInParent.BuildHoverText();
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Postfix()
			{
				_resolvedDb = null;
				BaitPrefabNames.Clear();
				DisplayCache.Clear();
			}
		}

		[HarmonyPatch(typeof(Localization), "SetupLanguage")]
		private static class Localization_SetupLanguage_Patch
		{
			private static void Postfix()
			{
				DisplayCache.Clear();
			}
		}

		internal const string PrefabName = "mm_corewood_compost_bin";

		private const string EnabledBinChildName = "enabled_bin";

		private const string ItemCraftedChildName = "item_crafted";

		private const string TokenWorking = "$text_compostbin_working";

		private const string TokenNoConsumable = "$text_compostbin_no_consumable";

		private const string TokenFull = "$text_compostbin_full";

		private static readonly int ZdoStartTimeHash = StringExtensionMethods.GetStableHashCode("mm_compostbin_starttime");

		private static readonly int ZdoAccTimeHash = StringExtensionMethods.GetStableHashCode("mm_compostbin_acctime");

		internal static readonly BaitDefinition[] Baits = new BaitDefinition[10]
		{
			new BaitDefinition("Fishing Bait", new string[1] { "FishingBait" }, Array.Empty<string>(), "RawMeat", 10),
			new BaitDefinition("Mossy Fishing Bait", new string[2] { "FishingBaitForest", "BaitForest" }, new string[2] { "forest", "mossy" }, "DeerMeat", 10),
			new BaitDefinition("Sticky Fishing Bait", new string[2] { "FishingBaitSwamp", "BaitSwamp" }, new string[2] { "swamp", "sticky" }, "Entrails", 10),
			new BaitDefinition("Cold Fishing Bait", new string[4] { "FishingBaitCave", "FishingBaitMountain", "BaitCave", "BaitMountain" }, new string[3] { "cave", "mountain", "cold" }, "WolfMeat", 10),
			new BaitDefinition("Stingy Fishing Bait", new string[2] { "FishingBaitPlains", "BaitPlains" }, new string[2] { "plain", "stingy" }, "LoxMeat", 10),
			new BaitDefinition("Heavy Fishing Bait", new string[2] { "FishingBaitOcean", "BaitOcean" }, new string[2] { "ocean", "heavy" }, "SerpentMeat", 10),
			new BaitDefinition("Misty Fishing Bait", new string[2] { "FishingBaitMistlands", "BaitMistlands" }, new string[1] { "mist" }, "HareMeat", 10),
			new BaitDefinition("Hot Fishing Bait", new string[2] { "FishingBaitAshlands", "BaitAshlands" }, new string[2] { "ash", "hot" }, "AsksvinMeat", 10),
			new BaitDefinition("Frosty Fishing Bait", new string[2] { "FishingBaitDeepNorth", "BaitDeepNorth" }, new string[2] { "north", "frost" }, "SealBlubber", 10),
			new BaitDefinition("Serpent Bait", new string[1] { "SerpentBait" }, Array.Empty<string>(), "BjornMeat", 1)
		};

		private static string[] _cachedRaws = Array.Empty<string>();

		private static Dictionary<string, int> _foodToBait = new Dictionary<string, int>(StringComparer.Ordinal);

		private static readonly HashSet<string> BaitPrefabNames = new HashSet<string>(StringComparer.Ordinal);

		private static readonly int[] ScratchCounts = new int[Baits.Length];

		private static readonly Dictionary<string, string> DisplayCache = new Dictionary<string, string>(StringComparer.Ordinal);

		private static ObjectDB _resolvedDb;

		private ZNetView _nview;

		private Piece _piece;

		private Container _container;

		private string _name = "$piece_container";

		private bool _productionTickRunning;

		private GameObject _enabledBin;

		private GameObject _itemCrafted;

		private Inventory _subscribedInventory;

		private bool _visualsDirty;

		private static float SecPerCycle => Mathf.Max(0.1f, MainConfig.compostSecPerCycle.Value);

		private static int ConsumablePerCycle => Mathf.Max(1, MainConfig.compostConsumablePerCycle.Value);

		private static int MaxBait => Mathf.Max(1, MainConfig.compostMaxBait.Value);

		private static int AmountFor(int baitIndex)
		{
			return Mathf.Max(1, Baits[baitIndex].Amount);
		}

		private static int MinAmount()
		{
			int num = int.MaxValue;
			for (int i = 0; i < Baits.Length; i++)
			{
				num = Mathf.Min(num, AmountFor(i));
			}
			return num;
		}

		private static string[] ReadRaws()
		{
			string[] array = new string[Baits.Length];
			for (int i = 0; i < array.Length; i++)
			{
				string text = ((MainConfig.compostConsumables.Length > i && MainConfig.compostConsumables[i] != null) ? (MainConfig.compostConsumables[i].Value ?? string.Empty) : string.Empty);
				if (!MainConfig.serpentBaitEnabled.Value && Baits[i].PrefabCandidates[0] == "SerpentBait")
				{
					text = string.Empty;
				}
				array[i] = text + "#" + ConsumablePerCycle;
			}
			return array;
		}

		private static void EnsureBaitsResolved()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)_resolvedDb || instance.m_items == null || instance.m_items.Count == 0)
			{
				return;
			}
			_resolvedDb = instance;
			BaitPrefabNames.Clear();
			List<ItemDrop> list = new List<ItemDrop>();
			foreach (GameObject item in instance.m_items)
			{
				if ((Object)(object)item != (Object)null && ((Object)item).name.IndexOf("bait", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					ItemDrop component = item.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null && !list.Contains(component))
					{
						list.Add(component);
					}
				}
			}
			Fish val = default(Fish);
			foreach (GameObject item2 in instance.m_items)
			{
				if ((Object)(object)item2 == (Object)null || !item2.TryGetComponent<Fish>(ref val))
				{
					continue;
				}
				foreach (BaitSetting bait in val.m_baits)
				{
					if ((Object)(object)bait.m_bait != (Object)null && !list.Contains(bait.m_bait))
					{
						list.Add(bait.m_bait);
					}
				}
			}
			HashSet<ItemDrop> used = new HashSet<ItemDrop>();
			BaitDefinition[] baits = Baits;
			foreach (BaitDefinition baitDefinition in baits)
			{
				baitDefinition.ItemPrefab = null;
				string[] prefabCandidates = baitDefinition.PrefabCandidates;
				foreach (string name in prefabCandidates)
				{
					baitDefinition.ItemPrefab = list.Find((ItemDrop d) => !used.Contains(d) && string.Equals(((Object)d).name, name, StringComparison.OrdinalIgnoreCase));
					if ((Object)(object)baitDefinition.ItemPrefab != (Object)null)
					{
						break;
					}
				}
				if ((Object)(object)baitDefinition.ItemPrefab == (Object)null)
				{
					prefabCandidates = baitDefinition.Keywords;
					foreach (string keyword in prefabCandidates)
					{
						baitDefinition.ItemPrefab = list.Find((ItemDrop d) => !used.Contains(d) && ((Object)d).name.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0);
						if ((Object)(object)baitDefinition.ItemPrefab != (Object)null)
						{
							break;
						}
					}
				}
				if ((Object)(object)baitDefinition.ItemPrefab == (Object)null)
				{
					continue;
				}
				used.Add(baitDefinition.ItemPrefab);
				BaitPrefabNames.Add(((Object)baitDefinition.ItemPrefab).name);
				if (instance.m_recipes == null)
				{
					continue;
				}
				foreach (Recipe recipe in instance.m_recipes)
				{
					if ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && ((Object)recipe.m_item).name == ((Object)baitDefinition.ItemPrefab).name)
					{
						if (recipe.m_amount > 0)
						{
							baitDefinition.Amount = recipe.m_amount;
						}
						break;
					}
				}
			}
		}

		private static void RefreshFoodMapIfNeeded()
		{
			EnsureBaitsResolved();
			string[] array = ReadRaws();
			bool flag = _cachedRaws.Length == array.Length;
			int num = 0;
			while (flag && num < array.Length)
			{
				flag = string.Equals(_cachedRaws[num], array[num], StringComparison.Ordinal);
				num++;
			}
			if (flag)
			{
				return;
			}
			_cachedRaws = array;
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			for (int i = 0; i < array.Length; i++)
			{
				if (!string.IsNullOrWhiteSpace(array[i]))
				{
					string text = array[i].Split(new char[1] { '#' })[0].Split(new char[1] { ',' })[0].Trim();
					if (!string.IsNullOrWhiteSpace(text) && !dictionary.ContainsKey(text))
					{
						dictionary[text] = i;
					}
				}
			}
			_foodToBait = dictionary;
		}

		private static bool TryGetBaitIndex(ItemData item, out int baitIndex)
		{
			baitIndex = -1;
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return _foodToBait.TryGetValue(((Object)item.m_dropPrefab).name, out baitIndex);
			}
			return false;
		}

		private static string GetLocalizedItemName(string prefabName)
		{
			ObjectDB instance = ObjectDB.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				GameObject itemPrefab = instance.GetItemPrefab(prefabName);
				obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name);
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				return Localization.instance.Localize(text);
			}
			return prefabName;
		}

		private static string GetAcceptedLines()
		{
			RefreshFoodMapIfNeeded();
			string key = string.Join("|", _cachedRaws) + ":" + (((Object)(object)_resolvedDb != (Object)null) ? "1" : "0");
			if (DisplayCache.TryGetValue(key, out var value))
			{
				return value;
			}
			List<string> list = new List<string>();
			for (int i = 0; i < Baits.Length; i++)
			{
				string text = null;
				foreach (KeyValuePair<string, int> item in _foodToBait)
				{
					if (item.Value == i)
					{
						text = item.Key;
						break;
					}
				}
				if (text != null)
				{
					ItemDrop itemPrefab = Baits[i].ItemPrefab;
					string text2 = (((Object)(object)itemPrefab != (Object)null && !string.IsNullOrEmpty(itemPrefab.m_itemData.m_shared.m_name)) ? Localization.instance.Localize(itemPrefab.m_itemData.m_shared.m_name) : Baits[i].ConfigLabel);
					list.Add("<color=yellow>" + text2 + "</color>: " + ConsumablePerCycle + "x " + GetLocalizedItemName(text));
				}
			}
			string text3 = ((list.Count > 0) ? string.Join("\n", list) : "-");
			DisplayCache[key] = text3;
			return text3;
		}

		private static int CountAllConsumables(Inventory inventory)
		{
			long num = 0L;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (TryGetBaitIndex(allItem, out var _))
				{
					num += allItem.m_stack;
					if (num >= int.MaxValue)
					{
						return int.MaxValue;
					}
				}
			}
			return (int)num;
		}

		private static bool TryFindProducibleBait(Inventory inventory, out int baitIndex)
		{
			baitIndex = -1;
			RefreshFoodMapIfNeeded();
			int consumablePerCycle = ConsumablePerCycle;
			Array.Clear(ScratchCounts, 0, ScratchCounts.Length);
			List<ItemData> allItems = inventory.GetAllItems();
			foreach (ItemData item in allItems)
			{
				if (TryGetBaitIndex(item, out var baitIndex2) && baitIndex2 >= 0 && baitIndex2 < ScratchCounts.Length)
				{
					ScratchCounts[baitIndex2] += item.m_stack;
				}
			}
			foreach (ItemData item2 in allItems)
			{
				if (TryGetBaitIndex(item2, out var baitIndex3) && baitIndex3 >= 0 && baitIndex3 < ScratchCounts.Length && ScratchCounts[baitIndex3] >= consumablePerCycle && (Object)(object)Baits[baitIndex3].ItemPrefab != (Object)null)
				{
					baitIndex = baitIndex3;
					return true;
				}
			}
			return false;
		}

		private static bool TryConsumeFoodForBait(Inventory inventory, int baitIndex, int amountNeeded)
		{
			int num = amountNeeded;
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				if (TryGetBaitIndex(item, out var baitIndex2) && baitIndex2 == baitIndex)
				{
					int num2 = Math.Min(item.m_stack, num);
					if (num2 > 0 && inventory.RemoveItem(item, num2))
					{
						num -= num2;
					}
					if (num <= 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryAddBait(Inventory inventory, int baitIndex, int amount)
		{
			ItemDrop itemPrefab = Baits[baitIndex].ItemPrefab;
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return false;
			}
			ItemData val = itemPrefab.m_itemData.Clone();
			val.m_dropPrefab = ((Component)itemPrefab).gameObject;
			val.m_stack = amount;
			val.m_quality = 1;
			return inventory.AddItem(val);
		}

		private static bool CanStackBait(Inventory inventory, int baitIndex)
		{
			ItemDrop itemPrefab = Baits[baitIndex].ItemPrefab;
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return false;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == ((Object)itemPrefab).name && allItem.m_stack < allItem.m_shared.m_maxStackSize)
				{
					return true;
				}
			}
			return false;
		}

		private int GetBaitCount()
		{
			Inventory val = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (val == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in val.GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && BaitPrefabNames.Contains(((Object)allItem.m_dropPrefab).name))
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_piece = ((Component)this).GetComponent<Piece>();
			_container = ((Component)this).GetComponent<Container>();
			if ((Object)(object)_container == (Object)null)
			{
				_container = ((Component)this).GetComponentInChildren<Container>(true);
			}
			if ((Object)(object)_piece != (Object)null && !string.IsNullOrEmpty(_piece.m_name))
			{
				_name = _piece.m_name;
			}
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && (Object)(object)_container != (Object)null && _container.GetInventory() != null)
			{
				InitializePersistentTimer();
				((MonoBehaviour)this).InvokeRepeating("UpdateOwnershipTick", 1f, 1f);
			}
		}

		private void Start()
		{
			_enabledBin = ProducerVisuals.FindChildRecursive(((Component)this).transform, "enabled_bin");
			_itemCrafted = ProducerVisuals.FindChildRecursive(((Component)this).transform, "item_crafted");
			_subscribedInventory = (((Object)(object)_container != (Object)null) ? _container.GetInventory() : null);
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Combine(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
			}
			UpdateEnabledBinVisual();
		}

		private void MarkVisualsDirty()
		{
			_visualsDirty = true;
		}

		private void LateUpdate()
		{
			if (_visualsDirty)
			{
				_visualsDirty = false;
				UpdateEnabledBinVisual();
			}
		}

		private void OnDestroy()
		{
			if (_subscribedInventory != null)
			{
				Inventory subscribedInventory = _subscribedInventory;
				subscribedInventory.m_onChanged = (Action)Delegate.Remove(subscribedInventory.m_onChanged, new Action(MarkVisualsDirty));
				_subscribedInventory = null;
			}
		}

		internal static void RefreshAllItemCrafted()
		{
			CompostBin[] array = Object.FindObjectsByType<CompostBin>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].UpdateItem