Decompiled source of AutoProduktion v1.0.0

plugins/AutoProduktion.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("AutoProduktion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AutoProduktion")]
[assembly: AssemblyTitle("AutoProduktion")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Schachio.AutoProduktion
{
	[BepInPlugin("AutoProduktion", "Auto-Produktion", "1.0.0")]
	public sealed class AutoProduktionPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "AutoProduktion";

		public const string PluginName = "Auto-Produktion";

		public const string PluginVersion = "1.0.0";

		private float _nextScan;

		private float _nextConfigCheck;

		private DateTime _configWriteTimeUtc;

		internal static AutoProduktionPlugin Instance { get; private set; }

		internal static ConfigEntry<bool> Aktiviert { get; private set; }

		internal static ConfigEntry<float> SchmelzofenRadius { get; private set; }

		internal static ConfigEntry<bool> SchmelzofenErzeAufnehmen { get; private set; }

		internal static ConfigEntry<float> KohlenmeilerRadius { get; private set; }

		internal static ConfigEntry<float> HochofenRadius { get; private set; }

		internal static ConfigEntry<bool> HochofenRohstoffeAufnehmen { get; private set; }

		internal static ConfigEntry<float> SteinofenRadius { get; private set; }

		internal static ConfigEntry<bool> SteinofenRohstoffeAufnehmen { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> SchmelzofenRadiusTaste { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> KohlenmeilerRadiusTaste { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> HochofenRadiusTaste { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> SteinofenRadiusTaste { get; private set; }

		internal static ConfigEntry<string> SchmelzofenRadiusFarbe { get; private set; }

		internal static ConfigEntry<string> KohlenmeilerRadiusFarbe { get; private set; }

		internal static ConfigEntry<string> HochofenRadiusFarbe { get; private set; }

		internal static ConfigEntry<string> SteinofenRadiusFarbe { get; private set; }

		internal static ConfigEntry<bool> AutomatischeRadiusAnzeige { get; private set; }

		internal static ConfigEntry<float> AutomatischeAnzeigeDauer { get; private set; }

		internal static ConfigEntry<float> Pruefintervall { get; private set; }

		internal static ConfigEntry<bool> Diagnose { get; private set; }

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Expected O, but got Unknown
			Instance = this;
			Aktiviert = ((BaseUnityPlugin)this).Config.Bind<bool>("Allgemein", "Aktiviert", true, "Schaltet die automatische Ressourcenaufnahme aller Anlagen ein oder aus.");
			SchmelzofenRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Schmelzofen", "Radius", 2.5f, new ConfigDescription("Kohle- und Erz-Aufnahmeradius des Schmelzofens in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
			SchmelzofenErzeAufnehmen = ((BaseUnityPlugin)this).Config.Bind<bool>("Schmelzofen", "ErzeVomBodenAufnehmen", true, "Nimmt alle unverarbeiteten Materialien auf, die der Schmelzofen laut seinen Rezepten verarbeiten kann. Barren werden nicht aufgenommen.");
			KohlenmeilerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Kohlenmeiler", "Radius", 2.5f, new ConfigDescription("Holz-Aufnahmeradius des Kohlenmeilers in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
			HochofenRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Hochofen", "Radius", 2.5f, new ConfigDescription("Kohle- und Rohstoff-Aufnahmeradius des Hochofens in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
			HochofenRohstoffeAufnehmen = ((BaseUnityPlugin)this).Config.Bind<bool>("Hochofen", "RohstoffeVomBodenAufnehmen", true, "Nimmt Kohle und alle unverarbeiteten Materialien auf, die der Hochofen laut seinen Rezepten verarbeiten kann.");
			SteinofenRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Steinofen", "Radius", 2.5f, new ConfigDescription("Holz- und Zutaten-Aufnahmeradius des Steinofens in Metern.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), Array.Empty<object>()));
			SteinofenRohstoffeAufnehmen = ((BaseUnityPlugin)this).Config.Bind<bool>("Steinofen", "RohstoffeVomBodenAufnehmen", true, "Nimmt Holz und alle ungebackenen Speisen auf, die der Steinofen laut seinen Rezepten verarbeiten kann.");
			Pruefintervall = ((BaseUnityPlugin)this).Config.Bind<float>("Allgemein", "PruefintervallSekunden", 0.25f, new ConfigDescription("Zeit zwischen zwei Suchlaeufen nach Ressourcen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
			SchmelzofenRadiusTaste = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Anzeige", "SchmelzofenRadiusTaste", RadiusHotkeys.Default((KeyCode)282), "Schaltet die Schmelzofen-Kreise dauerhaft ein oder aus. Standard: Shift + F1; linke oder rechte Shift-Taste.");
			KohlenmeilerRadiusTaste = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Anzeige", "KohlenmeilerRadiusTaste", RadiusHotkeys.Default((KeyCode)283), "Schaltet die Kohlenmeiler-Kreise dauerhaft ein oder aus. Standard: Shift + F2; linke oder rechte Shift-Taste.");
			HochofenRadiusTaste = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Anzeige", "HochofenRadiusTaste", RadiusHotkeys.Default((KeyCode)284), "Schaltet die Hochofen-Kreise dauerhaft ein oder aus. Standard: Shift + F3; linke oder rechte Shift-Taste.");
			SteinofenRadiusTaste = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Anzeige", "SteinofenRadiusTaste", RadiusHotkeys.Default((KeyCode)285), "Schaltet die Steinofen-Kreise dauerhaft ein oder aus. Standard: Shift + F4; linke oder rechte Shift-Taste.");
			SchmelzofenRadiusFarbe = ((BaseUnityPlugin)this).Config.Bind<string>("Anzeige", "SchmelzofenRadiusFarbe", "#FF0000", "Kreisfarbe als HTML-Farbwert, zum Beispiel #FF0000 fuer Rot.");
			KohlenmeilerRadiusFarbe = ((BaseUnityPlugin)this).Config.Bind<string>("Anzeige", "KohlenmeilerRadiusFarbe", "#FFFFFF", "Kreisfarbe als HTML-Farbwert, zum Beispiel #FFFFFF fuer Weiss.");
			HochofenRadiusFarbe = ((BaseUnityPlugin)this).Config.Bind<string>("Anzeige", "HochofenRadiusFarbe", "#FF8C00", "Kreisfarbe als HTML-Farbwert, Standard ist Orange.");
			SteinofenRadiusFarbe = ((BaseUnityPlugin)this).Config.Bind<string>("Anzeige", "SteinofenRadiusFarbe", "#00BFFF", "Kreisfarbe als HTML-Farbwert, Standard ist Hellblau.");
			AutomatischeRadiusAnzeige = ((BaseUnityPlugin)this).Config.Bind<bool>("Anzeige", "AutomatischFuenfSekundenAnzeigen", true, "Zeigt den passenden Kreis automatisch bei neu erkannten oder angesehenen Anlagen.");
			AutomatischeAnzeigeDauer = ((BaseUnityPlugin)this).Config.Bind<float>("Anzeige", "AutomatischeAnzeigedauerSekunden", 5f, new ConfigDescription("Dauer der automatischen Radiusanzeige.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			Diagnose = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnose", "AusfuehrlichesProtokoll", false, "Schreibt erkannte Anlagen und Ressourcentransfers in das BepInEx-Protokoll.");
			int num = RadiusHotkeys.MigrateLegacyDefaults(((BaseUnityPlugin)this).Config, SchmelzofenRadiusTaste, KohlenmeilerRadiusTaste, HochofenRadiusTaste, SteinofenRadiusTaste);
			if (num > 0)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"{num} bisherige Radiustasten auf Shift + F1 bis F4 umgestellt. Eigene Belegungen bleiben erhalten.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Auto-Produktion 1.0.0 geladen. " + $"Schmelzofen {SchmelzofenRadius.Value:0.##} m, " + $"Kohlenmeiler {KohlenmeilerRadius.Value:0.##} m, " + $"Hochofen {HochofenRadius.Value:0.##} m, " + $"Steinofen {SteinofenRadius.Value:0.##} m."));
			if (File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				_configWriteTimeUtc = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
			}
		}

		private void Update()
		{
			//IL_000b: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			ReloadConfigIfChanged();
			if (RadiusHotkeys.IsDown(SchmelzofenRadiusTaste.Value))
			{
				bool flag = RadiusDisplay.ToggleSmelters();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Schmelzofen-Radiustaste erkannt: " + (flag ? "AN" : "AUS") + "."));
				ShowMessage(string.Format("Schmelzofen-Radius {0} ({1:0.##} m)", flag ? "AN" : "AUS", SchmelzofenRadius.Value));
			}
			if (RadiusHotkeys.IsDown(KohlenmeilerRadiusTaste.Value))
			{
				bool flag2 = RadiusDisplay.ToggleKilns();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Kohlenmeiler-Radiustaste erkannt: " + (flag2 ? "AN" : "AUS") + "."));
				ShowMessage(string.Format("Kohlenmeiler-Radius {0} ({1:0.##} m)", flag2 ? "AN" : "AUS", KohlenmeilerRadius.Value));
			}
			if (RadiusHotkeys.IsDown(HochofenRadiusTaste.Value))
			{
				bool flag3 = RadiusDisplay.ToggleBlastFurnaces();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Hochofen-Radiustaste erkannt: " + (flag3 ? "AN" : "AUS") + "."));
				ShowMessage(string.Format("Hochofen-Radius {0} ({1:0.##} m)", flag3 ? "AN" : "AUS", HochofenRadius.Value));
			}
			if (RadiusHotkeys.IsDown(SteinofenRadiusTaste.Value))
			{
				bool flag4 = RadiusDisplay.ToggleStoneOvens();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Steinofen-Radiustaste erkannt: " + (flag4 ? "AN" : "AUS") + "."));
				ShowMessage(string.Format("Steinofen-Radius {0} ({1:0.##} m)", flag4 ? "AN" : "AUS", SteinofenRadius.Value));
			}
			RadiusDisplay.Update();
			if (Aktiviert.Value && !(Time.time < _nextScan))
			{
				_nextScan = Time.time + Mathf.Clamp(Pruefintervall.Value, 0.1f, 2f);
				CoalCollector.Scan();
				if (SchmelzofenErzeAufnehmen.Value || HochofenRohstoffeAufnehmen.Value)
				{
					OreCollector.Scan();
				}
				WoodCollector.Scan();
				if (SteinofenRohstoffeAufnehmen.Value)
				{
					StoneOvenCollector.Scan();
				}
			}
		}

		internal static void LogDiagnostic(string message)
		{
			if (Diagnose.Value)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogInfo(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}

		private void ReloadConfigIfChanged()
		{
			if (Time.unscaledTime < _nextConfigCheck)
			{
				return;
			}
			_nextConfigCheck = Time.unscaledTime + 1f;
			if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath) || File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath) <= _configWriteTimeUtc)
			{
				return;
			}
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
				_configWriteTimeUtc = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
				((BaseUnityPlugin)this).Logger.LogInfo((object)($"Config neu geladen: Schmelzofen {SchmelzofenRadius.Value:0.##} m, " + $"Kohlenmeiler {KohlenmeilerRadius.Value:0.##} m, " + $"Hochofen {HochofenRadius.Value:0.##} m, " + $"Steinofen {SteinofenRadius.Value:0.##} m."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Config konnte noch nicht neu geladen werden: " + ex.Message));
			}
		}

		private static void ShowMessage(string message)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null);
			}
		}
	}
	internal static class CoalCollector
	{
		private sealed class Target
		{
			internal Smelter Station { get; }

			internal float Radius { get; }

			internal string Name { get; }

			internal Target(Smelter station, float radius, string name)
			{
				Station = station;
				Radius = radius;
				Name = name;
			}
		}

		private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly FieldInfo NetworkViewField = typeof(Smelter).GetField("m_nview", PrivateInstance);

		private static readonly MethodInfo GetFuelMethod = typeof(Smelter).GetMethod("GetFuel", PrivateInstance);

		internal static void Scan()
		{
			List<Target> list = (from station in SmelterFinder.FindAll()
				select new Target(station, Mathf.Clamp(AutoProduktionPlugin.SchmelzofenRadius.Value, 2f, 50f), "Schmelzofen")).ToList();
			if (AutoProduktionPlugin.HochofenRohstoffeAufnehmen.Value)
			{
				list.AddRange(from station in SmelterFinder.FindAllBlastFurnaces()
					select new Target(station, Mathf.Clamp(AutoProduktionPlugin.HochofenRadius.Value, 2f, 50f), "Hochofen"));
			}
			list = list.Where((Target target) => UsesCoal(target.Station)).ToList();
			if (list.Count == 0)
			{
				return;
			}
			foreach (ItemDrop coal in Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0).Where(IsCoal).ToList())
			{
				if (!EnsureItemOwnership(coal))
				{
					continue;
				}
				foreach (Target item in (from candidate in list
					where SmelterFinder.HorizontalDistance(((Component)coal).transform.position, ((Component)candidate.Station).transform.position) <= candidate.Radius
					orderby SmelterFinder.HorizontalDistance(((Component)coal).transform.position, ((Component)candidate.Station).transform.position)
					select candidate).ToList())
				{
					int num = InsertCoal(item.Station, coal.m_itemData.m_stack);
					if (num > 0)
					{
						AutoProduktionPlugin.LogDiagnostic($"{num} Kohle vom Boden in {item.Name} eingefuellt.");
						RemoveFromGround(coal, num);
						if ((Object)(object)coal == (Object)null || coal.m_itemData == null || coal.m_itemData.m_stack <= 0)
						{
							break;
						}
					}
				}
			}
		}

		private static bool UsesCoal(Smelter station)
		{
			ItemDrop fuelItem = station.m_fuelItem;
			if ((Object)(object)fuelItem == (Object)null || fuelItem.m_itemData == null)
			{
				return false;
			}
			string a = SmelterFinder.CleanName(((Object)((Component)fuelItem).gameObject).name);
			string a2 = fuelItem.m_itemData.m_shared?.m_name ?? string.Empty;
			if (!string.Equals(a, "Coal", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(a2, "$item_coal", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static int InsertCoal(Smelter smelter, int available)
		{
			if (available <= 0 || smelter.m_maxFuel <= 0)
			{
				return 0;
			}
			object? value = NetworkViewField.GetValue(smelter);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return 0;
			}
			float num = (float)(GetFuelMethod.Invoke(smelter, null) ?? ((object)0f));
			int val2 = Math.Max(0, smelter.m_maxFuel - Mathf.CeilToInt(num));
			int num2 = Math.Min(available, val2);
			for (int i = 0; i < num2; i++)
			{
				val.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
			}
			return num2;
		}

		private static bool IsCoal(ItemDrop drop)
		{
			if ((Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_stack <= 0)
			{
				return false;
			}
			GameObject dropPrefab = drop.m_itemData.m_dropPrefab;
			string a = SmelterFinder.CleanName(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? ((Object)((Component)drop).gameObject).name);
			string a2 = drop.m_itemData.m_shared?.m_name ?? string.Empty;
			if (!string.Equals(a, "Coal", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(a2, "$item_coal", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool EnsureItemOwnership(ItemDrop drop)
		{
			ZNetView component = ((Component)drop).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			return component.IsOwner();
		}

		private static void RemoveFromGround(ItemDrop drop, int amount)
		{
			for (int i = 0; i < amount; i++)
			{
				if (!((Object)(object)drop != (Object)null))
				{
					break;
				}
				if (drop.m_itemData.m_stack <= 0)
				{
					break;
				}
				drop.RemoveOne();
			}
		}
	}
	internal static class OreCollector
	{
		private sealed class Target
		{
			internal Smelter Station { get; }

			internal float Radius { get; }

			internal string Name { get; }

			internal Target(Smelter station, float radius, string name)
			{
				Station = station;
				Radius = radius;
				Name = name;
			}
		}

		private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly FieldInfo NetworkViewField = typeof(Smelter).GetField("m_nview", PrivateInstance);

		private static readonly MethodInfo GetQueueSizeMethod = typeof(Smelter).GetMethod("GetQueueSize", PrivateInstance);

		internal static void Scan()
		{
			List<Target> list = new List<Target>();
			if (AutoProduktionPlugin.SchmelzofenErzeAufnehmen.Value)
			{
				list.AddRange(from station in SmelterFinder.FindAll()
					select new Target(station, Mathf.Clamp(AutoProduktionPlugin.SchmelzofenRadius.Value, 2f, 50f), "Schmelzofen"));
			}
			if (AutoProduktionPlugin.HochofenRohstoffeAufnehmen.Value)
			{
				list.AddRange(from station in SmelterFinder.FindAllBlastFurnaces()
					select new Target(station, Mathf.Clamp(AutoProduktionPlugin.HochofenRadius.Value, 2f, 50f), "Hochofen"));
			}
			if (list.Count == 0)
			{
				return;
			}
			ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
			foreach (ItemDrop item in array)
			{
				if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0 || !EnsureItemOwnership(item))
				{
					continue;
				}
				foreach (Target item2 in (from candidate in list
					where SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)candidate.Station).transform.position) <= candidate.Radius
					orderby SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)candidate.Station).transform.position)
					select candidate).ToList())
				{
					string text = FindAcceptedInput(item2.Station, item);
					if (text == null)
					{
						continue;
					}
					int num2 = InsertOre(item2.Station, text, item.m_itemData.m_stack);
					if (num2 > 0)
					{
						AutoProduktionPlugin.LogDiagnostic($"{num2}x {text} vom Boden in {item2.Name} eingefuellt.");
						RemoveFromGround(item, num2);
						if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0)
						{
							break;
						}
					}
				}
			}
		}

		private static string? FindAcceptedInput(Smelter smelter, ItemDrop item)
		{
			if (smelter.m_conversion == null)
			{
				return null;
			}
			GameObject dropPrefab = item.m_itemData.m_dropPrefab;
			string a = SmelterFinder.CleanName(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? ((Object)((Component)item).gameObject).name);
			string a2 = item.m_itemData.m_shared?.m_name ?? string.Empty;
			foreach (ItemConversion item2 in smelter.m_conversion)
			{
				if (!((Object)(object)item2?.m_from == (Object)null))
				{
					string text = SmelterFinder.CleanName(((Object)((Component)item2.m_from).gameObject).name);
					string b = item2.m_from.m_itemData?.m_shared?.m_name ?? string.Empty;
					if (string.Equals(a, text, StringComparison.OrdinalIgnoreCase) || string.Equals(a2, b, StringComparison.OrdinalIgnoreCase))
					{
						return text;
					}
				}
			}
			return null;
		}

		private static int InsertOre(Smelter smelter, string prefabName, int available)
		{
			if (available <= 0)
			{
				return 0;
			}
			object? value = NetworkViewField.GetValue(smelter);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return 0;
			}
			int num = (int)(GetQueueSizeMethod.Invoke(smelter, null) ?? ((object)0));
			int val2 = Math.Max(0, smelter.m_maxOre - num);
			int num2 = Math.Min(available, val2);
			for (int i = 0; i < num2; i++)
			{
				val.InvokeRPC("RPC_AddOre", new object[1] { prefabName });
			}
			return num2;
		}

		private static bool EnsureItemOwnership(ItemDrop item)
		{
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			return component.IsOwner();
		}

		private static void RemoveFromGround(ItemDrop item, int amount)
		{
			for (int i = 0; i < amount; i++)
			{
				if (!((Object)(object)item != (Object)null))
				{
					break;
				}
				if (item.m_itemData.m_stack <= 0)
				{
					break;
				}
				item.RemoveOne();
			}
		}
	}
	internal static class RadiusDisplay
	{
		private enum StationKind
		{
			Smelter,
			Kiln,
			BlastFurnace,
			StoneOven
		}

		private sealed class Circle
		{
			internal GameObject Marker { get; }

			internal CircleProjector Projector { get; }

			internal GameObject SegmentTemplate { get; }

			internal Color Color { get; set; }

			internal float Radius { get; set; }

			internal float VisibleUntil { get; set; }

			internal Circle(GameObject marker, CircleProjector projector, GameObject segmentTemplate, Color color)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				Marker = marker;
				Projector = projector;
				SegmentTemplate = segmentTemplate;
				Color = color;
				Radius = -1f;
			}
		}

		private static readonly Dictionary<int, Circle> Circles = new Dictionary<int, Circle>();

		private static readonly HashSet<int> Seen = new HashSet<int>();

		private static bool _smeltersPersistent;

		private static bool _kilnsPersistent;

		private static bool _blastFurnacesPersistent;

		private static bool _stoneOvensPersistent;

		private static float _nextRefresh;

		private static GameObject? _segmentTemplateRoot;

		internal static bool ToggleSmelters()
		{
			return _smeltersPersistent = !_smeltersPersistent;
		}

		internal static bool ToggleKilns()
		{
			return _kilnsPersistent = !_kilnsPersistent;
		}

		internal static bool ToggleBlastFurnaces()
		{
			return _blastFurnacesPersistent = !_blastFurnacesPersistent;
		}

		internal static bool ToggleStoneOvens()
		{
			return _stoneOvensPersistent = !_stoneOvensPersistent;
		}

		internal static void Update()
		{
			if (Time.time < _nextRefresh)
			{
				return;
			}
			_nextRefresh = Time.time + 0.2f;
			HashSet<int> liveIds = new HashSet<int>();
			foreach (Smelter item in SmelterFinder.FindAll())
			{
				UpdateStation((Component)(object)item, StationKind.Smelter, _smeltersPersistent, liveIds);
			}
			foreach (Smelter item2 in SmelterFinder.FindAllKilns())
			{
				UpdateStation((Component)(object)item2, StationKind.Kiln, _kilnsPersistent, liveIds);
			}
			foreach (Smelter item3 in SmelterFinder.FindAllBlastFurnaces())
			{
				UpdateStation((Component)(object)item3, StationKind.BlastFurnace, _blastFurnacesPersistent, liveIds);
			}
			foreach (CookingStation item4 in SmelterFinder.FindAllStoneOvens())
			{
				UpdateStation((Component)(object)item4, StationKind.StoneOven, _stoneOvensPersistent, liveIds);
			}
			ShowHoveredStation();
			foreach (int item5 in Circles.Keys.Where((int id) => !liveIds.Contains(id)).ToList())
			{
				Circle circle = Circles[item5];
				if ((Object)(object)circle.Marker != (Object)null)
				{
					Object.Destroy((Object)(object)circle.Marker);
				}
				if ((Object)(object)circle.SegmentTemplate != (Object)null)
				{
					Object.Destroy((Object)(object)circle.SegmentTemplate);
				}
				Circles.Remove(item5);
				Seen.Remove(item5);
			}
		}

		private static void UpdateStation(Component station, StationKind kind, bool persistent, HashSet<int> liveIds)
		{
			//IL_009d: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)station).GetInstanceID();
			liveIds.Add(instanceID);
			Circle orCreate = GetOrCreate(station, kind);
			if (orCreate != null)
			{
				if (Seen.Add(instanceID) && AutoProduktionPlugin.AutomatischeRadiusAnzeige.Value)
				{
					orCreate.VisibleUntil = Time.time + AutoProduktionPlugin.AutomatischeAnzeigeDauer.Value;
				}
				float num = Mathf.Clamp(GetRadius(kind), 2f, 50f);
				orCreate.Projector.m_radius = num;
				if (!Mathf.Approximately(orCreate.Radius, num))
				{
					orCreate.Radius = num;
					AutoProduktionPlugin.LogInfo($"{GetName(kind)}-Kreis auf {num:0.##} m aktualisiert.");
				}
				Color color = GetColor(kind);
				if (orCreate.Color != color)
				{
					Recolor(orCreate.SegmentTemplate, color);
					Recolor(orCreate.Marker, color);
					orCreate.Color = color;
					AutoProduktionPlugin.LogInfo(GetName(kind) + "-Kreisfarbe auf #" + ColorUtility.ToHtmlStringRGB(color) + " aktualisiert.");
				}
				orCreate.Marker.SetActive(persistent || Time.time < orCreate.VisibleUntil);
			}
		}

		private static void ShowHoveredStation()
		{
			if (!AutoProduktionPlugin.AutomatischeRadiusAnzeige.Value || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			GameObject hoverObject = ((Humanoid)Player.m_localPlayer).GetHoverObject();
			if ((Object)(object)hoverObject == (Object)null)
			{
				return;
			}
			Smelter componentInParent = hoverObject.GetComponentInParent<Smelter>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if (SmelterFinder.IsNormalSmelter(componentInParent))
				{
					ShowHovered((Component)(object)componentInParent, StationKind.Smelter);
				}
				else if (SmelterFinder.IsCharcoalKiln(componentInParent))
				{
					ShowHovered((Component)(object)componentInParent, StationKind.Kiln);
				}
				else if (SmelterFinder.IsBlastFurnace(componentInParent))
				{
					ShowHovered((Component)(object)componentInParent, StationKind.BlastFurnace);
				}
			}
			else
			{
				CookingStation componentInParent2 = hoverObject.GetComponentInParent<CookingStation>();
				if ((Object)(object)componentInParent2 != (Object)null && SmelterFinder.IsStoneOven(componentInParent2))
				{
					ShowHovered((Component)(object)componentInParent2, StationKind.StoneOven);
				}
			}
		}

		private static void ShowHovered(Component station, StationKind kind)
		{
			Circle orCreate = GetOrCreate(station, kind);
			if (orCreate != null)
			{
				float radius = Mathf.Clamp(GetRadius(kind), 2f, 50f);
				orCreate.Projector.m_radius = radius;
				orCreate.Radius = radius;
				orCreate.VisibleUntil = Time.time + AutoProduktionPlugin.AutomatischeAnzeigeDauer.Value;
				orCreate.Marker.SetActive(true);
			}
		}

		private static Circle? GetOrCreate(Component station, StationKind kind)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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)
			int instanceID = ((Object)station).GetInstanceID();
			if (Circles.TryGetValue(instanceID, out Circle value) && (Object)(object)value.Marker != (Object)null)
			{
				return value;
			}
			GameObject val = FindNativeAreaMarker();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, station.transform);
			((Object)val2).name = GetName(kind) + "_Radius";
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			CircleProjector component = val2.GetComponent<CircleProjector>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			Color color = GetColor(kind);
			GameObject val3 = CreateSegmentTemplate(component.m_prefab, color, GetName(kind));
			if ((Object)(object)val3 == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			component.m_prefab = val3;
			Recolor(val2, color);
			val2.SetActive(false);
			value = new Circle(val2, component, val3, color);
			Circles[instanceID] = value;
			AutoProduktionPlugin.LogInfo("Originaler Valheim-Radius fuer " + GetName(kind) + " mit Farbe #" + ColorUtility.ToHtmlStringRGB(color) + " erstellt.");
			return value;
		}

		private static GameObject? CreateSegmentTemplate(GameObject original, Color color, string stationName)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			if ((Object)(object)_segmentTemplateRoot == (Object)null)
			{
				_segmentTemplateRoot = new GameObject("AutoProduktion_RadiusVorlagen");
				Object.DontDestroyOnLoad((Object)(object)_segmentTemplateRoot);
				_segmentTemplateRoot.SetActive(false);
			}
			GameObject obj = Object.Instantiate<GameObject>(original, _segmentTemplateRoot.transform);
			((Object)obj).name = stationName + "_FarbigesKreissegment";
			Recolor(obj, color);
			return obj;
		}

		private static GameObject? FindNativeAreaMarker()
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = instance.GetPrefab("piece_workbench");
			CraftingStation val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CraftingStation>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_areaMarker;
		}

		private static float GetRadius(StationKind kind)
		{
			return kind switch
			{
				StationKind.Kiln => AutoProduktionPlugin.KohlenmeilerRadius.Value, 
				StationKind.BlastFurnace => AutoProduktionPlugin.HochofenRadius.Value, 
				StationKind.StoneOven => AutoProduktionPlugin.SteinofenRadius.Value, 
				_ => AutoProduktionPlugin.SchmelzofenRadius.Value, 
			};
		}

		private static Color GetColor(StationKind kind)
		{
			//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_002a: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0071: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(kind switch
			{
				StationKind.Kiln => ParseColor(AutoProduktionPlugin.KohlenmeilerRadiusFarbe.Value, Color.white), 
				StationKind.BlastFurnace => ParseColor(AutoProduktionPlugin.HochofenRadiusFarbe.Value, new Color(1f, 0.55f, 0f)), 
				StationKind.StoneOven => ParseColor(AutoProduktionPlugin.SteinofenRadiusFarbe.Value, new Color(0f, 0.75f, 1f)), 
				_ => ParseColor(AutoProduktionPlugin.SchmelzofenRadiusFarbe.Value, Color.red), 
			});
		}

		private static Color ParseColor(string configured, Color fallback)
		{
			//IL_0035: 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)
			string text = (configured ?? string.Empty).Trim();
			if (!text.StartsWith("#"))
			{
				text = "#" + text;
			}
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(text, ref result))
			{
				return fallback;
			}
			return result;
		}

		private static string GetName(StationKind kind)
		{
			return kind switch
			{
				StationKind.Kiln => "Kohlenmeiler", 
				StationKind.BlastFurnace => "Hochofen", 
				StationKind.StoneOven => "Steinofen", 
				_ => "Schmelzofen", 
			};
		}

		private static void Recolor(GameObject marker, Color color)
		{
			//IL_002d: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)marker == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = marker.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] materials = componentsInChildren[i].materials;
				foreach (Material val in materials)
				{
					val.color = color;
					if (val.HasProperty("_Color"))
					{
						val.SetColor("_Color", color);
					}
					if (val.HasProperty("_BaseColor"))
					{
						val.SetColor("_BaseColor", color);
					}
					if (val.HasProperty("_TintColor"))
					{
						val.SetColor("_TintColor", color);
					}
					if (val.HasProperty("_EmissionColor"))
					{
						val.SetColor("_EmissionColor", color);
					}
				}
			}
			ParticleSystem[] componentsInChildren2 = marker.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				MainModule main = componentsInChildren2[i].main;
				((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color);
			}
			Light[] componentsInChildren3 = marker.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				componentsInChildren3[i].color = color;
			}
		}
	}
	internal static class RadiusHotkeys
	{
		internal static KeyboardShortcut Default(KeyCode functionKey)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return new KeyboardShortcut(functionKey, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 });
		}

		internal static bool IsDown(KeyboardShortcut shortcut)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected I4, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !UnityInput.Current.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey))
			{
				return false;
			}
			if (((KeyboardShortcut)(ref shortcut)).IsDown())
			{
				return true;
			}
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 304 || (int)((KeyboardShortcut)(ref shortcut)).MainKey == 303)
			{
				return false;
			}
			KeyCode[] array = ((KeyboardShortcut)(ref shortcut)).Modifiers.ToArray();
			bool flag = array.Contains((KeyCode)304);
			bool flag2 = array.Contains((KeyCode)303);
			if (flag == flag2)
			{
				return false;
			}
			KeyCode configuredShift = (KeyCode)(flag ? 304 : 303);
			KeyCode otherShift = (KeyCode)(flag ? 303 : 304);
			KeyCode[] array2 = array.Select((KeyCode key) => (key != configuredShift) ? key : otherShift).ToArray();
			KeyboardShortcut val = new KeyboardShortcut(((KeyboardShortcut)(ref shortcut)).MainKey, array2);
			if (!((KeyboardShortcut)(ref val)).IsDown())
			{
				val = new KeyboardShortcut(((KeyboardShortcut)(ref shortcut)).MainKey, array.Concat((IEnumerable<KeyCode>)(object)new KeyCode[1] { (KeyCode)(int)otherShift }).ToArray());
				return ((KeyboardShortcut)(ref val)).IsDown();
			}
			return true;
		}

		internal static int MigrateLegacyDefaults(ConfigFile config, ConfigEntry<KeyboardShortcut> smelter, ConfigEntry<KeyboardShortcut> kiln, ConfigEntry<KeyboardShortcut> blastFurnace, ConfigEntry<KeyboardShortcut> stoneOven)
		{
			ConfigEntry<int> val = config.Bind<int>("Intern", "HotkeySchemaVersion", 0, "Interne einmalige Umstellung der alten Standardtasten. Nicht manuell aendern.");
			if (val.Value >= 1)
			{
				return 0;
			}
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			int result;
			try
			{
				result = MigrateEntry(smelter, (KeyCode)289, (KeyCode)282) + MigrateEntry(kiln, (KeyCode)290, (KeyCode)283) + MigrateEntry(blastFurnace, (KeyCode)291, (KeyCode)284) + MigrateEntry(stoneOven, (KeyCode)292, (KeyCode)285);
				val.Value = 1;
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
			config.Save();
			return result;
		}

		private static int MigrateEntry(ConfigEntry<KeyboardShortcut> entry, KeyCode previous, KeyCode next)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_000f: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!((object)entry.Value/*cast due to .constrained prefix*/).Equals((object)new KeyboardShortcut(previous, Array.Empty<KeyCode>())))
			{
				return 0;
			}
			entry.Value = Default(next);
			return 1;
		}
	}
	internal static class SmelterFinder
	{
		internal static List<Smelter> FindAll()
		{
			return Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0).Where(IsNormalSmelter).ToList();
		}

		internal static List<Smelter> FindAllKilns()
		{
			return Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0).Where(IsCharcoalKiln).ToList();
		}

		internal static List<Smelter> FindAllBlastFurnaces()
		{
			return Object.FindObjectsByType<Smelter>((FindObjectsSortMode)0).Where(IsBlastFurnace).ToList();
		}

		internal static List<CookingStation> FindAllStoneOvens()
		{
			return Object.FindObjectsByType<CookingStation>((FindObjectsSortMode)0).Where(IsStoneOven).ToList();
		}

		internal static bool IsNormalSmelter(Smelter station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return false;
			}
			return string.Equals(CleanName(((Object)((Component)station).gameObject).name), "smelter", StringComparison.OrdinalIgnoreCase);
		}

		internal static bool IsCharcoalKiln(Smelter station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return false;
			}
			return string.Equals(CleanName(((Object)((Component)station).gameObject).name), "charcoal_kiln", StringComparison.OrdinalIgnoreCase);
		}

		internal static bool IsBlastFurnace(Smelter station)
		{
			if ((Object)(object)station != (Object)null)
			{
				return HasPrefabName(((Component)station).transform, "blastfurnace", "blast_furnace");
			}
			return false;
		}

		internal static bool IsStoneOven(CookingStation station)
		{
			if ((Object)(object)station != (Object)null)
			{
				return HasPrefabName(((Component)station).transform, "piece_oven");
			}
			return false;
		}

		private static bool HasPrefabName(Transform start, params string[] acceptedNames)
		{
			Transform val = start;
			while ((Object)(object)val != (Object)null)
			{
				string currentName = CleanName(((Object)((Component)val).gameObject).name);
				if (acceptedNames.Any((string name) => string.Equals(currentName, name, StringComparison.OrdinalIgnoreCase)))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		internal static string CleanName(string name)
		{
			return (name ?? string.Empty).Replace("(Clone)", string.Empty).Trim();
		}

		internal static float HorizontalDistance(Vector3 a, Vector3 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			float num = a.x - b.x;
			float num2 = a.z - b.z;
			return Mathf.Sqrt(num * num + num2 * num2);
		}
	}
	internal static class StoneOvenCollector
	{
		private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly FieldInfo NetworkViewField = typeof(CookingStation).GetField("m_nview", PrivateInstance);

		private static readonly MethodInfo GetFuelMethod = typeof(CookingStation).GetMethod("GetFuel", PrivateInstance);

		internal static void Scan()
		{
			float radius = Mathf.Clamp(AutoProduktionPlugin.SteinofenRadius.Value, 2f, 50f);
			List<CookingStation> list = SmelterFinder.FindAllStoneOvens();
			if (list.Count == 0)
			{
				return;
			}
			ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
			foreach (ItemDrop item in array)
			{
				if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0 || !EnsureItemOwnership(item))
				{
					continue;
				}
				foreach (CookingStation item2 in (from station in list
					where SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)station).transform.position) <= radius
					orderby SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)station).transform.position)
					select station).ToList())
				{
					int num;
					string arg;
					if (item2.m_useFuel && Matches(item2.m_fuelItem, item))
					{
						num = InsertFuel(item2, item.m_itemData.m_stack);
						arg = "Holz";
					}
					else
					{
						string text = FindAcceptedInput(item2, item);
						if (text == null)
						{
							continue;
						}
						num = InsertFood(item2, text, item.m_itemData.m_stack);
						arg = text;
					}
					if (num > 0)
					{
						AutoProduktionPlugin.LogDiagnostic($"{num}x {arg} vom Boden in Steinofen eingefuellt.");
						RemoveFromGround(item, num);
						if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0)
						{
							break;
						}
					}
				}
			}
		}

		private static string? FindAcceptedInput(CookingStation oven, ItemDrop item)
		{
			if (oven.m_conversion == null)
			{
				return null;
			}
			foreach (ItemConversion item2 in oven.m_conversion)
			{
				if ((Object)(object)item2?.m_from != (Object)null && Matches(item2.m_from, item))
				{
					return SmelterFinder.CleanName(((Object)((Component)item2.m_from).gameObject).name);
				}
			}
			return null;
		}

		private static bool Matches(ItemDrop accepted, ItemDrop groundItem)
		{
			if ((Object)(object)accepted == (Object)null || accepted.m_itemData == null || (Object)(object)groundItem == (Object)null || groundItem.m_itemData == null)
			{
				return false;
			}
			GameObject dropPrefab = groundItem.m_itemData.m_dropPrefab;
			string a = SmelterFinder.CleanName(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? ((Object)((Component)groundItem).gameObject).name);
			string b = SmelterFinder.CleanName(((Object)((Component)accepted).gameObject).name);
			string a2 = groundItem.m_itemData.m_shared?.m_name ?? string.Empty;
			string b2 = accepted.m_itemData.m_shared?.m_name ?? string.Empty;
			if (!string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(a2, b2, StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static int InsertFuel(CookingStation oven, int available)
		{
			ZNetView networkView = GetNetworkView(oven);
			if (available <= 0 || (Object)(object)networkView == (Object)null || oven.m_maxFuel <= 0)
			{
				return 0;
			}
			float num = (float)(GetFuelMethod.Invoke(oven, null) ?? ((object)0f));
			int val = Math.Max(0, oven.m_maxFuel - Mathf.CeilToInt(num));
			int num2 = Math.Min(available, val);
			for (int i = 0; i < num2; i++)
			{
				networkView.InvokeRPC("RPC_AddFuel", Array.Empty<object>());
			}
			return num2;
		}

		private static int InsertFood(CookingStation oven, string prefabName, int available)
		{
			ZNetView networkView = GetNetworkView(oven);
			if (available <= 0 || (Object)(object)networkView == (Object)null || oven.m_slots == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < oven.m_slots.Length; i++)
			{
				if (string.IsNullOrEmpty(networkView.GetZDO().GetString("slot" + i, "")))
				{
					num++;
				}
			}
			int num2 = Math.Min(available, num);
			for (int j = 0; j < num2; j++)
			{
				networkView.InvokeRPC("RPC_AddItem", new object[1] { prefabName });
			}
			return num2;
		}

		private static ZNetView? GetNetworkView(CookingStation oven)
		{
			object? value = NetworkViewField.GetValue(oven);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return null;
			}
			return val;
		}

		private static bool EnsureItemOwnership(ItemDrop item)
		{
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			return component.IsOwner();
		}

		private static void RemoveFromGround(ItemDrop item, int amount)
		{
			for (int i = 0; i < amount; i++)
			{
				if (!((Object)(object)item != (Object)null))
				{
					break;
				}
				if (item.m_itemData.m_stack <= 0)
				{
					break;
				}
				item.RemoveOne();
			}
		}
	}
	internal static class WoodCollector
	{
		private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly FieldInfo NetworkViewField = typeof(Smelter).GetField("m_nview", PrivateInstance);

		private static readonly MethodInfo GetQueueSizeMethod = typeof(Smelter).GetMethod("GetQueueSize", PrivateInstance);

		private static readonly MethodInfo QueueOreMethod = typeof(Smelter).GetMethod("QueueOre", PrivateInstance);

		internal static void Scan()
		{
			float radius = Mathf.Clamp(AutoProduktionPlugin.KohlenmeilerRadius.Value, 2f, 50f);
			List<Smelter> list = SmelterFinder.FindAllKilns();
			if (list.Count == 0)
			{
				return;
			}
			ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
			foreach (ItemDrop item in array)
			{
				if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0 || !EnsureItemOwnership(item))
				{
					continue;
				}
				foreach (Smelter item2 in (from station in list
					where SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)station).transform.position) <= radius
					orderby SmelterFinder.HorizontalDistance(((Component)item).transform.position, ((Component)station).transform.position)
					select station).ToList())
				{
					string text = FindAcceptedInput(item2, item);
					if (text == null)
					{
						continue;
					}
					int num = InsertWood(item2, text, item.m_itemData.m_stack);
					if (num > 0)
					{
						AutoProduktionPlugin.LogDiagnostic($"{num}x {text} vom Boden in Kohlenmeiler eingefuellt.");
						RemoveFromGround(item, num);
						if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_stack <= 0)
						{
							break;
						}
					}
				}
			}
		}

		private static string? FindAcceptedInput(Smelter kiln, ItemDrop item)
		{
			if (kiln.m_conversion == null)
			{
				return null;
			}
			GameObject dropPrefab = item.m_itemData.m_dropPrefab;
			string a = SmelterFinder.CleanName(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? ((Object)((Component)item).gameObject).name);
			string a2 = item.m_itemData.m_shared?.m_name ?? string.Empty;
			foreach (ItemConversion item2 in kiln.m_conversion)
			{
				if (!((Object)(object)item2?.m_from == (Object)null))
				{
					string text = SmelterFinder.CleanName(((Object)((Component)item2.m_from).gameObject).name);
					string b = item2.m_from.m_itemData?.m_shared?.m_name ?? string.Empty;
					if (string.Equals(a, text, StringComparison.OrdinalIgnoreCase) || string.Equals(a2, b, StringComparison.OrdinalIgnoreCase))
					{
						return text;
					}
				}
			}
			return null;
		}

		private static int InsertWood(Smelter kiln, string prefabName, int available)
		{
			if (available <= 0 || !EnsureKilnOwnership(kiln))
			{
				return 0;
			}
			int num = (int)(GetQueueSizeMethod.Invoke(kiln, null) ?? ((object)0));
			int val = Math.Max(0, kiln.m_maxOre - num);
			int num2 = Math.Min(available, val);
			for (int i = 0; i < num2; i++)
			{
				QueueOreMethod.Invoke(kiln, new object[1] { prefabName });
			}
			return num2;
		}

		private static bool EnsureItemOwnership(ItemDrop item)
		{
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return true;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			return component.IsOwner();
		}

		private static bool EnsureKilnOwnership(Smelter kiln)
		{
			object? value = NetworkViewField.GetValue(kiln);
			ZNetView val = (ZNetView)((value is ZNetView) ? value : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return false;
			}
			if (!val.IsOwner())
			{
				val.ClaimOwnership();
			}
			return val.IsOwner();
		}

		private static void RemoveFromGround(ItemDrop item, int amount)
		{
			for (int i = 0; i < amount; i++)
			{
				if (!((Object)(object)item != (Object)null))
				{
					break;
				}
				if (item.m_itemData.m_stack <= 0)
				{
					break;
				}
				item.RemoveOne();
			}
		}
	}
}