Decompiled source of ValheimPipes v1.2.2

ValheimPipes.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.GUI;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using MultiUserChest;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using ValheimPipes.Logic;
using ValheimPipes.Logic.Helper;
using ValheimPipes.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ValheimPipes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimPipes")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("FE8B42E3-7082-4DFF-A5CC-6B62B0315ACA")]
[assembly: AssemblyFileVersion("1.2.2")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimPipes
{
	[BepInPlugin("com.faryzal2020.valheim.ValheimPipes", "ValheimPipes", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		[PublicAPI]
		public const string ModName = "ValheimPipes";

		[PublicAPI]
		public const string ModGuid = "com.faryzal2020.valheim.ValheimPipes";

		[PublicAPI]
		public const string ModVersion = "1.2.2";

		private static ConfigEntry<bool> addSmelterSnappoints;

		private static ConfigEntry<bool> debugLogs;

		public static ConfigEntry<float> BronzeTransferRate;

		public static ConfigEntry<float> IronTransferRate;

		public static ConfigEntry<bool> ShowHopperInputBox;

		public static ConfigEntry<bool> ShowHopperOutputBox;

		public static ConfigEntry<bool> ShowPipeOutputBox;

		public static ConfigEntry<bool> ShowSnappointHighlights;

		public static ConfigEntry<string> ExtraCompatiblePrefabs;

		public static ConfigEntry<bool> DisableAllSystems;

		private Harmony harmony;

		public static Plugin Instance { get; private set; }

		public static AssetBundle AssetBundle { get; private set; }

		private void Awake()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			Instance = this;
			harmony = new Harmony("com.faryzal2020.valheim.ValheimPipes");
			harmony.PatchAll();
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			BronzeTransferRate = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Bronze Transfer Rate", 60f, new ConfigDescription("Items per minute for bronze hoppers and pipes.", (AcceptableValueBase)null, new object[1] { val }));
			IronTransferRate = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Iron Transfer Rate", 120f, new ConfigDescription("Items per minute for iron hoppers.", (AcceptableValueBase)null, new object[1] { val }));
			ExtraCompatiblePrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("Compatibility", "Extra Compatible Prefabs", "BCP_ClayCollector,RDP_beehive", new ConfigDescription("A comma-separated list of prefab names to try to make them compatible with hoppers and pipes (not always works).", (AcceptableValueBase)null, new object[1] { val }));
			addSmelterSnappoints = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Add Smelter Snappoints", true, "Adds snappoints to inputs/outputs of the smelter, charcoal kiln, blastfurnace, windmill and spinning wheel. Requires a restart to take effect.");
			debugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug Logs", false, "Enable debug logging.");
			BronzeTransferRate = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Bronze Transfer Rate", 60f, "Items per minute for bronze hoppers and pipes.");
			IronTransferRate = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Iron Transfer Rate", 120f, "Items per minute for iron hoppers.");
			ShowHopperInputBox = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Hopper Input Box", false, "Show the hopper input bounding box in-game.");
			ShowHopperOutputBox = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Hopper Output Box", false, "Show the hopper output bounding box in-game.");
			ShowPipeOutputBox = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Pipe Output Box", false, "Show the pipe output bounding box in-game.");
			ShowSnappointHighlights = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Snappoint Highlights", false, "Show a visual marker for custom snappoints added by the mod. Requires local restart of the area (teleport or logout) to take effect.");
			DisableAllSystems = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Disable All Systems", false, "Globally disable all push/pull mechanisms for debugging purposes.");
			SynchronizationManager.OnConfigurationSynchronized += delegate(object obj, ConfigurationSynchronizationEventArgs attr)
			{
				if (!attr.InitialSynchronization)
				{
					Logger.LogMessage((object)"Server synced new config values.");
				}
			};
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			localization.AddJsonFile("English", AssetUtils.LoadTextFromResources("Localization.English.json"));
			localization.AddJsonFile("German", AssetUtils.LoadTextFromResources("Localization.German.json"));
			localization.AddJsonFile("Russian", AssetUtils.LoadTextFromResources("Localization.Russian.json"));
			localization.AddJsonFile("Portuguese_Brazilian", AssetUtils.LoadTextFromResources("Localization.Portuguese_Brazilian.json"));
			AssetBundle = AssetUtils.LoadAssetBundleFromResources("valheimpipes_assetbundle");
			AddBronzePiece("HopperBronzeDown", 6, 4);
			AddBronzePiece("HopperBronzeSide", 6, 4);
			AddBronzePiece("HopperBronzeSideways", 6, 4);
			AddBronzePiece("MS_PipeBronzeSide", 4, 2);
			AddBronzePiece("MS_PipeBronzeSide_2m", 2, 1);
			AddBronzePiece("MS_PipeBronze_Vertical_Up_4m", 4, 2);
			AddBronzePiece("MS_PipeBronze_Vertical_Down_4m", 4, 2);
			AddBronzePiece("MS_PipeBronze_Vertical_Up_2m", 2, 1);
			AddBronzePiece("MS_PipeBronze_Vertical_Down_2m", 2, 1);
			AddBronzePiece("MS_PipeBronze_Diagonal_45_Up_4m", 4, 2);
			AddBronzePiece("MS_PipeBronze_Diagonal_45_Down_4m", 4, 2);
			AddBronzePiece("MS_PipeBronze_Diagonal_26_Up_4m", 4, 2);
			AddBronzePiece("MS_PipeBronze_Diagonal_26_Down_4m", 4, 2);
			AddIronPiece("HopperIronDown", 6, 2);
			AddIronPiece("HopperIronSide", 6, 2);
			AddIronPiece("HopperIronSideways", 6, 2);
			AddIronPiece("MS_PipeIronSide", 4, 2);
			AddIronPiece("MS_PipeIronSide_2m", 2, 1);
			AddIronPiece("MS_PipeIron_Vertical_Up_4m", 4, 2);
			AddIronPiece("MS_PipeIron_Vertical_Down_4m", 4, 2);
			AddIronPiece("MS_PipeIron_Vertical_Up_2m", 2, 1);
			AddIronPiece("MS_PipeIron_Vertical_Down_2m", 2, 1);
			AddIronPiece("MS_PipeIron_Diagonal_45_Up_4m", 4, 2);
			AddIronPiece("MS_PipeIron_Diagonal_45_Down_4m", 4, 2);
			AddIronPiece("MS_PipeIron_Diagonal_26_Up_4m", 4, 2);
			AddIronPiece("MS_PipeIron_Diagonal_26_Down_4m", 4, 2);
			PrefabManager.OnVanillaPrefabsAvailable += AddSnappoints;
		}

		private void Update()
		{
			HopperUI.UpdateStatic();
		}

		private static void AddSnappoints()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			if (addSmelterSnappoints.Value)
			{
				SnappointHelper.AddSnappoints("smelter", (Vector3[])(object)new Vector3[2]
				{
					new Vector3(0f, 1.6f, -1.2f),
					new Vector3(0f, 1.6f, 1.2f)
				});
				SnappointHelper.AddSnappoints("charcoal_kiln", (Vector3[])(object)new Vector3[1]
				{
					new Vector3(0f, 1.1f, 2f)
				});
				SnappointHelper.AddSnappoints("blastfurnace", (Vector3[])(object)new Vector3[4]
				{
					new Vector3(-0.5f, 1.72001f, 1.55f),
					new Vector3(-0.6f, 1.72001f, 1.55f),
					new Vector3(0.57f, 1.72f, 1.55001f),
					new Vector3(0.73f, 1.72f, 1.55001f)
				});
				SnappointHelper.AddSnappoints("windmill", (Vector3[])(object)new Vector3[2]
				{
					new Vector3(0f, 1.55f, -1.55f),
					new Vector3(-0.05f, 0.83f, 2.3f)
				});
				SnappointHelper.FixPiece("windmill");
				SnappointHelper.AddSnappoints("piece_oven", (Vector3[])(object)new Vector3[2]
				{
					new Vector3(0f, 1.1f, 2f),
					new Vector3(0f, 0.72f, 0.55f)
				});
				SnappointHelper.AddSnappoints("piece_spinningwheel", (Vector3[])(object)new Vector3[2]
				{
					new Vector3(0.72f, 1.8f, 0f),
					new Vector3(0f, 0.95f, 1.75f)
				});
			}
			PrefabManager.OnVanillaPrefabsAvailable -= AddSnappoints;
		}

		private static void AddBronzePiece(string assetName, int wood, int nails)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			PieceConfig val = new PieceConfig();
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", wood, 0, true),
				new RequirementConfig("BronzeNails", nails, 0, true)
			};
			val.PieceTable = "Hammer";
			val.CraftingStation = "piece_workbench";
			val.Category = "Crafting";
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece(AssetBundle, assetName, true, val2);
			EnsureCorrectComponent(val3);
			PieceManager.Instance.AddPiece(val3);
		}

		private static void EnsureCorrectComponent(CustomPiece customPiece)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			GameObject piecePrefab = customPiece.PiecePrefab;
			if (((Object)piecePrefab).name.Contains("Pipe"))
			{
				Hopper component = piecePrefab.GetComponent<Hopper>();
				if ((Object)(object)component != (Object)null)
				{
					FieldInfo field = typeof(Hopper).GetField("outPos", BindingFlags.Instance | BindingFlags.NonPublic);
					FieldInfo field2 = typeof(Hopper).GetField("outSize", BindingFlags.Instance | BindingFlags.NonPublic);
					Vector3 val = (Vector3)field.GetValue(component);
					Vector3 val2 = (Vector3)field2.GetValue(component);
					Object.DestroyImmediate((Object)(object)component);
					Pipe obj = piecePrefab.AddComponent<Pipe>();
					FieldInfo field3 = typeof(Pipe).GetField("outPos", BindingFlags.Instance | BindingFlags.NonPublic);
					FieldInfo field4 = typeof(Pipe).GetField("outSize", BindingFlags.Instance | BindingFlags.NonPublic);
					Vector3 val3 = val2 * 0.5f;
					if (field3 != null)
					{
						field3.SetValue(obj, val);
					}
					if (field4 != null)
					{
						field4.SetValue(obj, val3);
					}
					Logger.LogInfo((object)$"Scaled Pipe outSize on {((Object)piecePrefab).name}: outSize={val3}");
					return;
				}
				Pipe component2 = piecePrefab.GetComponent<Pipe>();
				if ((Object)(object)component2 != (Object)null)
				{
					FieldInfo field5 = typeof(Pipe).GetField("outSize", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field5 != null)
					{
						Vector3 val4 = (Vector3)field5.GetValue(component2);
						Vector3 val5 = val4 * 0.5f;
						field5.SetValue(component2, val5);
						Logger.LogInfo((object)$"Scaled Pipe outSize on {((Object)piecePrefab).name}: outSize={val5}");
					}
				}
			}
			else
			{
				if (!((Object)piecePrefab).name.Contains("Hopper"))
				{
					return;
				}
				Hopper hopper = piecePrefab.GetComponent<Hopper>();
				if ((Object)(object)hopper == (Object)null)
				{
					hopper = piecePrefab.AddComponent<Hopper>();
				}
				if ((Object)(object)piecePrefab.GetComponent<Pipe>() != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)piecePrefab.GetComponent<Pipe>());
				}
				if ((Object)(object)hopper != (Object)null)
				{
					FieldInfo field6 = typeof(Hopper).GetField("inSize", BindingFlags.Instance | BindingFlags.NonPublic);
					FieldInfo field7 = typeof(Hopper).GetField("outSize", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field6 != null && field7 != null)
					{
						Vector3 val6 = (Vector3)field6.GetValue(hopper);
						Vector3 val7 = (Vector3)field7.GetValue(hopper);
						Vector3 val8 = val6 * 0.5f;
						Vector3 val9 = val7 * 0.5f;
						field6.SetValue(hopper, val8);
						field7.SetValue(hopper, val9);
						Logger.LogInfo((object)$"Scaled Hopper boxes on {((Object)piecePrefab).name}: inSize={val8}, outSize={val9}");
					}
				}
			}
		}

		private static void AddIronPiece(string assetName, int wood, int nails)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			PieceConfig val = new PieceConfig();
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", wood, 0, true),
				new RequirementConfig("IronNails", nails, 0, true)
			};
			val.PieceTable = "Hammer";
			val.CraftingStation = "piece_workbench";
			val.Category = "Crafting";
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece(AssetBundle, assetName, true, val2);
			EnsureCorrectComponent(val3);
			PieceManager.Instance.AddPiece(val3);
		}

		public static void Debug(object data)
		{
			if (debugLogs != null && debugLogs.Value)
			{
				Logger.LogInfo(data);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ValheimPipes";

		public const string PLUGIN_NAME = "ValheimPipes";

		public const string PLUGIN_VERSION = "1.2.2";
	}
}
namespace ValheimPipes.UI
{
	public class FilterSlotClickHandler : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IDropHandler, IPointerEnterHandler, IPointerExitHandler
	{
		public int SlotIndex;

		public Action<int, InputButton> OnClick;

		public Image BackgroundImage;

		private Color defaultColor = new Color(0f, 0f, 0f, 0.45f);

		private static readonly Color HoverColor = new Color(0.25f, 0.25f, 0.25f, 0.7f);

		public void SetDefaultColor(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			defaultColor = color;
			if ((Object)(object)BackgroundImage != (Object)null)
			{
				((Graphic)BackgroundImage).color = defaultColor;
			}
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			OnClick?.Invoke(SlotIndex, eventData.button);
		}

		public void OnDrop(PointerEventData eventData)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			OnClick?.Invoke(SlotIndex, eventData.button);
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)BackgroundImage != (Object)null)
			{
				((Graphic)BackgroundImage).color = HoverColor;
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)BackgroundImage != (Object)null)
			{
				((Graphic)BackgroundImage).color = defaultColor;
			}
		}
	}
	public class HopperUI : MonoBehaviour
	{
		private class FilterSlotUI
		{
			public int Index;

			public GameObject SlotObject;

			public Image BackgroundImage;

			public Image IconImage;

			public UITooltip Tooltip;
		}

		private static readonly Color WhiteShade = new Color(73f / 85f, 73f / 85f, 73f / 85f);

		private readonly FilterSlotUI[] filterSlots = new FilterSlotUI[3];

		[SerializeField]
		private Text title;

		[SerializeField]
		private Toggle filterHopper;

		[SerializeField]
		private Toggle dropItems;

		[SerializeField]
		private Toggle pickupItems;

		[SerializeField]
		private Toggle leaveLastItem;

		[SerializeField]
		private Toggle blacklistMode;

		[SerializeField]
		private Toggle stackMode;

		[SerializeField]
		private Button copyButton;

		[SerializeField]
		private Button pasteButton;

		[SerializeField]
		private Button resetButton;

		[SerializeField]
		private Container filterContainer;

		private static GameObject uiInstance;

		private static GameObject uiRoot;

		private Hopper target;

		private Hopper copy;

		public static HopperUI Instance { get; private set; }

		public static bool IsOpen { get; private set; }

		public Container FilterContainer => filterContainer;

		private void Awake()
		{
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			Instance = this;
			if ((Object)(object)dropItems != (Object)null)
			{
				((UnityEvent<bool>)(object)dropItems.onValueChanged).AddListener((UnityAction<bool>)delegate(bool i)
				{
					if ((Object)(object)target != (Object)null)
					{
						target.DropItemsOption.Set(i);
					}
				});
			}
			if ((Object)(object)pickupItems != (Object)null)
			{
				((UnityEvent<bool>)(object)pickupItems.onValueChanged).AddListener((UnityAction<bool>)delegate(bool i)
				{
					if ((Object)(object)target != (Object)null)
					{
						target.PickupItemsOption.Set(i);
					}
				});
			}
			if ((Object)(object)leaveLastItem != (Object)null)
			{
				((UnityEvent<bool>)(object)leaveLastItem.onValueChanged).AddListener((UnityAction<bool>)delegate(bool i)
				{
					if ((Object)(object)target != (Object)null)
					{
						target.LeaveLastItemOption.Set(i);
					}
				});
			}
			if ((Object)(object)blacklistMode != (Object)null)
			{
				((UnityEvent<bool>)(object)blacklistMode.onValueChanged).AddListener((UnityAction<bool>)delegate(bool active)
				{
					if (!((Object)(object)target == (Object)null))
					{
						target.BlacklistModeOption.Set(active);
						if (active && !target.FilterItemsOption.Get())
						{
							target.FilterItemsOption.Set(value: true);
							if ((Object)(object)filterHopper != (Object)null)
							{
								filterHopper.SetIsOnWithoutNotify(true);
							}
						}
					}
				});
			}
			if ((Object)(object)stackMode != (Object)null)
			{
				((UnityEvent<bool>)(object)stackMode.onValueChanged).AddListener((UnityAction<bool>)delegate(bool i)
				{
					if ((Object)(object)target != (Object)null)
					{
						target.StackModeOption.Set(i);
					}
				});
			}
			if ((Object)(object)filterHopper != (Object)null)
			{
				((UnityEvent<bool>)(object)filterHopper.onValueChanged).AddListener((UnityAction<bool>)delegate(bool active)
				{
					if (!((Object)(object)target == (Object)null))
					{
						target.FilterItemsOption.Set(active);
						if (!active)
						{
							target.BlacklistModeOption.Set(value: false);
							if ((Object)(object)blacklistMode != (Object)null)
							{
								blacklistMode.SetIsOnWithoutNotify(false);
							}
						}
					}
				});
			}
			if ((Object)(object)copyButton != (Object)null)
			{
				((UnityEvent)copyButton.onClick).AddListener((UnityAction)delegate
				{
					if ((Object)(object)target != (Object)null)
					{
						copy = target;
					}
				});
			}
			if ((Object)(object)pasteButton != (Object)null)
			{
				((UnityEvent)pasteButton.onClick).AddListener((UnityAction)delegate
				{
					if ((Object)(object)target != (Object)null && (Object)(object)copy != (Object)null && copy.IsValid())
					{
						target.PasteData(copy);
						UpdateText();
					}
				});
			}
			if (!((Object)(object)resetButton != (Object)null))
			{
				return;
			}
			((UnityEvent)resetButton.onClick).AddListener((UnityAction)delegate
			{
				if ((Object)(object)target != (Object)null)
				{
					target.ResetValues();
					UpdateText();
				}
			});
		}

		public static void Init()
		{
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				return;
			}
			object obj;
			if (!((Object)(object)InventoryGui.instance != (Object)null))
			{
				GameObject customGUIFront = GUIManager.CustomGUIFront;
				obj = ((customGUIFront != null) ? customGUIFront.transform : null);
			}
			else
			{
				obj = ((Component)InventoryGui.instance).transform;
			}
			Transform val = (Transform)obj;
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"HopperUI: Cannot init because parent canvas is null. Waiting...");
				return;
			}
			GameObject val2 = Plugin.AssetBundle.LoadAsset<GameObject>("HopperUI");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogError((object)"HopperUI: Failed to load prefab from AssetBundle!");
				return;
			}
			ZNetView[] componentsInChildren = val2.GetComponentsInChildren<ZNetView>(true);
			foreach (ZNetView val3 in componentsInChildren)
			{
				Object.DestroyImmediate((Object)(object)val3, true);
			}
			Container[] componentsInChildren2 = val2.GetComponentsInChildren<Container>(true);
			foreach (Container val4 in componentsInChildren2)
			{
				Object.DestroyImmediate((Object)(object)val4, true);
			}
			uiInstance = Object.Instantiate<GameObject>(val2, val, false);
			uiRoot = ((uiInstance.transform.childCount > 0) ? ((Component)uiInstance.transform.GetChild(0)).gameObject : uiInstance);
			HopperUI component = uiInstance.GetComponent<HopperUI>();
			if ((Object)(object)component == (Object)null)
			{
				Logger.LogWarning((object)"HopperUI component missing on prefab!");
				return;
			}
			ApplyAllComponents(uiRoot);
			if ((Object)(object)component.title != (Object)null)
			{
				GUIManager.Instance.ApplyTextStyle(component.title, GUIManager.Instance.AveriaSerifBold, GUIManager.Instance.ValheimOrange, 20, true);
			}
			ApplyLocalization();
			if ((Object)(object)uiRoot.GetComponent<DragWindowCntrl>() == (Object)null)
			{
				uiRoot.AddComponent<DragWindowCntrl>();
			}
			component.SetupFilterSlots();
			PrefabExtension.FixReferences(uiRoot, true);
			IsOpen = false;
			uiRoot.SetActive(false);
			uiInstance.SetActive(false);
			Logger.LogInfo((object)"HopperUI: Successfully initialized custom UI instance.");
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
				uiInstance = null;
				uiRoot = null;
				IsOpen = false;
			}
		}

		public static void UpdateStatic()
		{
			InventoryGui instance = InventoryGui.instance;
			Hopper hopper = default(Hopper);
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)instance) || !instance.IsContainerOpen() || !Object.op_Implicit((Object)(object)instance.m_currentContainer))
			{
				if ((Object)(object)Instance != (Object)null && IsOpen)
				{
					Instance.target = null;
					SetGUIState(active: false);
				}
			}
			else if (((Component)instance.m_currentContainer).TryGetComponent<Hopper>(ref hopper))
			{
				if ((Object)(object)Instance == (Object)null)
				{
					Init();
				}
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.UpdateInstance(hopper);
				}
			}
			else if ((Object)(object)Instance != (Object)null && IsOpen)
			{
				Instance.target = null;
				SetGUIState(active: false);
			}
		}

		public static bool IsFilterInventory(Inventory inventory)
		{
			if ((Object)(object)Instance == (Object)null || (Object)(object)Instance.filterContainer == (Object)null)
			{
				return false;
			}
			return Instance.filterContainer.GetInventory() == inventory;
		}

		private void UpdateInstance(Hopper hopper)
		{
			target = hopper;
			target.LoadFilterInventory();
			SetGUIState(active: true);
			UpdateText();
		}

		private void LateUpdate()
		{
		}

		private static void SetGUIState(bool active)
		{
			if (IsOpen == active)
			{
				return;
			}
			IsOpen = active;
			if ((Object)(object)uiInstance != (Object)null)
			{
				uiInstance.SetActive(active);
				if (active)
				{
					uiInstance.transform.SetAsLastSibling();
				}
			}
			if ((Object)(object)uiRoot != (Object)null)
			{
				uiRoot.SetActive(active);
			}
		}

		private void UpdateText()
		{
			if (!((Object)(object)target == (Object)null))
			{
				if ((Object)(object)title != (Object)null)
				{
					title.text = Localization.instance.Localize(target.Piece.m_name);
				}
				if ((Object)(object)filterHopper != (Object)null)
				{
					filterHopper.SetIsOnWithoutNotify(target.FilterItemsOption.Get());
				}
				if ((Object)(object)dropItems != (Object)null)
				{
					dropItems.SetIsOnWithoutNotify(target.DropItemsOption.Get());
				}
				if ((Object)(object)pickupItems != (Object)null)
				{
					pickupItems.SetIsOnWithoutNotify(target.PickupItemsOption.Get());
				}
				if ((Object)(object)leaveLastItem != (Object)null)
				{
					leaveLastItem.SetIsOnWithoutNotify(target.LeaveLastItemOption.Get());
				}
				if ((Object)(object)blacklistMode != (Object)null)
				{
					blacklistMode.SetIsOnWithoutNotify(target.BlacklistModeOption.Get());
				}
				if ((Object)(object)stackMode != (Object)null)
				{
					stackMode.SetIsOnWithoutNotify(target.StackModeOption.Get());
				}
				if ((Object)(object)stackMode != (Object)null)
				{
					bool active = ((Object)target).name.Contains("Iron");
					((Component)stackMode).gameObject.SetActive(active);
				}
				UpdateFilterSlots();
			}
		}

		private static Sprite FindSlotBackgroundSprite()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if ((Object)(object)instance.m_containerGrid != (Object)null)
			{
				if ((Object)(object)instance.m_containerGrid.m_elementPrefab != (Object)null)
				{
					Image val = instance.m_containerGrid.m_elementPrefab.GetComponent<Image>() ?? instance.m_containerGrid.m_elementPrefab.GetComponentInChildren<Image>();
					if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null)
					{
						return val.sprite;
					}
				}
				if (instance.m_containerGrid.m_elements != null && instance.m_containerGrid.m_elements.Count > 0)
				{
					InventoryElement val2 = instance.m_containerGrid.m_elements[0];
					Image component = ((Component)val2).GetComponent<Image>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null)
					{
						return component.sprite;
					}
				}
			}
			if ((Object)(object)instance.m_playerGrid != (Object)null)
			{
				if ((Object)(object)instance.m_playerGrid.m_elementPrefab != (Object)null)
				{
					Image val3 = instance.m_playerGrid.m_elementPrefab.GetComponent<Image>() ?? instance.m_playerGrid.m_elementPrefab.GetComponentInChildren<Image>();
					if ((Object)(object)val3 != (Object)null && (Object)(object)val3.sprite != (Object)null)
					{
						return val3.sprite;
					}
				}
				if (instance.m_playerGrid.m_elements != null && instance.m_playerGrid.m_elements.Count > 0)
				{
					InventoryElement val4 = instance.m_playerGrid.m_elements[0];
					Image component2 = ((Component)val4).GetComponent<Image>();
					if ((Object)(object)component2 != (Object)null && (Object)(object)component2.sprite != (Object)null)
					{
						return component2.sprite;
					}
				}
			}
			return null;
		}

		private static GameObject FindTooltipPrefab()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			UITooltip val = ((IEnumerable<UITooltip>)((Component)instance).GetComponentsInChildren<UITooltip>(true)).FirstOrDefault((Func<UITooltip, bool>)((UITooltip t) => (Object)(object)t.m_tooltipPrefab != (Object)null));
			return ((Object)(object)val != (Object)null) ? val.m_tooltipPrefab : null;
		}

		private void SetupFilterSlots()
		{
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)uiRoot == (Object)null)
			{
				return;
			}
			Sprite val = FindSlotBackgroundSprite();
			GameObject val2 = FindTooltipPrefab();
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0f, 0f, 0f, 0.45f);
			for (int i = 0; i < 3; i++)
			{
				string slotName = $"Slot_{i}";
				Transform val4 = ((IEnumerable<Transform>)uiRoot.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == slotName));
				if ((Object)(object)val4 == (Object)null)
				{
					Logger.LogWarning((object)("HopperUI: Could not find " + slotName + " in prefab!"));
					continue;
				}
				GameObject gameObject = ((Component)val4).gameObject;
				Button component = gameObject.GetComponent<Button>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
				Image val5 = gameObject.GetComponent<Image>();
				if ((Object)(object)val5 == (Object)null)
				{
					val5 = gameObject.AddComponent<Image>();
				}
				if ((Object)(object)val != (Object)null)
				{
					val5.sprite = val;
					val5.type = (Type)1;
				}
				else
				{
					val5.sprite = null;
				}
				((Graphic)val5).color = val3;
				Transform val6 = gameObject.transform.Find("_icon");
				if ((Object)(object)val6 == (Object)null)
				{
					GameObject val7 = new GameObject("_icon", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					val7.transform.SetParent(gameObject.transform, false);
					val6 = val7.transform;
				}
				Image val8 = ((Component)val6).GetComponent<Image>();
				if ((Object)(object)val8 == (Object)null)
				{
					val8 = ((Component)val6).gameObject.AddComponent<Image>();
				}
				RectTransform rectTransform = ((Graphic)val8).rectTransform;
				rectTransform.anchorMin = new Vector2(0.1f, 0.1f);
				rectTransform.anchorMax = new Vector2(0.9f, 0.9f);
				rectTransform.offsetMin = Vector2.zero;
				rectTransform.offsetMax = Vector2.zero;
				val8.preserveAspect = true;
				((Graphic)val8).raycastTarget = false;
				((Graphic)val8).color = Color.white;
				((Behaviour)val8).enabled = false;
				UITooltip val9 = gameObject.GetComponent<UITooltip>();
				if ((Object)(object)val9 == (Object)null)
				{
					val9 = gameObject.AddComponent<UITooltip>();
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val9.m_tooltipPrefab = val2;
				}
				((Behaviour)val9).enabled = false;
				int num = i;
				FilterSlotClickHandler filterSlotClickHandler = gameObject.GetComponent<FilterSlotClickHandler>();
				if ((Object)(object)filterSlotClickHandler == (Object)null)
				{
					filterSlotClickHandler = gameObject.AddComponent<FilterSlotClickHandler>();
				}
				filterSlotClickHandler.SlotIndex = num;
				filterSlotClickHandler.OnClick = OnSlotClicked;
				filterSlotClickHandler.BackgroundImage = val5;
				filterSlotClickHandler.SetDefaultColor(val3);
				filterSlots[i] = new FilterSlotUI
				{
					Index = num,
					SlotObject = gameObject,
					BackgroundImage = val5,
					IconImage = val8,
					Tooltip = val9
				};
			}
		}

		private void OnSlotClicked(int slotIndex, InputButton button)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			if ((int)button == 1)
			{
				UITooltip.HideTooltip();
				target.ClearFilterItem(slotIndex);
				UpdateFilterSlots();
			}
			else if ((int)button == 0)
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance != (Object)null && instance.m_dragItem != null)
				{
					target.SetFilterItem(slotIndex, instance.m_dragItem);
				}
				else
				{
					UITooltip.HideTooltip();
					target.ClearFilterItem(slotIndex);
				}
				UpdateFilterSlots();
			}
		}

		private void UpdateFilterSlots()
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			Sprite val = FindSlotBackgroundSprite();
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0.45f);
			for (int i = 0; i < filterSlots.Length; i++)
			{
				FilterSlotUI filterSlotUI = filterSlots[i];
				if (filterSlotUI == null)
				{
					continue;
				}
				if ((Object)(object)filterSlotUI.BackgroundImage != (Object)null)
				{
					GameObject slotObject = filterSlotUI.SlotObject;
					FilterSlotClickHandler filterSlotClickHandler = ((slotObject != null) ? slotObject.GetComponent<FilterSlotClickHandler>() : null);
					if ((Object)(object)filterSlotUI.BackgroundImage.sprite == (Object)null && (Object)(object)val != (Object)null)
					{
						filterSlotUI.BackgroundImage.sprite = val;
						filterSlotUI.BackgroundImage.type = (Type)1;
					}
					((Graphic)filterSlotUI.BackgroundImage).color = val2;
					filterSlotClickHandler?.SetDefaultColor(val2);
				}
				ItemData filterItem = target.GetFilterItem(i);
				if (filterItem != null)
				{
					filterSlotUI.IconImage.sprite = filterItem.GetIcon();
					((Graphic)filterSlotUI.IconImage).color = Color.white;
					((Behaviour)filterSlotUI.IconImage).enabled = true;
					if ((Object)(object)filterSlotUI.Tooltip != (Object)null)
					{
						if ((Object)(object)filterSlotUI.Tooltip.m_tooltipPrefab == (Object)null)
						{
							filterSlotUI.Tooltip.m_tooltipPrefab = FindTooltipPrefab();
						}
						filterSlotUI.Tooltip.m_topic = "";
						filterSlotUI.Tooltip.m_text = ((filterItem.m_shared != null) ? Localization.instance.Localize(filterItem.m_shared.m_name) : "");
						((Behaviour)filterSlotUI.Tooltip).enabled = (Object)(object)filterSlotUI.Tooltip.m_tooltipPrefab != (Object)null;
					}
				}
				else
				{
					filterSlotUI.IconImage.sprite = null;
					((Behaviour)filterSlotUI.IconImage).enabled = false;
					if ((Object)(object)filterSlotUI.Tooltip != (Object)null)
					{
						UITooltip.HideTooltip();
						filterSlotUI.Tooltip.m_topic = "";
						filterSlotUI.Tooltip.m_text = "";
						((Behaviour)filterSlotUI.Tooltip).enabled = false;
					}
				}
			}
		}

		private static void ApplyAllComponents(GameObject root)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Text[] componentsInChildren = root.GetComponentsInChildren<Text>();
			foreach (Text val in componentsInChildren)
			{
				GUIManager.Instance.ApplyTextStyle(val, GUIManager.Instance.AveriaSerif, WhiteShade, 16, false);
			}
			InputField[] componentsInChildren2 = root.GetComponentsInChildren<InputField>();
			foreach (InputField val2 in componentsInChildren2)
			{
				GUIManager.Instance.ApplyInputFieldStyle(val2, 16);
			}
			Toggle[] componentsInChildren3 = root.GetComponentsInChildren<Toggle>();
			foreach (Toggle val3 in componentsInChildren3)
			{
				GUIManager.Instance.ApplyToogleStyle(val3);
			}
			Button[] componentsInChildren4 = root.GetComponentsInChildren<Button>();
			foreach (Button val4 in componentsInChildren4)
			{
				GUIManager.Instance.ApplyButtonStyle(val4, 16);
			}
		}

		private static void ApplyLocalization()
		{
			Text[] componentsInChildren = uiRoot.GetComponentsInChildren<Text>();
			foreach (Text val in componentsInChildren)
			{
				val.text = Localization.instance.Localize(val.text);
			}
		}
	}
}
namespace ValheimPipes.Patches
{
	[HarmonyPatch]
	public class ExtensionPatch
	{
		[HarmonyPatch(typeof(Container), "Awake")]
		[HarmonyPostfix]
		private static void ContainerAwakePostfix(Container __instance)
		{
			if ((Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) || Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ZNetView>())) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ContainerTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<ContainerTarget>();
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "Awake")]
		[HarmonyPostfix]
		private static void ItemDropAwakePostfix(ItemDrop __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ItemDropTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<ItemDropTarget>();
			}
		}

		[HarmonyPatch(typeof(Smelter), "Awake")]
		[HarmonyPostfix]
		private static void SmelterAwakePostfix(Smelter __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.m_addWoodSwitch) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<SmelterFuelTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<SmelterFuelTarget>();
			}
			if (Object.op_Implicit((Object)(object)__instance.m_addOreSwitch) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<SmelterOreTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<SmelterOreTarget>();
			}
			if (((Object)__instance).name.StartsWith("windmill") && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<WindmillTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<WindmillTarget>();
			}
		}

		[HarmonyPatch(typeof(Beehive), "Awake")]
		[HarmonyPostfix]
		private static void BeehiveAwakePostfix(Beehive __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<BeehiveTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<BeehiveTarget>();
			}
		}

		[HarmonyPatch(typeof(Turret), "Awake")]
		[HarmonyPostfix]
		private static void TurretAwakePostfix(Turret __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<TurretTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<TurretTarget>();
			}
		}

		[HarmonyPatch(typeof(CookingStation), "Awake")]
		[HarmonyPostfix]
		private static void CookingStationAwakePostfix(CookingStation __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CookingStationTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<CookingStationTarget>();
			}
		}

		[HarmonyPatch(typeof(Fireplace), "Awake")]
		[HarmonyPostfix]
		private static void FireplaceAwakePostfix(Fireplace __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<FireplaceFuelTarget>()))
			{
				((Component)__instance).gameObject.AddComponent<FireplaceFuelTarget>();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		[HarmonyPostfix]
		private static void ZNetSceneAwakePostfix(ZNetScene __instance)
		{
			if (Plugin.ExtraCompatiblePrefabs == null || string.IsNullOrEmpty(Plugin.ExtraCompatiblePrefabs.Value))
			{
				return;
			}
			string[] array = (from x in Plugin.ExtraCompatiblePrefabs.Value.Split(new char[1] { ',' })
				select x.Trim()).ToArray();
			string[] array2 = array;
			foreach (string text in array2)
			{
				GameObject prefab = __instance.GetPrefab(text);
				if (Object.op_Implicit((Object)(object)prefab))
				{
					bool flag = false;
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Container>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<ContainerTarget>()))
					{
						prefab.AddComponent<ContainerTarget>();
						Plugin.Debug("Added ContainerTarget to " + text);
						flag = true;
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Beehive>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<BeehiveTarget>()))
					{
						prefab.AddComponent<BeehiveTarget>();
						Plugin.Debug("Added BeehiveTarget to " + text);
						flag = true;
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Smelter>()))
					{
						Smelter component = prefab.GetComponent<Smelter>();
						if (Object.op_Implicit((Object)(object)component.m_addWoodSwitch) && !Object.op_Implicit((Object)(object)prefab.GetComponent<SmelterFuelTarget>()))
						{
							prefab.AddComponent<SmelterFuelTarget>();
							Plugin.Debug("Added SmelterFuelTarget to " + text);
							flag = true;
						}
						if (Object.op_Implicit((Object)(object)component.m_addOreSwitch) && !Object.op_Implicit((Object)(object)prefab.GetComponent<SmelterOreTarget>()))
						{
							prefab.AddComponent<SmelterOreTarget>();
							Plugin.Debug("Added SmelterOreTarget to " + text);
							flag = true;
						}
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Fermenter>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<FermenterTarget>()))
					{
						prefab.AddComponent<FermenterTarget>();
						Plugin.Debug("Added FermenterTarget to " + text);
						flag = true;
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Fireplace>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<FireplaceFuelTarget>()))
					{
						prefab.AddComponent<FireplaceFuelTarget>();
						Plugin.Debug("Added FireplaceFuelTarget to " + text);
						flag = true;
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<CookingStation>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<CookingStationTarget>()))
					{
						prefab.AddComponent<CookingStationTarget>();
						Plugin.Debug("Added CookingStationTarget to " + text);
						flag = true;
					}
					if (Object.op_Implicit((Object)(object)prefab.GetComponent<Turret>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<TurretTarget>()))
					{
						prefab.AddComponent<TurretTarget>();
						Plugin.Debug("Added TurretTarget to " + text);
						flag = true;
					}
					if (!flag && (Object)(object)prefab.GetComponent("ClayCollector") != (Object)null && !Object.op_Implicit((Object)(object)prefab.GetComponent<ClayCollectorTarget>()))
					{
						prefab.AddComponent<ClayCollectorTarget>();
						Plugin.Debug("Added ClayCollectorTarget to " + text);
						flag = true;
					}
					if (!flag)
					{
						string text2 = string.Join(", ", from c in prefab.GetComponents<Component>()
							select ((object)c).GetType().Name);
						Plugin.Debug("Compatibility info: Prefab '" + text + "' found but no standard production component detected. Components found: " + text2);
					}
				}
				else
				{
					Plugin.Debug("Compatibility warning: Prefab '" + text + "' not found in ZNetScene.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	public static class InventoryPatch
	{
		[HarmonyPrefix]
		public static bool AddItem_Prefix(Inventory __instance, ItemData item, int amount, int x, int y, bool skipValidPositionCheck)
		{
			if ((Object)(object)HopperUI.Instance != (Object)null && CheckIsFilterInventory(__instance))
			{
				Logger.LogInfo((object)"[HopperUI] Intercepted Item Placement:");
				Logger.LogInfo((object)(" - Name: " + item.m_shared.m_name));
				Logger.LogInfo((object)(" - Prefab: " + ((Object)item.m_dropPrefab).name));
				Logger.LogInfo((object)$" - Slot: ({x}, {y})");
				Logger.LogInfo((object)$" - Amount: {amount}");
				return false;
			}
			return true;
		}

		private static bool CheckIsFilterInventory(Inventory inventory)
		{
			return HopperUI.IsFilterInventory(inventory);
		}
	}
	[HarmonyPatch(typeof(Container), "Save")]
	public static class PatchContainerSave
	{
		private static bool Prefix(Container __instance)
		{
			if ((Object)(object)HopperUI.Instance != (Object)null && (Object)(object)__instance == (Object)(object)HopperUI.Instance.FilterContainer)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Container), "Load")]
	public static class PatchContainerLoad
	{
		private static bool Prefix(Container __instance)
		{
			if ((Object)(object)HopperUI.Instance != (Object)null && (Object)(object)__instance == (Object)(object)HopperUI.Instance.FilterContainer)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	public static class PatchContainerAwake
	{
		private static bool Prefix(Container __instance)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ZNetView>()))
			{
				if (__instance.m_inventory == null)
				{
					__instance.m_inventory = new Inventory(__instance.m_name, __instance.m_bkg, __instance.m_width, __instance.m_height);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class PlacementPatch
	{
		[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
		[HarmonyPostfix]
		public static void SetupPlacementGhostPatch(Player __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.m_placementGhost))
			{
				Hopper[] componentsInChildren = __instance.m_placementGhost.GetComponentsInChildren<Hopper>();
				foreach (Hopper hopper in componentsInChildren)
				{
					Object.Destroy((Object)(object)hopper);
				}
				Pipe[] componentsInChildren2 = __instance.m_placementGhost.GetComponentsInChildren<Pipe>();
				foreach (Pipe pipe in componentsInChildren2)
				{
					Object.Destroy((Object)(object)pipe);
				}
			}
		}
	}
}
namespace ValheimPipes.Logic
{
	[DefaultExecutionOrder(5)]
	public class Hopper : NetworkPiece, IPushTarget, ITarget, IEqualityComparer<ITarget>, IPullTarget
	{
		private Container container;

		private ContainerTarget containerTarget;

		[SerializeField]
		private Vector3 inPos = new Vector3(0f, 0.375f, 0f);

		[SerializeField]
		private Vector3 outPos = new Vector3(0f, -0.375f, 0f);

		[SerializeField]
		private Vector3 inSize = new Vector3(0.5f, 0.25f, 0.5f);

		[SerializeField]
		private Vector3 outSize = new Vector3(0.5f, 0.5f, 0.5f);

		private List<IPushTarget> pushTo = new List<IPushTarget>();

		internal List<IPullTarget> pullFrom = new List<IPullTarget>();

		private BoxVisualizer inVisualizer;

		private BoxVisualizer outVisualizer;

		private int lastPullFrame = -1;

		private const float ObjectSearchInterval = 3f;

		private int transferFrame;

		private int objectSearchFrame;

		private int frameOffset;

		private int pullCounter;

		internal Inventory filterInventory;

		public Piece Piece { get; private set; }

		public HopperPriority PushPriority { get; } = HopperPriority.HopperPull;

		public HopperPriority PullPriority { get; } = HopperPriority.HopperPull;

		public bool IsPickup { get; } = false;

		public Vector3 InPos => inPos;

		public Vector3 InSize => inSize;

		public ZBool FilterItemsOption { get; private set; }

		public ZBool BlacklistModeOption { get; private set; }

		public ZBool StackModeOption { get; private set; }

		public ZBool DropItemsOption { get; private set; }

		public ZBool PickupItemsOption { get; private set; }

		public ZBool LeaveLastItemOption { get; private set; }

		private string DbgId
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				Vector3 position = ((Component)this).transform.position;
				return "Hopper@" + ((Vector3)(ref position)).ToString("F1");
			}
		}

		protected override void Awake()
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			base.Awake();
			Piece = ((Component)this).GetComponent<Piece>();
			container = ((Component)this).GetComponent<Container>();
			containerTarget = ((Component)this).GetComponent<ContainerTarget>();
			FilterItemsOption = new ZBool("hopper_filter_items", defaultValue: false, zNetView);
			BlacklistModeOption = new ZBool("hopper_blacklist_mode", defaultValue: false, zNetView);
			StackModeOption = new ZBool("hopper_stack_mode", defaultValue: false, zNetView);
			DropItemsOption = new ZBool("hopper_drop_items", defaultValue: false, zNetView);
			PickupItemsOption = new ZBool("hopper_pickup_items", defaultValue: true, zNetView);
			LeaveLastItemOption = new ZBool("hopper_leave_last_item", defaultValue: false, zNetView);
			UpdateTransferRate();
			objectSearchFrame = Mathf.RoundToInt(1f / Time.fixedDeltaTime * 3f);
			frameOffset = Mathf.Abs(((Object)this).GetInstanceID() % transferFrame);
			inVisualizer = ((Component)this).gameObject.AddComponent<BoxVisualizer>();
			inVisualizer.SetData(inPos, inSize, Color.blue, Plugin.ShowHopperInputBox);
			outVisualizer = ((Component)this).gameObject.AddComponent<BoxVisualizer>();
			outVisualizer.SetData(outPos, outSize, Color.yellow, Plugin.ShowHopperOutputBox);
			filterInventory = new Inventory("HopperFilter", (Sprite)null, 3, 1);
			Inventory obj = filterInventory;
			obj.m_onChanged = (Action)Delegate.Combine(obj.m_onChanged, new Action(SaveFilterInventory));
			LoadFilterInventory();
		}

		private void UpdateTransferRate()
		{
			float num = (((Object)this).name.Contains("Iron") ? Plugin.IronTransferRate.Value : Plugin.BronzeTransferRate.Value);
			float num2 = 30f / Mathf.Max(1f, num);
			transferFrame = Mathf.RoundToInt(num2 / Time.fixedDeltaTime);
			if (transferFrame < 1)
			{
				transferFrame = 1;
			}
		}

		private void Start()
		{
			Inventory inventory = container.GetInventory();
			inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(base.WakeUp));
			HopperHelper.OnTargetChanged += OnTargetChanged;
		}

		public void LoadFilterInventory()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if (!zNetView.IsValid())
			{
				return;
			}
			byte[] byteArray = zNetView.GetZDO().GetByteArray("hopper_filter_inv", (byte[])null);
			if (byteArray != null && byteArray.Length != 0)
			{
				ZPackage val = new ZPackage(byteArray);
				filterInventory.Load(val);
				return;
			}
			string text = zNetView.GetZDO().GetString("hopper_filter_inv", "");
			if (!string.IsNullOrEmpty(text))
			{
				ZPackage val2 = new ZPackage(text);
				filterInventory.Load(val2);
			}
		}

		private void SaveFilterInventory()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if (zNetView.IsValid())
			{
				if (!zNetView.IsOwner())
				{
					zNetView.ClaimOwnership();
				}
				ZPackage val = new ZPackage();
				filterInventory.Save(val);
				zNetView.GetZDO().Set("hopper_filter_inv", val.GetArray());
			}
		}

		public ItemData GetFilterItem(int slotIndex)
		{
			if (filterInventory == null)
			{
				return null;
			}
			return filterInventory.GetItemAt(slotIndex, 0);
		}

		public void SetFilterItem(int slotIndex, ItemData item)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (filterInventory != null && item != null)
			{
				if ((Object)(object)zNetView != (Object)null && !zNetView.IsOwner())
				{
					zNetView.ClaimOwnership();
				}
				ItemData itemAt = filterInventory.GetItemAt(slotIndex, 0);
				if (itemAt != null)
				{
					filterInventory.RemoveItem(itemAt);
				}
				ItemData val = item.Clone();
				val.m_stack = 1;
				val.m_gridPos = new Vector2i(slotIndex, 0);
				filterInventory.m_inventory.Add(val);
				filterInventory.Changed(false, false);
			}
		}

		public void ClearFilterItem(int slotIndex)
		{
			if (filterInventory != null)
			{
				if ((Object)(object)zNetView != (Object)null && !zNetView.IsOwner())
				{
					zNetView.ClaimOwnership();
				}
				ItemData itemAt = filterInventory.GetItemAt(slotIndex, 0);
				if (itemAt != null)
				{
					filterInventory.RemoveItem(itemAt);
					filterInventory.Changed(false, false);
				}
			}
		}

		private void OnDestroy()
		{
			HopperHelper.OnTargetChanged -= OnTargetChanged;
		}

		private void OnInventoryChanged()
		{
			WakeUp();
		}

		private void OnTargetChanged(ITarget target)
		{
			if (base.IsPushBlocked && pushTo.Any((IPushTarget t) => t.NetworkHashCode() == target.NetworkHashCode()))
			{
				base.IsPushBlocked = false;
			}
			if (base.IsPullBlocked && pullFrom.Any((IPullTarget t) => t.NetworkHashCode() == target.NetworkHashCode()))
			{
				base.IsPullBlocked = false;
			}
		}

		public void PasteData(Hopper copy)
		{
			FilterItemsOption.Set(copy.FilterItemsOption.Get());
			BlacklistModeOption.Set(copy.BlacklistModeOption.Get());
			StackModeOption.Set(copy.StackModeOption.Get());
			DropItemsOption.Set(copy.DropItemsOption.Get());
			PickupItemsOption.Set(copy.PickupItemsOption.Get());
			LeaveLastItemOption.Set(copy.LeaveLastItemOption.Get());
			if ((Object)(object)zNetView != (Object)null && !zNetView.IsOwner())
			{
				zNetView.ClaimOwnership();
			}
			filterInventory.m_inventory.Clear();
			foreach (ItemData item2 in copy.filterInventory.m_inventory)
			{
				ItemData item = item2.Clone();
				filterInventory.m_inventory.Add(item);
			}
			filterInventory.Changed(false, false);
		}

		public void ResetValues()
		{
			if ((Object)(object)zNetView != (Object)null && !zNetView.IsOwner())
			{
				zNetView.ClaimOwnership();
			}
			FilterItemsOption.Reset();
			BlacklistModeOption.Reset();
			StackModeOption.Reset();
			DropItemsOption.Reset();
			PickupItemsOption.Reset();
			LeaveLastItemOption.Reset();
			filterInventory.m_inventory.Clear();
			filterInventory.Changed(false, false);
		}

		private void FixedUpdate()
		{
			if (!IsValid() || !zNetView.IsOwner() || Plugin.DisableAllSystems.Value)
			{
				return;
			}
			int fixedFrameCount = HopperHelper.GetFixedFrameCount();
			int num = (fixedFrameCount + frameOffset) / transferFrame;
			if ((fixedFrameCount + frameOffset) % transferFrame == 0)
			{
				if (num % 2 == 0 && !base.IsPullBlocked)
				{
					PullItems();
				}
				if (num % 2 == 1 && !base.IsPushBlocked)
				{
					PushItems();
				}
			}
			if ((fixedFrameCount + frameOffset + 1) % objectSearchFrame == 0)
			{
				FindIO();
			}
		}

		private void PullItems()
		{
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			if (pullFrom.Count == 0)
			{
				base.IsPullBlocked = true;
				return;
			}
			int num = pullCounter % pullFrom.Count;
			for (int i = 0; i < pullFrom.Count; i++)
			{
				int num2 = (num + i) % pullFrom.Count;
				IPullTarget pullTarget = pullFrom[num2];
				if (!pullTarget.IsValid() || (!PickupItemsOption.Get() && pullTarget.IsPickup))
				{
					continue;
				}
				foreach (ItemData item in pullTarget.GetItems())
				{
					if (!FindFreeSlot(item, out var pos))
					{
						continue;
					}
					int num3 = 1;
					if (StackModeOption.Get() && ((Object)this).name.Contains("Iron"))
					{
						int maxStackSize = item.m_shared.m_maxStackSize;
						int stack = item.m_stack;
						int roomForItem = container.GetInventory().GetRoomForItem(item);
						num3 = Mathf.Min(new int[3] { maxStackSize, stack, roomForItem });
					}
					pullCounter = num2 + 1;
					object[] obj = new object[6]
					{
						DbgId,
						num3,
						item.m_shared.m_name,
						pullTarget.GetType().Name,
						null,
						null
					};
					IPullTarget obj2 = ((pullTarget is MonoBehaviour) ? pullTarget : null);
					obj[4] = ((obj2 != null) ? ((Object)((Component)obj2).gameObject).name : null);
					obj[5] = num2;
					Plugin.Debug(string.Format("[{0}] Pulling {1}x '{2}' <- {3} ({4}) (sourceIdx={5})", obj));
					pullTarget.RemoveItem(item, container, pos, zNetView.GetZDO().m_uid, num3);
					HopperHelper.NotifyChange(this);
					HopperHelper.NotifyChange(pullTarget);
					return;
				}
			}
			base.IsPullBlocked = true;
		}

		private void PushItems()
		{
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			if (pushTo.Count == 0)
			{
				if (DropItemsOption.Get())
				{
					DropItem();
				}
				else
				{
					base.IsPushBlocked = true;
				}
				return;
			}
			int num = OutputCounter % pushTo.Count;
			for (int i = 0; i < pushTo.Count; i++)
			{
				int num2 = (num + i) % pushTo.Count;
				IPushTarget to = pushTo[num2];
				if (!to.IsValid())
				{
					continue;
				}
				ItemData val = container.GetInventory().FindLastItem((ItemData item) => to.CanAddItem(item) && CanPushItem(item) && IsAllowedPushing(item));
				if (val == null)
				{
					continue;
				}
				int num3 = 1;
				if (StackModeOption.Get() && ((Object)this).name.Contains("Iron"))
				{
					int maxStackSize = val.m_shared.m_maxStackSize;
					int num4 = container.GetInventory().CountItems(val.m_shared.m_name, -1, true);
					if (LeaveLastItemOption.Get())
					{
						num4--;
					}
					num3 = Mathf.Min(maxStackSize, num4);
				}
				OutputCounter = num2 + 1;
				object[] obj = new object[6]
				{
					DbgId,
					num3,
					val.m_shared.m_name,
					to.GetType().Name,
					null,
					null
				};
				IPushTarget pushTarget = to;
				IPushTarget obj2 = ((pushTarget is MonoBehaviour) ? pushTarget : null);
				obj[4] = ((obj2 != null) ? ((Object)((Component)obj2).gameObject).name : null);
				obj[5] = num2;
				Plugin.Debug(string.Format("[{0}] Pushing {1}x '{2}' -> {3} ({4}) (targetIdx={5})", obj));
				to.AddItem(val, container, zNetView.GetZDO().m_uid, num3);
				HopperHelper.NotifyChange(this);
				HopperHelper.NotifyChange(to);
				return;
			}
			Plugin.Debug("[" + DbgId + "] No targets could accept pushable item (full, filtered, or leave-last)");
			base.IsPushBlocked = true;
		}

		private void DropItem()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = container.GetInventory().FindLastItem((ItemData i) => CanPushItem(i) && IsAllowedPushing(i));
			if (val != null)
			{
				container.GetInventory().RemoveOneItem(val);
				float num = Random.Range(0f, (float)Math.PI * 2f);
				Vector3 val2 = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 0.2f;
				Vector3 visualItemOffset = ItemHelper.GetVisualItemOffset(((Object)val.m_dropPrefab).name);
				Vector3 val3 = ((Component)this).transform.TransformPoint(outPos) + visualItemOffset + new Vector3(val2.x, 0f, val2.z);
				ItemDrop.DropItem(val, 1, val3, val.m_dropPrefab.transform.rotation);
			}
		}

		public bool CanAddItem(ItemData item)
		{
			Vector2i pos;
			return FindFreeSlot(item, out pos);
		}

		public void AddItem(ItemData item, Container sourceContainer, ZDOID sender, int amount = 1)
		{
			//IL_0047: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			FindFreeSlot(item, out var pos);
			if ((Object)(object)sourceContainer != (Object)null && sourceContainer.GetInventory() != null)
			{
				ContainerHandler.AddItemToChest(container, item, sourceContainer.GetInventory(), pos, sender, amount);
			}
			else
			{
				container.AddItemDirect(item, pos, amount);
			}
		}

		public IEnumerable<ItemData> GetItems()
		{
			int fixedFrameCount = HopperHelper.GetFixedFrameCount();
			if (fixedFrameCount == lastPullFrame)
			{
				return Enumerable.Empty<ItemData>();
			}
			return containerTarget.GetItems();
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Debug("[" + DbgId + "] RemoveItem '" + item.m_shared.m_name + "' pulled by upstream");
			lastPullFrame = HopperHelper.GetFixedFrameCount();
			containerTarget.RemoveItem(item, destinationContainer, destinationPos, sender, amount);
		}

		private bool FindFreeSlot(ItemData itemToAdd, out Vector2i pos)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			pos = new Vector2i(0, 0);
			if (!container.GetInventory().CanAddItem(itemToAdd, 1))
			{
				return false;
			}
			if (FilterItemsOption.Get())
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)itemToAdd.m_dropPrefab).name);
				bool flag = IsInFilter(stableHashCode);
				if (BlacklistModeOption.Get())
				{
					if (flag)
					{
						return false;
					}
				}
				else if (!flag && filterInventory.m_inventory.Count > 0)
				{
					return false;
				}
			}
			for (int i = 0; i < container.m_height; i++)
			{
				for (int j = 0; j < container.m_width; j++)
				{
					if (container.GetInventory().GetItemAt(j, i) == null)
					{
						pos = new Vector2i(j, i);
						return true;
					}
				}
			}
			return false;
		}

		private bool IsInFilter(int itemHash)
		{
			foreach (ItemData item in filterInventory.m_inventory)
			{
				if (StringExtensionMethods.GetStableHashCode(((Object)item.m_dropPrefab).name) == itemHash)
				{
					return true;
				}
			}
			return false;
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}

		private bool CanPushItem(ItemData item)
		{
			return !LeaveLastItemOption.Get() || container.GetInventory().CountItems(item.m_shared.m_name, -1, true) > 1;
		}

		private bool IsAllowedPushing(ItemData item)
		{
			if (!FilterItemsOption.Get())
			{
				return true;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)item.m_dropPrefab).name);
			bool flag = IsInFilter(stableHashCode);
			if (BlacklistModeOption.Get())
			{
				return !flag;
			}
			return flag || filterInventory.m_inventory.Count == 0;
		}

		private void FindIO()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotation = ((Component)this).transform.rotation;
			pullFrom = HopperHelper.FindTargets(((Component)this).transform.TransformPoint(inPos), inSize, rotation, (IPullTarget i) => i.PullPriority, this);
			int count = pullFrom.Count;
			pullFrom.RemoveAll((IPullTarget i) => i is Pipe);
			if (pullFrom.Count < count)
			{
				Plugin.Debug($"[{DbgId}] Ignored {count - pullFrom.Count} Upstream Pipes (Hoppers cannot pull from Pipes)");
			}
			pushTo = HopperHelper.FindTargets(((Component)this).transform.TransformPoint(outPos), outSize, rotation, (IPushTarget i) => i.PushPriority, this);
			Plugin.Debug(string.Format("[{0}] Targets: Pull[{1}] {2}", DbgId, pullFrom.Count, string.Join(", ", pullFrom.Select(delegate(IPullTarget t)
			{
				IPullTarget obj = ((t is MonoBehaviour) ? t : null);
				return ((obj != null) ? ((Object)((Component)obj).gameObject).name : null) ?? t.GetType().Name;
			}))));
			Plugin.Debug(string.Format("[{0}] Targets: Push[{1}] {2}", DbgId, pushTo.Count, string.Join(", ", pushTo.Select(delegate(IPushTarget t)
			{
				IPushTarget obj = ((t is MonoBehaviour) ? t : null);
				return ((obj != null) ? ((Object)((Component)obj).gameObject).name : null) ?? t.GetType().Name;
			}))));
			pullFrom.RemoveAll((IPullTarget pull) => pushTo.Exists((IPushTarget push) => push.NetworkHashCode() == pull.NetworkHashCode()));
			WakeUp();
		}

		private void OnDrawGizmos()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = Color.blue;
			Gizmos.DrawWireCube(((Component)this).transform.TransformPoint(inPos), inSize);
			Gizmos.color = Color.yellow;
			Gizmos.DrawWireCube(((Component)this).transform.TransformPoint(outPos), outSize);
			Gizmos.color = Color.cyan;
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val = item;
				if (((Component)val).CompareTag("snappoint"))
				{
					Gizmos.DrawSphere(val.position, 0.05f);
				}
			}
		}
	}
	public enum HopperPriority
	{
		ItemDropPull = 0,
		SmelterFuelPush = 10,
		SmelterOrePush = 10,
		ContainerPull = 20,
		ContainerPush = 20,
		HopperPull = 30,
		HopperPush = 30,
		PipePull = 40,
		PipePush = 40,
		BeehivePull = 50,
		TurretPush = 60
	}
	public interface IPullTarget : ITarget, IEqualityComparer<ITarget>
	{
		HopperPriority PullPriority { get; }

		bool IsPickup { get; }

		IEnumerable<ItemData> GetItems();

		void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1);
	}
	public interface IPushTarget : ITarget, IEqualityComparer<ITarget>
	{
		HopperPriority PushPriority { get; }

		bool CanAddItem(ItemData item);

		void AddItem(ItemData item, Container sourceContainer, ZDOID sender, int amount = 1);
	}
	public interface ITarget : IEqualityComparer<ITarget>
	{
		int NetworkHashCode();

		bool IsValid();

		bool InRange(Vector3 position);
	}
	public class NetworkPiece : MonoBehaviour
	{
		protected ZNetView zNetView;

		protected int OutputCounter = 0;

		public bool IsPushBlocked { get; protected set; }

		public bool IsPullBlocked { get; protected set; }

		protected virtual void Awake()
		{
			zNetView = ((Component)this).GetComponentInParent<ZNetView>();
		}

		public void WakeUp()
		{
			IsPushBlocked = false;
			IsPullBlocked = false;
		}

		public bool IsValid()
		{
			return Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)zNetView) && HopperHelper.IsValidNetView(zNetView) && zNetView.HasOwner();
		}

		public int NetworkHashCode()
		{
			if (Object.op_Implicit((Object)(object)zNetView) && zNetView.m_zdo != null)
			{
				return HopperHelper.GetNetworkHashCode(zNetView);
			}
			return ((Object)this).GetInstanceID();
		}

		public bool Equals(ITarget x, ITarget y)
		{
			return x == y || x?.NetworkHashCode() == y?.NetworkHashCode();
		}

		public int GetHashCode(ITarget obj)
		{
			return obj.NetworkHashCode();
		}
	}
	public class Pipe : NetworkPiece, IPushTarget, ITarget, IEqualityComparer<ITarget>, IPullTarget
	{
		[SerializeField]
		private Vector3 outPos = new Vector3(0f, 0f, -1f);

		[SerializeField]
		private Vector3 outSize = new Vector3(0.125f, 0.25f, 0.25f);

		private Container container;

		private ContainerTarget containerTarget;

		private List<IPushTarget> pushTo = new List<IPushTarget>();

		private BoxVisualizer outVisualizer;

		private int lastPullFrame = -1;

		private const float ObjectSearchInterval = 3f;

		private int transferFrame;

		private int objectSearchFrame;

		private int frameOffset;

		public HopperPriority PushPriority { get; } = HopperPriority.PipePull;

		public HopperPriority PullPriority { get; } = HopperPriority.PipePull;

		public bool IsPickup { get; } = false;

		private string DbgId
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				Vector3 position = ((Component)this).transform.position;
				return "Pipe@" + ((Vector3)(ref position)).ToString("F1");
			}
		}

		protected override void Awake()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			base.Awake();
			container = ((Component)this).GetComponent<Container>();
			containerTarget = ((Component)this).GetComponent<ContainerTarget>();
			UpdateTransferRate();
			objectSearchFrame = Mathf.RoundToInt(1f / Time.fixedDeltaTime * 3f);
			frameOffset = Mathf.Abs(((Object)this).GetInstanceID() % transferFrame);
			outVisualizer = ((Component)this).gameObject.AddComponent<BoxVisualizer>();
			outVisualizer.SetData(outPos, outSize, Color.yellow, Plugin.ShowPipeOutputBox);
		}

		private void Start()
		{
			Inventory inventory = container.GetInventory();
			inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(base.WakeUp));
			HopperHelper.OnTargetChanged += OnTargetChanged;
		}

		private void OnDestroy()
		{
			HopperHelper.OnTargetChanged -= OnTargetChanged;
		}

		private void OnTargetChanged(ITarget target)
		{
			if (base.IsPushBlocked && pushTo.Any((IPushTarget t) => t.NetworkHashCode() == target.NetworkHashCode()))
			{
				base.IsPushBlocked = false;
			}
		}

		private void UpdateTransferRate()
		{
			float num = (((Object)this).name.Contains("Iron") ? Plugin.IronTransferRate.Value : Plugin.BronzeTransferRate.Value);
			float num2 = 30f / Mathf.Max(1f, num);
			transferFrame = Mathf.RoundToInt(num2 / Time.fixedDeltaTime);
			if (transferFrame < 1)
			{
				transferFrame = 1;
			}
		}

		private void FixedUpdate()
		{
			if (IsValid() && zNetView.IsOwner() && !Plugin.DisableAllSystems.Value)
			{
				int fixedFrameCount = HopperHelper.GetFixedFrameCount();
				int num = (fixedFrameCount + frameOffset) / transferFrame;
				if ((fixedFrameCount + frameOffset) % transferFrame == 0 && num % 2 == 1 && !base.IsPushBlocked)
				{
					PushItems();
				}
				if ((fixedFrameCount + frameOffset + 1) % objectSearchFrame == 0)
				{
					FindIO();
				}
			}
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}

		public bool CanAddItem(ItemData item)
		{
			return containerTarget.CanAddItem(item);
		}

		public void AddItem(ItemData item, Container sourceContainer, ZDOID sender, int amount = 1)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Debug("[" + DbgId + "] AddItem '" + (item?.m_shared?.m_name ?? "null") + "' pushed by upstream");
			containerTarget.AddItem(item, sourceContainer, sender, amount);
		}

		public IEnumerable<ItemData> GetItems()
		{
			int fixedFrameCount = HopperHelper.GetFixedFrameCount();
			if (fixedFrameCount == lastPullFrame)
			{
				return Enumerable.Empty<ItemData>();
			}
			return containerTarget.GetItems();
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//IL_006a: 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)
			Plugin.Debug("[" + DbgId + "] RemoveItem '" + (item?.m_shared?.m_name ?? "null") + "' pulled by hopper");
			lastPullFrame = HopperHelper.GetFixedFrameCount();
			containerTarget.RemoveItem(item, destinationContainer, destinationPos, sender, amount);
		}

		private void PushItems()
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			if (pushTo.Count == 0 || container.GetInventory().NrOfItems() == 0)
			{
				base.IsPushBlocked = true;
				return;
			}
			int num = OutputCounter % pushTo.Count;
			for (int i = 0; i < pushTo.Count; i++)
			{
				int num2 = (num + i) % pushTo.Count;
				IPushTarget to = pushTo[num2];
				if (to.IsValid())
				{
					ItemData val = container.GetInventory().FindLastItem((ItemData item) => to.CanAddItem(item));
					if (val != null)
					{
						OutputCounter = num2 + 1;
						Plugin.Debug(string.Format("[{0}] Pushing '{1}' -> target [{2}] ({3})", DbgId, val.m_shared?.m_name ?? "null", num2, to.GetType().Name));
						to.AddItem(val, container, zNetView.GetZDO().m_uid);
						HopperHelper.NotifyChange(this);
						HopperHelper.NotifyChange(to);
						return;
					}
				}
			}
			Plugin.Debug("[" + DbgId + "] No targets could accept item (full or filtered)");
			base.IsPushBlocked = true;
		}

		private void FindIO()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			Quaternion rotation = ((Component)this).transform.rotation;
			List<IPushTarget> list = HopperHelper.FindTargets(((Component)this).transform.TransformPoint(outPos), outSize, rotation, (IPushTarget i) => i.PushPriority, this);
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 2.5f, LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" }));
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				Hopper hopper = ((Component)val).GetComponentInParent<Hopper>();
				if ((Object)(object)hopper != (Object)null && !list.Any((IPushTarget t) => t.NetworkHashCode() == hopper.NetworkHashCode()))
				{
					list.Add(hopper);
				}
			}
			List<IPushTarget> list2 = new List<IPushTarget>();
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>();
			foreach (IPushTarget item in list)
			{
				if (item is Hopper hopper2)
				{
					if (HopperHelper.BoxIntersectsColliders(((Component)hopper2).transform.TransformPoint(hopper2.InPos), hopper2.InSize, ((Component)hopper2).transform.rotation, componentsInChildren))
					{
						list2.Add(item);
						Plugin.Debug("[" + DbgId + "] Added Hopper output via body-overlap: " + ((Object)((Component)hopper2).gameObject).name);
					}
					else
					{
						Plugin.Debug("[" + DbgId + "] Skipped Hopper (no body-overlap): " + ((Object)((Component)hopper2).gameObject).name);
					}
					continue;
				}
				list2.Add(item);
				MonoBehaviour val2 = (MonoBehaviour)((item is MonoBehaviour) ? item : null);
				if (val2 != null)
				{
					Plugin.Debug("[" + DbgId + "] Added standard output target: " + ((Object)((Component)val2).gameObject).name);
				}
			}
			pushTo = list2;
			Plugin.Debug("[" + DbgId + "] Output list: [" + string.Join(", ", pushTo.Select((IPushTarget t) => t.GetType().Name)) + "]");
			WakeUp();
		}

		private void OnDrawGizmos()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			Gizmos.color = Color.yellow;
			Gizmos.DrawWireCube(((Component)this).transform.TransformPoint(outPos), outSize);
			Gizmos.color = Color.cyan;
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val = item;
				if (((Component)val).CompareTag("snappoint"))
				{
					Gizmos.DrawSphere(val.position, 0.05f);
				}
			}
		}
	}
	public class BeehiveTarget : NetworkPiece, IPullTarget, ITarget, IEqualityComparer<ITarget>
	{
		private Beehive beehive;

		private const string RequestOwnershipRPC = "VH_RequestOwnership";

		public HopperPriority PullPriority { get; } = HopperPriority.BeehivePull;

		public bool IsPickup { get; } = false;

		protected override void Awake()
		{
			base.Awake();
			beehive = ((Component)this).GetComponent<Beehive>();
			beehive.m_nview.Register("VH_RequestOwnership", (Action<long>)RPC_RequestOwnership);
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}

		public IEnumerable<ItemData> GetItems()
		{
			if (Object.op_Implicit((Object)(object)beehive.m_honeyItem) && beehive.GetHoneyLevel() > 0)
			{
				ItemHelper.CheckDropPrefab(beehive.m_honeyItem);
				yield return beehive.m_honeyItem.m_itemData;
			}
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (!beehive.m_nview.IsOwner())
			{
				beehive.m_nview.InvokeRPC("VH_RequestOwnership", Array.Empty<object>());
				return;
			}
			int honeyLevel = beehive.GetHoneyLevel();
			int num = Mathf.Min(honeyLevel, amount);
			if (num > 0)
			{
				beehive.m_nview.GetZDO().Set(ZDOVars.s_level, honeyLevel - num, false);
				destinationContainer.AddItemDirect(item, destinationPos, num);
			}
		}

		private void RPC_RequestOwnership(long sender)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (beehive.m_nview.IsOwner())
			{
				beehive.m_nview.GetZDO().SetOwner(sender);
				ZDOMan.instance.ForceSendZDO(sender, beehive.m_nview.GetZDO().m_uid);
			}
		}
	}
	public class ClayCollectorTarget : NetworkPiece, IPullTarget, ITarget, IEqualityComparer<ITarget>
	{
		private Component collectorComponent;

		private MethodInfo getTarLevelMethod;

		private MethodInfo resetLevelMethod;

		private FieldInfo clayItemField;

		private const string RequestOwnershipRPC = "VH_RequestOwnership_Clay";

		public HopperPriority PullPriority { get; } = HopperPriority.BeehivePull;

		public bool IsPickup { get; } = false;

		protected override void Awake()
		{
			base.Awake();
			collectorComponent = ((Component)this).GetComponent("ClayCollector");
			if ((Object)(object)collectorComponent != (Object)null)
			{
				Type type = ((object)collectorComponent).GetType();
				getTarLevelMethod = type.GetMethod("GetTarLevel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				resetLevelMethod = type.GetMethod("ResetLevel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				clayItemField = type.GetField("m_clayItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Plugin.Debug($"[ClayCollector] Found component. Methods: GetTarLevel={getTarLevelMethod != null}, ResetLevel={resetLevelMethod != null}, m_clayItem={clayItemField != null}");
			}
			else
			{
				Plugin.Debug("[ClayCollector] Critical: 'ClayCollector' component not found on this object!");
			}
			if ((Object)(object)zNetView != (Object)null)
			{
				zNetView.Register("VH_RequestOwnership_Clay", (Action<long>)RPC_RequestOwnership);
			}
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}

		public IEnumerable<ItemData> GetItems()
		{
			if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || (Object)(object)collectorComponent == (Object)null)
			{
				yield break;
			}
			int level = GetCurrentLevel();
			if (level <= 0)
			{
				yield break;
			}
			GameObject prefab = GetClayPrefab();
			if (Object.op_Implicit((Object)(object)prefab))
			{
				ItemDrop itemDrop = prefab.GetComponent<ItemDrop>();
				if (Object.op_Implicit((Object)(object)itemDrop))
				{
					yield return itemDrop.m_itemData;
				}
			}
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || (Object)(object)collectorComponent == (Object)null)
			{
				return;
			}
			if (!zNetView.IsOwner())
			{
				zNetView.InvokeRPC("VH_RequestOwnership_Clay", Array.Empty<object>());
				return;
			}
			int currentLevel = GetCurrentLevel();
			if (currentLevel > 0)
			{
				if (resetLevelMethod != null)
				{
					resetLevelMethod.Invoke(collectorComponent, null);
				}
				else
				{
					zNetView.GetZDO().Set("Produced", 0);
					zNetView.GetZDO().Set("level", 0);
				}
				destinationContainer.AddItemDirect(item, destinationPos, currentLevel);
			}
		}

		private int GetCurrentLevel()
		{
			if (getTarLevelMethod != null)
			{
				return (int)getTarLevelMethod.Invoke(collectorComponent, null);
			}
			int num = zNetView.GetZDO().GetInt("Produced", 0);
			if (num == 0)
			{
				num = zNetView.GetZDO().GetInt("level", 0);
			}
			return num;
		}

		private GameObject GetClayPrefab()
		{
			if (clayItemField != null)
			{
				object? value = clayItemField.GetValue(collectorComponent);
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("BFP_Clay");
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				itemPrefab = ObjectDB.instance.GetItemPrefab("Clay");
			}
			return itemPrefab;
		}

		private void RPC_RequestOwnership(long sender)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)zNetView == (Object)null) && zNetView.IsOwner())
			{
				zNetView.GetZDO().SetOwner(sender);
				ZDOMan.instance.ForceSendZDO(sender, zNetView.GetZDO().m_uid);
			}
		}
	}
	public class ContainerTarget : NetworkPiece, IPushTarget, ITarget, IEqualityComparer<ITarget>, IPullTarget
	{
		private Container container;

		public HopperPriority PushPriority { get; } = HopperPriority.ContainerPull;

		public HopperPriority PullPriority { get; } = HopperPriority.ContainerPull;

		public bool IsPickup { get; } = false;

		protected override void Awake()
		{
			base.Awake();
			container = ((Component)this).GetComponent<Container>();
		}

		private void Start()
		{
			if ((Object)(object)container != (Object)null && container.GetInventory() != null)
			{
				Inventory inventory = container.GetInventory();
				inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
			}
		}

		private void OnInventoryChanged()
		{
			HopperHelper.NotifyChange(this);
		}

		public IEnumerable<ItemData> GetItems()
		{
			return container.GetInventory().GetItemInReverseOrder();
		}

		public void AddItem(ItemData item, Container sourceContainer, ZDOID sender, int amount = 1)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sourceContainer != (Object)null && sourceContainer.GetInventory() != null)
			{
				ContainerHandler.AddItemToChest(container, item, sourceContainer.GetInventory(), new Vector2i(-1, -1), sender, amount);
			}
			else
			{
				container.AddItemDirect(item, new Vector2i(-1, -1), amount);
			}
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)destinationContainer != (Object)null && destinationContainer.GetInventory() != null)
			{
				ContainerHandler.RemoveItemFromChest(container, item, destinationContainer.GetInventory(), destinationPos, sender, amount, (ItemData)null);
			}
			else
			{
				container.GetInventory().RemoveItem(item, amount);
			}
		}

		public bool CanAddItem(ItemData item)
		{
			return container.GetInventory().CanAddItem(item, 1);
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}
	}
	public class CookingStationTarget : NetworkPiece, IPushTarget, ITarget, IEqualityComparer<ITarget>, IPullTarget
	{
		private CookingStation cookingStation;

		private static FieldInfo cookableField;

		private static bool fieldDetected;

		public HopperPriority PushPriority { get; } = HopperPriority.SmelterFuelPush;

		public HopperPriority PullPriority { get; } = HopperPriority.HopperPull;

		public bool IsPickup { get; } = false;

		protected override void Awake()
		{
			base.Awake();
			cookingStation = ((Component)this).GetComponent<CookingStation>();
			FieldInfo[] fields = typeof(CookingStation).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				Plugin.Debug($"CookingStation field: {fieldInfo.FieldType} {fieldInfo.Name}");
			}
			if (!fieldDetected)
			{
				cookableField = typeof(CookingStation).GetField("m_cookable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (cookableField == null)
				{
					cookableField = typeof(CookingStation).GetField("m_conversion", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				Plugin.Debug("Checking " + ((object)this).GetType().Name);
				Plugin.Debug("cookableField resolved to: " + (cookableField?.Name ?? "NULL"));
				fieldDetected = true;
			}
		}

		private void Start()
		{
			string[] array = new string[11]
			{
				"RPC_AddFuel", "RPC_AddItem", "RPC_RemoveDoneItem", "RPC_SetSlotVisual", "RPC_RequestOwn", "RPC_Pick", "RPC_RemoveItem", "RPC_ClearSlot", "RPC_SetCookingStation", "RPC_AddItemToSlot",
				"RPC_RemoveSlot"
			};
			string[] array2 = array;
			foreach (string text in array2)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(text);
				if (cookingStation.m_nview.m_functions.ContainsKey(stableHashCode))
				{
					Plugin.Debug($"MATCHED: '{text}' = {stableHashCode}");
				}
			}
			foreach (int key in cookingStation.m_nview.m_functions.Keys)
			{
				Plugin.Debug($"Registered hash: {key}");
			}
		}

		private bool IsFuelItem(ItemData item)
		{
			if ((Object)(object)cookingStation.m_fuelItem == (Object)null)
			{
				return false;
			}
			return cookingStation.m_fuelItem.m_itemData.m_shared.m_name == item.m_shared.m_name;
		}

		private bool IsCookableItem(ItemData item)
		{
			if (cookableField == null)
			{
				Plugin.Debug("cookableField is null — reflection failed at Awake");
				return false;
			}
			if (!(cookableField.GetValue(cookingStation) is IEnumerable enumerable))
			{
				Plugin.Debug("cookableList cast failed on field: " + cookableField.Name);
				return false;
			}
			foreach (object item2 in enumerable)
			{
				FieldInfo field = item2.GetType().GetField("m_from", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					continue;
				}
				object? value = field.GetValue(item2);
				ItemDrop val = (ItemDrop)((value is ItemDrop) ? value : null);
				if (!((Object)(object)val == (Object)null))
				{
					Plugin.Debug("Comparing incoming '" + item.m_shared.m_name + "' vs conversion '" + val.m_itemData.m_shared.m_name + "'");
					if (val.m_itemData.m_shared.m_name == item.m_shared.m_name)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool IsIncompatibleItem(ItemData item)
		{
			FieldInfo field = typeof(CookingStation).GetField("m_incompatibleItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return false;
			}
			if (!(field.GetValue(cookingStation) is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item2 in enumerable)
			{
				FieldInfo field2 = item2.GetType().GetField("m_item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field2 == null))
				{
					object? value = field2.GetValue(item2);
					ItemDrop val = (ItemDrop)((value is ItemDrop) ? value : null);
					if ((Object)(object)val != (Object)null && val.m_itemData.m_shared.m_name == item.m_shared.m_name)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool CanAddFuel()
		{
			if ((Object)(object)cookingStation.m_fuelItem == (Object)null)
			{
				return false;
			}
			float fuel = cookingStation.GetFuel();
			return fuel < (float)cookingStation.m_maxFuel;
		}

		public bool CanAddItem(ItemData item)
		{
			if (IsIncompatibleItem(item))
			{
				return false;
			}
			if ((Object)(object)cookingStation == (Object)null)
			{
				Plugin.Debug(((object)this).GetType().Name + " cookingStation is null");
				return false;
			}
			if (IsFuelItem(item))
			{
				Plugin.Debug(((object)this).GetType().Name + "'s " + item.m_shared.m_name + " is fuel");
				return CanAddFuel();
			}
			if (cookableField != null)
			{
				if (IsCookableItem(item))
				{
					Plugin.Debug(((object)this).GetType().Name + "'s " + item.m_shared.m_name + " is cookable");
					return cookingStation.GetFreeSlot() != -1;
				}
				Plugin.Debug(((object)this).GetType().Name + "'s " + item.m_shared.m_name + " is unknown");
				return false;
			}
			Plugin.Debug("cookableField null, falling back to slot check for '" + item.m_shared.m_name + "'");
			return cookingStation.GetFreeSlot() != -1;
		}

		public void AddItem(ItemData item, Container sourceContainer, ZDOID sender, int amount = 1)
		{
			sourceContainer.RemoveItemDirect(item, amount);
			if (IsFuelItem(item))
			{
				cookingStation.m_nview.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
				return;
			}
			cookingStation.m_nview.InvokeRPC("RPC_AddItem", new object[2]
			{
				((Object)item.m_dropPrefab).name,
				false
			});
		}

		public bool InRange(Vector3 position)
		{
			return true;
		}

		public IEnumerable<ItemData> GetItems()
		{
			List<ItemData> list = new List<ItemData>();
			if ((Object)(object)cookingStation == (Object)null)
			{
				return list;
			}
			int num = cookingStation.m_slots.Length;
			for (int i = 0; i < num; i++)
			{
				string text = cookingStation.m_nview.GetZDO().GetString($"slot{i}", "");
				if (string.IsNullOrEmpty(text) || text == "0")
				{
					continue;
				}
				bool flag = GetConversionForCooked(text) != null;
				ItemDrop overCookedItem = cookingStation.m_overCookedItem;
				bool flag2 = text == ((overCookedItem != null) ? ((Object)overCookedItem).name : null);
				if (!flag && !flag2)
				{
					continue;
				}
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if (!((Object)(object)prefab == (Object)null))
				{
					ItemDrop component = prefab.GetComponent<ItemDrop>();
					if (!((Object)(object)component == (Object)null))
					{
						list.Add(component.m_itemData.Clone());
					}
				}
			}
			return list;
		}

		public void RemoveItem(ItemData item, Container destinationContainer, Vector2i destinationPos, ZDOID sender, int amount = 1)
		{
			//I