Decompiled source of Kvist v0.4.1

plugins/Kvist/GreydwarfSorter.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GreydwarfSorter.Categories;
using GreydwarfSorter.Chests;
using GreydwarfSorter.Farming;
using GreydwarfSorter.Pieces;
using GreydwarfSorter.Smelting;
using GreydwarfSorter.Tools;
using GreydwarfSorter.Upkeep;
using GreydwarfSorter.Worker;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.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 GreydwarfSorter
{
	internal static class Keys
	{
		public static readonly int RespawnAt = StringExtensionMethods.GetStableHashCode("gs_respawn_at");

		public static readonly int Carry = StringExtensionMethods.GetStableHashCode("gs_carry");

		public static readonly int State = StringExtensionMethods.GetStableHashCode("gs_state");

		public static readonly int Label = StringExtensionMethods.GetStableHashCode("gs_label");

		public static readonly int Mode = StringExtensionMethods.GetStableHashCode("gs_mode");

		public static readonly int Butcher = StringExtensionMethods.GetStableHashCode("gs_butcher");

		public static readonly int ButcherKinds = StringExtensionMethods.GetStableHashCode("gs_butcher_kinds");

		public static readonly int WorkerName = StringExtensionMethods.GetStableHashCode("gs_worker_name");

		public static readonly int Problem = StringExtensionMethods.GetStableHashCode("gs_problem");

		public static readonly int ProblemAt = StringExtensionMethods.GetStableHashCode("gs_problem_at");

		public static readonly int StatDay = StringExtensionMethods.GetStableHashCode("gs_stat_day");

		public static readonly int[] Stats = new int[5]
		{
			StringExtensionMethods.GetStableHashCode("gs_stat_sorted"),
			StringExtensionMethods.GetStableHashCode("gs_stat_fed"),
			StringExtensionMethods.GetStableHashCode("gs_stat_harvested"),
			StringExtensionMethods.GetStableHashCode("gs_stat_planted"),
			StringExtensionMethods.GetStableHashCode("gs_stat_butchered")
		};

		public static readonly int NestId = StringExtensionMethods.GetStableHashCode("gs_nest_id");

		public static ZDOID GetLink(ZDO zdo)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null)
			{
				return zdo.GetConnectionZDOID((ConnectionType)3);
			}
			return ZDOID.None;
		}

		public static void SetLink(ZDO zdo, ZDOID target)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			zdo.SetConnection((ConnectionType)3, target);
		}
	}
	internal static class ModConfig
	{
		public static ConfigEntry<float> WorkRadius;

		public static ConfigEntry<int> CarryStacks;

		public static ConfigEntry<float> RespawnSeconds;

		public static ConfigEntry<float> AITickSeconds;

		public static ConfigEntry<float> IdleSeconds;

		public static ConfigEntry<float> DepositSeconds;

		public static ConfigEntry<float> StuckSeconds;

		public static ConfigEntry<float> ArriveDistance;

		public static ConfigEntry<KeyCode> LabelKey;

		public static ConfigEntry<bool> AreaFallback;

		public static ConfigEntry<int> CollectBatch;

		public static ConfigEntry<bool> Run;

		public static ConfigEntry<bool> NestSound;

		public static ConfigEntry<bool> Butchering;

		public static ConfigEntry<int> Breeders;

		public static ConfigEntry<int> ChickenFlock;

		public static ConfigEntry<int> ChickenCullAbove;

		public static ConfigEntry<int> SeedReserve;

		public static ConfigEntry<bool> SmartPriorities;

		public static ConfigEntry<bool> TeleportWhenStuck;

		public static ConfigEntry<bool> ReachWhenBlocked;

		public static ConfigEntry<float> ReachDistance;

		public static ConfigEntry<bool> ShowOnMap;

		public static ConfigEntry<KeyCode> TasksKey;

		public static void Bind(ConfigFile cfg)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Expected O, but got Unknown
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Expected O, but got Unknown
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Expected O, but got Unknown
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Expected O, but got Unknown
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			WorkRadius = cfg.Bind<float>("Worker", "WorkRadius", 50f, new ConfigDescription("Metres from the station a chest can be and still be sorted into.", (AcceptableValueBase)null, new object[1] { val }));
			CarryStacks = cfg.Bind<int>("Worker", "CarrySlots", 10, new ConfigDescription("Stacks the dwarf carries per trip.", (AcceptableValueBase)null, new object[1] { val }));
			RespawnSeconds = cfg.Bind<float>("Worker", "RespawnSeconds", 120f, new ConfigDescription("Seconds after death before the station spawns a new dwarf.", (AcceptableValueBase)null, new object[1] { val }));
			AITickSeconds = cfg.Bind<float>("Worker", "AITickSeconds", 0.5f, new ConfigDescription("Seconds between AI decisions.", (AcceptableValueBase)null, new object[1] { val }));
			IdleSeconds = cfg.Bind<float>("Worker", "IdleSeconds", 1f, new ConfigDescription("Seconds the dwarf waits when there is nothing to do.", (AcceptableValueBase)null, new object[1] { val }));
			DepositSeconds = cfg.Bind<float>("Worker", "DepositSeconds", 1f, new ConfigDescription("Pause after each deposit.", (AcceptableValueBase)null, new object[1] { val }));
			StuckSeconds = cfg.Bind<float>("Worker", "StuckSeconds", 8f, new ConfigDescription("Seconds without progress before a target is given up.", (AcceptableValueBase)null, new object[1] { val }));
			ArriveDistance = cfg.Bind<float>("Worker", "ArriveDistance", 2f, new ConfigDescription("Metres from a target that counts as arrived.", (AcceptableValueBase)null, new object[1] { val }));
			AreaFallback = cfg.Bind<bool>("Worker", "UseAreaFallback", false, new ConfigDescription("When no chest of an item's category has room, use another chest in the same Area (Forge, Kitchen...). Off: the item waits in the nest and the nest says which chest is missing.", (AcceptableValueBase)null, new object[1] { val }));
			Run = cfg.Bind<bool>("Worker", "Run", true, new ConfigDescription("Kvist runs everywhere, idle wandering included, instead of walking.", (AcceptableValueBase)null, new object[1] { val }));
			SmartPriorities = cfg.Bind<bool>("Worker", "SmartPriorities", true, new ConfigDescription("Kvist picks the job worth most for the walk (big jobs and near jobs first, deliveries when his hands are full). Off: the fixed priority order from 0.2.", (AcceptableValueBase)null, new object[1] { val }));
			TeleportWhenStuck = cfg.Bind<bool>("Worker", "TeleportWhenStuck", true, new ConfigDescription("When Kvist can't get to something (no path, no door that leads there, too far to reach over), he teleports beside it in a puff, and home the same way if he's trapped. Off: he skips it and tries again later, and jumps to get out of traps.", (AcceptableValueBase)null, new object[1] { val }));
			ReachWhenBlocked = cfg.Bind<bool>("Worker", "ReachWhenBlocked", true, new ConfigDescription("The last resort when Kvist can't get to something (after doors, gates and teleporting): if it's within ReachDistance, he does the job from where he stands.", (AcceptableValueBase)null, new object[1] { val }));
			ReachDistance = cfg.Bind<float>("Worker", "ReachDistance", 8f, new ConfigDescription("Metres Kvist can reach from where he stands when blocked (ReachWhenBlocked).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), new object[1] { val }));
			CollectBatch = cfg.Bind<int>("Smelting", "CollectBatch", 20, new ConfigDescription("Smelting mode: wait for a pile of charcoal or bars this big before fetching it, unless the kiln or furnace has finished or a furnace is out of coal.", (AcceptableValueBase)null, new object[1] { val }));
			Butchering = cfg.Bind<bool>("Animals", "Butchering", true, new ConfigDescription("Animal Husbandry mode: master switch for butchering. Each species also has to be chosen: look at one of your animals and press Shift+L (nothing is butchered until you do). Off: Kvist only feeds animals. Named animals and saddled mounts are never butchered.", (AcceptableValueBase)null, new object[1] { val }));
			Breeders = cfg.Bind<int>("Animals", "Breeders", 2, new ConfigDescription("Animal Husbandry mode: adults of each kind kept as breeders (the highest-starred). Other adults are butchered. Not used for chickens.", (AcceptableValueBase)null, new object[1] { val }));
			ChickenFlock = cfg.Bind<int>("Animals", "ChickenFlock", 6, new ConfigDescription("Hens + chicks to keep. Below this, Kvist leaves all eggs alone so they can hatch (vanilla: by a fire, under a roof); at or above it, he collects them in Upkeep mode.", (AcceptableValueBase)null, new object[1] { val }));
			ChickenCullAbove = cfg.Bind<int>("Animals", "ChickenCullAbove", 8, new ConfigDescription("Animal Husbandry mode: when adult hens exceed this, Kvist butchers down to ChickenFlock, keeping the highest-starred.", (AcceptableValueBase)null, new object[1] { val }));
			SeedReserve = cfg.Bind<int>("Animals", "SeedReserve", 20, new ConfigDescription("Of anything Kvist plants with (seeds, barley, flax...), keep at least this many in the nest and chests for planting. Animals are only fed what's above it.", (AcceptableValueBase)null, new object[1] { val }));
			ShowOnMap = cfg.Bind<bool>("Map", "ShowOnMap", true, "Show a pin for every Kvist on the map and minimap, named after his job.");
			NestSound = cfg.Bind<bool>("Nest", "NestSound", false, "Play the nest's ambient sound (the greydwarf nest loop). Takes effect immediately.");
			LabelKey = cfg.Bind<KeyCode>("Input", "LabelKey", (KeyCode)108, "Hover a chest and press to cycle its label. Hold Shift to cycle backwards.");
			TasksKey = cfg.Bind<KeyCode>("Input", "TasksKey", (KeyCode)107, "Look at a nest and press to set its Kvist's task priorities.");
		}
	}
	[BepInPlugin("com.ryan.greydwarfsorter", "Kvist", "0.4.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.ryan.greydwarfsorter";

		public const string ModName = "Kvist";

		public const string ModVersion = "0.4.1";

		internal static ManualLogSource Log;

		private readonly Harmony _harmony = new Harmony("com.ryan.greydwarfsorter");

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			CategoryRegistry.Load();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DumpItemsCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FillCarryCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new KillKvistCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClassifyCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ClassifyAllCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DebugCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new StressCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FiresCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SoilCommand());
			((Component)this).gameObject.AddComponent<LabelInput>();
			((Component)this).gameObject.AddComponent<DebugOverlay>();
			((Component)this).gameObject.AddComponent<MapPins>();
			((Component)this).gameObject.AddComponent<TaskWindow>();
			_harmony.PatchAll();
			Log.LogInfo((object)"Kvist 0.4.1 loaded");
		}

		private void OnVanillaPrefabsAvailable()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			StationRegistration.Register();
			WorkerRegistration.Register();
		}
	}
}
namespace GreydwarfSorter.Tools
{
	internal class ClassifyCommand : ConsoleCommand
	{
		public override string Name => "gs_classify";

		public override string Help => "gs_classify <prefab> - show the category an item sorts into";

		public override void Run(string[] args)
		{
			if (args.Length == 0)
			{
				Console.instance.Print("usage: gs_classify <prefab>");
				return;
			}
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(args[0]) : null);
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Console.instance.Print("gs_classify: no item prefab '" + args[0] + "'");
				return;
			}
			ItemData obj = val2.m_itemData.Clone();
			obj.m_dropPrefab = val;
			string via;
			Category category = ItemClassifier.Classify(obj, out via);
			Console.instance.Print(((Object)val).name + " -> " + category.Name + " (" + category.Id + ", " + via + ")");
		}
	}
	internal class ClassifyAllCommand : ConsoleCommand
	{
		public override string Name => "gs_classify_all";

		public override string Help => "Reload categories.yaml and write every item's category to classified.csv";

		public override void Run(string[] args)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || ObjectDB.instance.m_items.Count == 0)
			{
				Console.instance.Print("gs_classify_all: ObjectDB not loaded, run this in a world");
				return;
			}
			CategoryRegistry.Load();
			List<GameObject> list = (from go in ObjectDB.instance.m_items
				where Object.op_Implicit((Object)(object)go) && Object.op_Implicit((Object)(object)go.GetComponent<ItemDrop>())
				orderby ((Object)go).name
				select go).ToList();
			StringBuilder stringBuilder = new StringBuilder("prefab,name,itemType,category,via\n");
			int num = 0;
			foreach (GameObject item in list)
			{
				ItemData val = item.GetComponent<ItemDrop>().m_itemData.Clone();
				val.m_dropPrefab = item;
				string via;
				Category category = ItemClassifier.Classify(val, out via);
				if (category.Id == "incoming_loot")
				{
					num++;
				}
				stringBuilder.Append(((Object)item).name).Append(',').Append(Csv(Localization.instance.Localize(val.m_shared.m_name)))
					.Append(',')
					.Append(val.m_shared.m_itemType)
					.Append(',')
					.Append(category.Id)
					.Append(',')
					.Append(via)
					.Append('\n');
			}
			List<string> names = list.Select((GameObject p) => ((Object)p).name).ToList();
			var list2 = (from x in CategoryRegistry.All.SelectMany((Category c) => c.Items.Select((string i) => new
				{
					Id = c.Id,
					Entry = i
				}))
				where !names.Any((string n) => new Category("", "", "")
				{
					Items = { x.Entry }
				}.ListMatches(n))
				select x).ToList();
			stringBuilder.Append("\n# yaml entries matching no item\n");
			foreach (var item2 in list2)
			{
				stringBuilder.Append("# ").Append(item2.Id).Append(": ")
					.Append(item2.Entry)
					.Append('\n');
			}
			string text = Path.Combine(Path.Combine(Paths.ConfigPath, "GreydwarfSorter"), "classified.csv");
			File.WriteAllText(text, stringBuilder.ToString());
			Console.instance.Print($"gs_classify_all: {list.Count} items, {num} to Incoming Loot, " + $"{list2.Count} yaml names match nothing -> {text}");
		}

		private static string Csv(string v)
		{
			if (v.IndexOfAny(new char[3] { ',', '"', '\n' }) >= 0)
			{
				return "\"" + v.Replace("\"", "\"\"") + "\"";
			}
			return v;
		}
	}
	public class DebugOverlay : MonoBehaviour
	{
		public static bool Enabled;

		private const float Range = 40f;

		private SorterAI[] _workers = new SorterAI[0];

		private float _nextScan;

		private GUIStyle _style;

		private void Update()
		{
			if (Enabled && !(Time.time < _nextScan))
			{
				_nextScan = Time.time + 1f;
				_workers = Object.FindObjectsByType<SorterAI>((FindObjectsSortMode)0);
			}
		}

		private void OnGUI()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00d5: 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)
			//IL_00dc: 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_0104: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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)
			if (!Enabled || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)Camera.main))
			{
				return;
			}
			if (_style == null)
			{
				_style = new GUIStyle(GUI.skin.box)
				{
					alignment = (TextAnchor)0,
					fontSize = 13,
					richText = true
				};
			}
			SorterAI[] workers = _workers;
			foreach (SorterAI sorterAI in workers)
			{
				if (!Object.op_Implicit((Object)(object)sorterAI) || !Object.op_Implicit((Object)(object)((BaseAI)sorterAI).m_nview) || !((BaseAI)sorterAI).m_nview.IsValid())
				{
					continue;
				}
				Vector3 val = ((Component)sorterAI).transform.position + Vector3.up * 2.4f;
				if (!(Vector3.Distance(val, ((Component)Player.m_localPlayer).transform.position) > 40f))
				{
					Vector3 val2 = Camera.main.WorldToScreenPoint(val);
					if (!(val2.z <= 0f))
					{
						string text = Describe(sorterAI);
						Vector2 val3 = _style.CalcSize(new GUIContent(text));
						GUI.Box(new Rect(val2.x - val3.x / 2f, (float)Screen.height - val2.y - val3.y, val3.x, val3.y), text, _style);
					}
				}
			}
		}

		private static string Describe(SorterAI ai)
		{
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			ZDO zDO = ((BaseAI)ai).m_nview.GetZDO();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<b>Kvist</b>  ").Append((SorterAI.State)zDO.GetInt(Keys.State, 0));
			if (((BaseAI)ai).m_nview.IsOwner())
			{
				if (Object.op_Implicit((Object)(object)ai.Target))
				{
					stringBuilder.Append(" → ").Append(Localization.instance.Localize(ai.Target.m_name)).Append(" [")
						.Append(CategoryRegistry.DisplayName(ChestLabel.Get(ai.Target)))
						.Append(']');
				}
				else if (Object.op_Implicit((Object)(object)ai.SmelterTarget))
				{
					stringBuilder.Append(" → ").Append(Localization.instance.Localize(ai.SmelterTarget.m_name));
				}
				else if (Object.op_Implicit((Object)(object)ai.UpkeepTarget))
				{
					stringBuilder.Append(" → ").Append(Utils.GetPrefabName(ai.UpkeepTarget.gameObject));
				}
				else if (Object.op_Implicit((Object)(object)ai.CropTarget))
				{
					stringBuilder.Append(" → ").Append(Utils.GetPrefabName(((Component)ai.CropTarget).gameObject));
				}
				else if (Object.op_Implicit((Object)(object)ai.AnimalTarget))
				{
					stringBuilder.Append(" → ").Append(Utils.GetPrefabName(((Component)ai.AnimalTarget).gameObject));
				}
			}
			else
			{
				stringBuilder.Append("  (owned by another player)");
			}
			GameObject val = ZNetScene.instance.FindInstance(ai.StationId);
			SorterStation sorterStation = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<SorterStation>() : null);
			if (Object.op_Implicit((Object)(object)sorterStation))
			{
				stringBuilder.Append("\nMode: ").Append(SorterStation.ModeName(sorterStation.CurrentMode));
			}
			Inventory val2 = new Inventory("debug", (Sprite)null, Mathf.Max(1, ModConfig.CarryStacks.Value), 1);
			string text = zDO.GetString(Keys.Carry, "");
			if (!string.IsNullOrEmpty(text))
			{
				val2.Load(new ZPackage(text));
			}
			List<ItemData> allItems = val2.GetAllItems();
			stringBuilder.Append("\nCarry: ").Append((allItems.Count == 0) ? "empty" : string.Join(", ", allItems.Select((ItemData i) => $"{i.m_stack} {Localization.instance.Localize(i.m_shared.m_name)}")));
			return stringBuilder.ToString();
		}
	}
	internal class DebugCommand : ConsoleCommand
	{
		public override string Name => "gs_debug";

		public override string Help => "Toggle the Kvist overlay (state, target, mode, carry)";

		public override void Run(string[] args)
		{
			DebugOverlay.Enabled = !DebugOverlay.Enabled;
			Console.instance.Print("gs_debug: overlay " + (DebugOverlay.Enabled ? "on" : "off"));
		}
	}
	internal class DumpItemsCommand : ConsoleCommand
	{
		public override string Name => "gs_dumpitems";

		public override string Help => "Write every item prefab to BepInEx/config/GreydwarfSorter/items.csv";

		public override void Run(string[] args)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || ObjectDB.instance.m_items.Count == 0)
			{
				Console.instance.Print("gs_dumpitems: ObjectDB not loaded, run this in a world");
				return;
			}
			StringBuilder stringBuilder = new StringBuilder("prefab,name,itemType,food,stamina,eitr,hasStatusEffect\n");
			IOrderedEnumerable<GameObject> orderedEnumerable = from go in ObjectDB.instance.m_items
				where Object.op_Implicit((Object)(object)go) && Object.op_Implicit((Object)(object)go.GetComponent<ItemDrop>())
				orderby ((Object)go).name
				select go;
			int num = 0;
			foreach (GameObject item in orderedEnumerable)
			{
				SharedData shared = item.GetComponent<ItemDrop>().m_itemData.m_shared;
				stringBuilder.Append(Csv(((Object)item).name)).Append(',').Append(Csv(Localization.instance.Localize(shared.m_name)))
					.Append(',')
					.Append(shared.m_itemType)
					.Append(',')
					.Append(shared.m_food.ToString(CultureInfo.InvariantCulture))
					.Append(',')
					.Append(shared.m_foodStamina.ToString(CultureInfo.InvariantCulture))
					.Append(',')
					.Append(shared.m_foodEitr.ToString(CultureInfo.InvariantCulture))
					.Append(',')
					.Append((Object)(object)shared.m_consumeStatusEffect != (Object)null)
					.Append('\n');
				num++;
			}
			string text = Path.Combine(Paths.ConfigPath, "GreydwarfSorter");
			Directory.CreateDirectory(text);
			string text2 = Path.Combine(text, "items.csv");
			File.WriteAllText(text2, stringBuilder.ToString());
			Console.instance.Print($"gs_dumpitems: {num} items -> {text2}");
		}

		private static string Csv(string v)
		{
			if (v.IndexOfAny(new char[3] { ',', '"', '\n' }) >= 0)
			{
				return "\"" + v.Replace("\"", "\"\"") + "\"";
			}
			return v;
		}
	}
	internal class FillCarryCommand : ConsoleCommand
	{
		private static readonly string[] Prefabs = new string[5] { "Wood", "Stone", "Resin", "Flint", "RawMeat" };

		public override string Name => "gs_fillcarry";

		public override string Help => "Fill the nearest Kvist's carry with test stacks";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Player player = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			WorkerCarry workerCarry = (from c in Object.FindObjectsByType<WorkerCarry>((FindObjectsSortMode)0)
				orderby Vector3.Distance(((Component)c).transform.position, ((Component)player).transform.position)
				select c).FirstOrDefault();
			if (!Object.op_Implicit((Object)(object)workerCarry) || Vector3.Distance(((Component)workerCarry).transform.position, ((Component)player).transform.position) > 30f)
			{
				Console.instance.Print("gs_fillcarry: no Kvist within 30 m");
				return;
			}
			if (!((Component)workerCarry).GetComponent<ZNetView>().IsOwner())
			{
				Console.instance.Print("gs_fillcarry: another client owns this Kvist");
				return;
			}
			foreach (string item in Prefabs.Take(workerCarry.Inventory.GetWidth()))
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item);
				if (Object.op_Implicit((Object)(object)itemPrefab))
				{
					ItemData val = itemPrefab.GetComponent<ItemDrop>().m_itemData.Clone();
					val.m_dropPrefab = itemPrefab;
					val.m_stack = val.m_shared.m_maxStackSize;
					workerCarry.Inventory.AddItem(val);
				}
			}
			workerCarry.Save();
			Console.instance.Print($"gs_fillcarry: Kvist carries {workerCarry.Inventory.NrOfItems()} stacks");
		}
	}
	internal class FiresCommand : ConsoleCommand
	{
		public override string Name => "gs_fires";

		public override string Help => "List fires within 30 m and whether Kvist (Upkeep) fuels them";

		public override void Run(string[] args)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			Vector3 at = ((Component)localPlayer).transform.position;
			List<Fireplace> list = (from val in Object.FindObjectsByType<Fireplace>((FindObjectsSortMode)0)
				where Vector3.Distance(((Component)val).transform.position, at) <= 30f
				orderby Vector3.Distance(((Component)val).transform.position, at)
				select val).ToList();
			if (list.Count == 0)
			{
				Console.instance.Print("gs_fires: no fires within 30 m");
				return;
			}
			foreach (Fireplace f in list)
			{
				Piece componentInParent = ((Component)f).GetComponentInParent<Piece>();
				string text = (Object.op_Implicit((Object)(object)componentInParent) ? Utils.GetPrefabName(((Component)componentInParent).gameObject) : Utils.GetPrefabName(((Component)f).gameObject));
				SorterStation sorterStation = (from s in SorterStation.All
					where Object.op_Implicit((Object)(object)s) && s.CurrentMode == SorterStation.Mode.Upkeep
					orderby Vector3.Distance(((Component)s).transform.position, ((Component)f).transform.position)
					select s).FirstOrDefault();
				string text2 = UpkeepIndex.WhyNot(f, Object.op_Implicit((Object)(object)sorterStation) ? new Vector3?(((Component)sorterStation).transform.position) : ((Vector3?)null));
				Console.instance.Print(text + ": " + ((text2 == null) ? $"fuelled ({UpkeepIndex.FuelPrefab(f)}, room {UpkeepIndex.FuelRoom(f)})" : ("not fuelled: " + text2)));
			}
		}
	}
	internal class KillKvistCommand : ConsoleCommand
	{
		public override string Name => "gs_killkvist";

		public override string Help => "Kill the nearest Kvist (tests death drop and respawn)";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0094: Expected O, but got Unknown
			Player player = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)player))
			{
				SorterAI sorterAI = (from a in Object.FindObjectsByType<SorterAI>((FindObjectsSortMode)0)
					orderby Vector3.Distance(((Component)a).transform.position, ((Component)player).transform.position)
					select a).FirstOrDefault();
				if (!Object.op_Implicit((Object)(object)sorterAI) || Vector3.Distance(((Component)sorterAI).transform.position, ((Component)player).transform.position) > 30f)
				{
					Console.instance.Print("gs_killkvist: no Kvist within 30 m");
					return;
				}
				Character component = ((Component)sorterAI).GetComponent<Character>();
				HitData val = new HitData
				{
					m_point = component.GetCenterPoint()
				};
				val.m_damage.m_damage = 1000000f;
				component.Damage(val);
				Console.instance.Print("gs_killkvist: done");
			}
		}
	}
	internal class SoilCommand : ConsoleCommand
	{
		public override string Name => "gs_soil";

		public override string Help => "Why crops can't be planted in the tilled soil around you";

		public override void Run(string[] args)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			Sapling sapling = CropBook.All.FirstOrDefault((Sapling s) => s.Name == "sapling_carrot") ?? CropBook.All.FirstOrDefault();
			if (sapling == null)
			{
				Console.instance.Print("gs_soil: no crops known");
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			int num = 0;
			int num2 = 0;
			Vector3 val = default(Vector3);
			for (float num3 = -4f; num3 <= 4f; num3 += 0.5f)
			{
				for (float num4 = -4f; num4 <= 4f; num4 += 0.5f)
				{
					((Vector3)(ref val))..ctor(position.x + num3, position.y, position.z + num4);
					if (FarmIndex.Cultivated(val))
					{
						val.y = ZoneSystem.instance.GetGroundHeight(val);
						num++;
						string text = FarmIndex.WhyNotHere(sapling, val);
						if (text == null)
						{
							num2++;
						}
						else
						{
							dictionary[text] = (dictionary.TryGetValue(text, out var value) ? value : 0) + 1;
						}
					}
				}
			}
			Console.instance.Print($"gs_soil: {num} tilled spots within 4 m, {num2} free for {sapling.Name} (grow radius {sapling.GrowRadius:0.00})");
			foreach (KeyValuePair<string, int> item in dictionary.OrderByDescending((KeyValuePair<string, int> kv) => kv.Value).Take(8))
			{
				Console.instance.Print($"  {item.Value}: {item.Key}");
			}
		}
	}
	internal class StressCommand : ConsoleCommand
	{
		public override string Name => "gs_stress";

		public override string Help => "Fill the nearest station with 50 mixed stacks and time Kvist emptying it";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			Player player = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			SorterStation sorterStation = (from s in Object.FindObjectsByType<SorterStation>((FindObjectsSortMode)0)
				orderby Vector3.Distance(((Component)s).transform.position, ((Component)player).transform.position)
				select s).FirstOrDefault();
			if (!Object.op_Implicit((Object)(object)sorterStation) || Vector3.Distance(((Component)sorterStation).transform.position, ((Component)player).transform.position) > 30f)
			{
				Console.instance.Print("gs_stress: no station within 30 m");
				return;
			}
			ZNetView component = ((Component)sorterStation).GetComponent<ZNetView>();
			if (!component.IsOwner())
			{
				Console.instance.Print("gs_stress: another client owns this station");
				return;
			}
			List<GameObject> list = (from n in CategoryRegistry.All.SelectMany((Category c) => c.Items)
				where !n.Contains("*")
				select ObjectDB.instance.GetItemPrefab(n) into p
				where Object.op_Implicit((Object)(object)p)
				select p).ToList();
			if (list.Count == 0)
			{
				Console.instance.Print("gs_stress: no items found");
				return;
			}
			Inventory inventory = sorterStation.Container.GetInventory();
			int num = 0;
			for (int num2 = 0; num2 < 50; num2++)
			{
				if (!inventory.HaveEmptySlot())
				{
					break;
				}
				GameObject val = list[Random.Range(0, list.Count)];
				ItemData val2 = val.GetComponent<ItemDrop>().m_itemData.Clone();
				val2.m_dropPrefab = val;
				val2.m_stack = val2.m_shared.m_maxStackSize;
				if (inventory.AddItem(val2))
				{
					num++;
				}
			}
			StressRun.Start(component.GetZDO().m_uid, inventory.NrOfItems());
			Console.instance.Print($"gs_stress: added {num} stacks; station holds {inventory.NrOfItems()}. Timing started.");
		}
	}
	public static class StressRun
	{
		private class Run
		{
			public float Start;

			public int Stacks;

			public int LastCount;

			public float LastChange;
		}

		private static readonly Dictionary<ZDOID, Run> _runs = new Dictionary<ZDOID, Run>();

		public static void Start(ZDOID station, int stacks)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			_runs[station] = new Run
			{
				Start = Time.time,
				Stacks = stacks,
				LastCount = stacks,
				LastChange = Time.time
			};
		}

		public static void Check(ZDOID station, Inventory inv)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (!_runs.TryGetValue(station, out var value))
			{
				return;
			}
			int num = inv.NrOfItems();
			if (num != value.LastCount)
			{
				value.LastCount = num;
				value.LastChange = Time.time;
			}
			bool flag = num == 0;
			bool flag2 = Time.time - value.LastChange > 60f;
			if (flag || flag2)
			{
				float num2 = (flag ? Time.time : value.LastChange) - value.Start;
				string text = (flag ? $"gs_stress: station emptied, {value.Stacks} stacks in {num2:F0}s" : $"gs_stress: stalled with {num} stacks left after {num2:F0}s ({value.Stacks - num} moved)");
				Plugin.Log.LogInfo((object)text);
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
				}
				_runs.Remove(station);
			}
		}
	}
}
namespace GreydwarfSorter.Worker
{
	public class KvistPet : MonoBehaviour, Interactable
	{
		private class NameInput : TextReceiver
		{
			private readonly SorterStation _station;

			public NameInput(SorterStation station)
			{
				_station = station;
			}

			public string GetText()
			{
				if (!Object.op_Implicit((Object)(object)_station))
				{
					return "";
				}
				return _station.WorkerName;
			}

			public void SetText(string text)
			{
				if (Object.op_Implicit((Object)(object)_station))
				{
					_station.RequestSetName(text);
				}
			}
		}

		public EffectList m_petEffect = new EffectList();

		private float _lastPet = -10f;

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (hold || !Object.op_Implicit((Object)(object)user))
			{
				return false;
			}
			if (alt)
			{
				SorterAI component = ((Component)this).GetComponent<SorterAI>();
				SorterStation sorterStation = (Object.op_Implicit((Object)(object)component) ? component.Station : null);
				if (!Object.op_Implicit((Object)(object)sorterStation) || !Object.op_Implicit((Object)(object)TextInput.instance))
				{
					return false;
				}
				if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
				{
					return true;
				}
				TextInput.instance.RequestText((TextReceiver)(object)new NameInput(sorterStation), "$hud_rename", 20);
				return true;
			}
			if (Time.time - _lastPet < 1f)
			{
				return true;
			}
			_lastPet = Time.time;
			m_petEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			Character component2 = ((Component)this).GetComponent<Character>();
			string text = (Object.op_Implicit((Object)(object)component2) ? component2.GetHoverName() : "Kvist");
			((Character)user).Message((MessageType)2, text + " loves you", 0, (Sprite)null, false);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public class MapPins : MonoBehaviour
	{
		private const float Every = 2f;

		private float _next;

		private readonly List<PinData> _pins = new List<PinData>();

		private readonly List<ZDO> _pinZdos = new List<ZDO>();

		private readonly List<ZDO> _zdos = new List<ZDO>();

		private readonly Dictionary<long, string> _modeByNest = new Dictionary<long, string>();

		private readonly Dictionary<long, string> _nameByNest = new Dictionary<long, string>();

		private void Update()
		{
			//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_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _pins.Count; i++)
			{
				if (_pins[i] != null && _pinZdos[i] != null && _pinZdos[i].IsValid())
				{
					_pins[i].m_pos = Position(_pinZdos[i]);
				}
			}
			if (Time.time < _next)
			{
				return;
			}
			_next = Time.time + 2f;
			Clear();
			if (!ModConfig.ShowOnMap.Value || !Object.op_Implicit((Object)(object)Minimap.instance) || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			_modeByNest.Clear();
			_nameByNest.Clear();
			foreach (ZDO item in All("piece_gs_station"))
			{
				long num = item.GetLong(Keys.NestId, 0L);
				if (num != 0L)
				{
					_modeByNest[num] = SorterStation.ModeName((SorterStation.Mode)item.GetInt(Keys.Mode, 0));
					string text = item.GetString(Keys.WorkerName, "");
					_nameByNest[num] = (string.IsNullOrEmpty(text) ? "Kvist" : text);
				}
			}
			foreach (ZDO item2 in All("gs_worker"))
			{
				long key = item2.GetLong(Keys.NestId, 0L);
				string value;
				string text2 = (_nameByNest.TryGetValue(key, out value) ? value : "Kvist");
				string value2;
				string text3 = (_modeByNest.TryGetValue(key, out value2) ? (text2 + " (" + value2 + ")") : text2);
				_pins.Add(Minimap.instance.AddPin(Position(item2), (PinType)3, text3, false, false, 0L, default(PlatformUserID)));
				_pinZdos.Add(item2);
			}
		}

		private List<ZDO> All(string prefab)
		{
			_zdos.Clear();
			int num = 0;
			while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefab, _zdos, ref num))
			{
			}
			return new List<ZDO>(_zdos);
		}

		private static Vector3 Position(ZDO zdo)
		{
			//IL_0030: 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)
			ZNetView val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(zdo) : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return zdo.GetPosition();
			}
			return ((Component)val).transform.position;
		}

		private void Clear()
		{
			if (Object.op_Implicit((Object)(object)Minimap.instance))
			{
				foreach (PinData pin in _pins)
				{
					Minimap.instance.RemovePin(pin);
				}
			}
			_pins.Clear();
			_pinZdos.Clear();
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	public static class Placement
	{
		private static int _solid;

		private static float _radius = 0.5f;

		private static float _height = 1.8f;

		private static bool _measured;

		private static readonly float[] Rings = new float[6] { 0.75f, 1.5f, 2.5f, 3.5f, 5f, 8f };

		private static void Measure()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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)
			if (!_measured && Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("gs_worker");
				CapsuleCollider val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<CapsuleCollider>() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					float num = Mathf.Max(prefab.transform.localScale.x, prefab.transform.localScale.z);
					_radius = val.radius * num;
					_height = Mathf.Max(val.height * prefab.transform.localScale.y, _radius * 2f + 0.1f);
				}
				_measured = true;
			}
		}

		public static bool Fits(Vector3 feet)
		{
			//IL_0050: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			Measure();
			if (_solid == 0)
			{
				_solid = LayerMask.GetMask(new string[5] { "Default", "static_solid", "piece", "terrain", "vehicle" });
			}
			float num = _radius * 0.9f;
			Vector3 val = feet + Vector3.up * (num + 0.2f);
			Vector3 val2 = feet + Vector3.up * Mathf.Max(num + 0.2f, _height - num);
			return !Physics.CheckCapsule(val, val2, num, _solid, (QueryTriggerInteraction)1);
		}

		public static Vector3? ClearSpotNear(Vector3 center, float range, AgentType agent, Vector3? level = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_003b: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (Try(center, agent, level, out var spot))
			{
				return spot;
			}
			float[] rings = Rings;
			foreach (float num in rings)
			{
				if (num > range)
				{
					break;
				}
				for (int j = 0; j < 8; j++)
				{
					float num2 = (float)j * (float)Math.PI / 4f;
					if (Try(center + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * num, agent, level, out spot))
					{
						return spot;
					}
				}
			}
			return null;
		}

		private static bool Try(Vector3 candidate, AgentType agent, Vector3? level, out Vector3 spot)
		{
			//IL_0001: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			spot = default(Vector3);
			if (!Pathfinding.instance.FindValidPoint(ref spot, candidate, 1.5f, agent))
			{
				return false;
			}
			if (level.HasValue && Mathf.Abs(spot.y - level.Value.y) > 2.5f)
			{
				return false;
			}
			if (spot.y < ZoneSystem.instance.GetGroundHeight(spot) - 0.5f)
			{
				return false;
			}
			return Fits(spot);
		}

		public static Vector3 HomeSpot(SorterStation station, AgentType agent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			return (Vector3)(((??)ClearSpotNear(station.SpawnPosition, 6f, agent)) ?? station.SpawnPosition);
		}
	}
	public class SorterAI : BaseAI
	{
		public enum State
		{
			Idle,
			Load,
			Plan,
			Deliver,
			Return,
			Fetch,
			Feed,
			Collect,
			Empty,
			Refuel,
			Extract,
			Harvest,
			Plant,
			FeedAnimal,
			Butcher,
			TakeFood,
			FuelOven
		}

		private enum CrossPhase
		{
			Approach,
			Opening,
			Through
		}

		private class FeedPlan
		{
			public Container From;

			public string Food;

			public int Want;

			public int Mouths;

			public Vector3 Animals;
		}

		private class Job
		{
			public string What;

			public Vector3 At;

			public Vector3? Then;

			public float Value;

			public float Work;

			public Action Start;

			public float Rough;

			public float Score;

			public float Metres;

			public bool Delivery;

			public WorkTask? Task;
		}

		private class ReachSpot
		{
			public Vector3 Target;

			public Vector3 Stand;

			public float Until;
		}

		public const string RpcWorkerDied = "gs_WorkerDied";

		private const float WanderRange = 4f;

		private const float OrphanCheckSeconds = 1f;

		private const float AccessWaitSeconds = 5f;

		private const float BlacklistSeconds = 60f;

		private const float BusyChestSeconds = 10f;

		private const float LeashSlack = 10f;

		private const float ProgressStep = 0.5f;

		private WorkerCarry _carry;

		private SorterStation _station;

		private float _orphanTimer;

		private float _tickTimer;

		private State _state;

		private float _stateStart;

		private float _pauseUntil;

		private Container _target;

		private float _bestDist;

		private float _lastProgress;

		private float _noPathSince = -1f;

		private const float NoPathGraceSeconds = 3f;

		private const float TeleportLandingMax = 8f;

		private int _doorTries;

		private const int MaxDoorTries = 2;

		private const float CloseEnoughToReach = 4f;

		private bool _longReach;

		private Vector3 _moveGoal;

		private Component _moveNear;

		private float _waitStart = -1f;

		private Container _openChest;

		private float _stationMissingFor;

		private const float StationMissingGrace = 30f;

		private readonly List<float> _giveUps = new List<float>();

		private const int TrappedGiveUps = 1;

		private const float TrappedWindow = 45f;

		private const float HopSeconds = 3f;

		private const float HopEvery = 0.5f;

		private float _hopUntil = -1f;

		private Vector3 _hopDir;

		private float _lastHop;

		private bool _hoppedSinceHome;

		private const float DoorSearchRadius = 20f;

		private const float DoorSideOffset = 1.4f;

		private const float DoorOpenWait = 0.8f;

		private const float DoorThroughTimeout = 4f;

		private const float DoorApproachTimeout = 10f;

		private const float DoorRetrySeconds = 15f;

		private Door _door;

		private CrossPhase _crossPhase;

		private Vector3 _doorNear;

		private Vector3 _doorFar;

		private float _crossStart;

		private bool _openedDoor;

		private readonly Dictionary<int, float> _doorTried = new Dictionary<int, float>();

		private readonly Dictionary<int, float> _trapDoors = new Dictionary<int, float>();

		private const float TrapDoorSeconds = 1800f;

		private Door _lastCrossDoor;

		private Vector3 _lastCrossFrom;

		private float _lastCrossTime = -1000f;

		private readonly List<Vector3> _probe = new List<Vector3>();

		private Door _doorToClose;

		private float _closeNextTry;

		private float _closeGiveUp;

		private const int PlantBatch = 20;

		private const float HarvestPause = 0.8f;

		private Pickable _crop;

		private Vector3 _plantSpot;

		private Sapling _planting;

		private readonly Dictionary<Sapling, int> _plan = new Dictionary<Sapling, int>();

		private readonly List<Sapling> _toFetch = new List<Sapling>();

		private readonly SoilScan _soil = new SoilScan();

		private float _replantBlockedUntil;

		private readonly Dictionary<Vector3, float> _badCells = new Dictionary<Vector3, float>();

		private const float BadCellSeconds = 300f;

		private const float BadPatchRadius = 2f;

		private const float NearDropRadius = 8f;

		private const int MinIdleCells = 3;

		private const float FarmReach = 3f;

		private const int HarvestPerStop = 8;

		private const int PlantPerStop = 5;

		private const float FedCooldown = 60f;

		private const float FeedGroupRadius = 6f;

		private const float ButcherSiteSeconds = 600f;

		private const float ButcherSiteRadius = 6f;

		private Character _animal;

		private bool _feeding;

		private readonly Dictionary<int, float> _fedAt = new Dictionary<int, float>();

		private readonly List<KeyValuePair<Vector3, float>> _butcherSites = new List<KeyValuePair<Vector3, float>>();

		private readonly HashSet<string> _butcherDrops = new HashSet<string>();

		private bool _cullingHens;

		private string _lastNoFood;

		private bool _eggsWanted;

		private const float PenRadius = 10f;

		private readonly HashSet<string> _herdDrops = new HashSet<string>();

		private readonly List<KeyValuePair<Vector3, float>> _foodSpots = new List<KeyValuePair<Vector3, float>>();

		private const float FoodSpotSeconds = 600f;

		private readonly List<Vector3> _herdAt = new List<Vector3>();

		private readonly List<Job> _jobs = new List<Job>();

		private WorkTask? _offerTask;

		private const float JobOverhead = 1.5f;

		private const int JobsToPath = 4;

		private const float NoPathPenaltyMetres = 15f;

		private readonly List<Vector3> _jobPath = new List<Vector3>();

		private SorterStation.Mode? _lastGroup;

		private bool _flushAll;

		private float _lastFlush = -1000f;

		private const float FlushRetrySeconds = 30f;

		private const float MeterSeconds = 300f;

		private float _meterStart = -1f;

		private float _meterWalked;

		private int _meterJobs;

		private int _meterItems;

		private Vector3 _meterLast;

		private bool _meterHasLast;

		private const int MillBatch = 5;

		private const float AtHandDistance = 3f;

		private Container _piggyback;

		private readonly List<ReachSpot> _reachSpots = new List<ReachSpot>();

		private const float ReachSpotSeconds = 1800f;

		private const float ReachSpotMatch = 2f;

		private const int ReachSpotMax = 300;

		private Vector3? _reachStand;

		private bool _reachLooked;

		private const float SmelterArrive = 2.5f;

		private const float CollectArrive = 1.5f;

		private const float CollectRadius = 3f;

		private const float EmptyPause = 1.5f;

		private const int UrgentBatch = 5;

		private Smelter _smelter;

		private ItemDrop _drop;

		private string _fetchPrefab;

		private string _feedPrefab;

		private int _fetchAmount;

		private readonly Dictionary<int, float> _ignoreUntil = new Dictionary<int, float>();

		private const float ScoopRadius = 2.5f;

		private const float FarmScoopRadius = 4.5f;

		private static readonly float[] TeleportSearch = new float[2] { 3f, 8f };

		private int _embedded;

		private static int _ceilingMask;

		public const string RpcCallHome = "gs_CallHome";

		private const float SidestepSeconds = 1.2f;

		private bool _sidestepped;

		private float _sidestepUntil = -1f;

		private Vector3 _sidestepDir;

		private const float BackoffMax = 600f;

		private readonly Dictionary<int, int> _failures = new Dictionary<int, int>();

		private const float IdleTrapCheckSeconds = 10f;

		private float _nextIdleTrapCheck;

		private int _idleNoWayHome;

		private const float ProductRadius = 2.5f;

		private Fireplace _fire;

		private CookingStation _cooker;

		private Component _tap;

		private Vector3 _tapPoint;

		private static float ExtendedReach => Mathf.Max(0f, ModConfig.ReachDistance.Value);

		public State CurrentState => _state;

		public Container Target => _target;

		public SorterStation Station
		{
			get
			{
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)base.m_nview) || !base.m_nview.IsValid())
				{
					return null;
				}
				ZDO zdo = base.m_nview.GetZDO();
				long nest = zdo.GetLong(Keys.NestId, 0L);
				if (nest != 0L)
				{
					return SorterStation.All.FirstOrDefault((SorterStation s) => Object.op_Implicit((Object)(object)s) && s.NestId == nest);
				}
				SorterStation sorterStation = SorterStation.All.FirstOrDefault((SorterStation s) => Object.op_Implicit((Object)(object)s) && s.WorkerId == zdo.m_uid);
				if (!Object.op_Implicit((Object)(object)sorterStation))
				{
					GameObject val = ZNetScene.instance.FindInstance(Keys.GetLink(zdo));
					sorterStation = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<SorterStation>() : null);
				}
				if (Object.op_Implicit((Object)(object)sorterStation) && sorterStation.NestId != 0L && base.m_nview.IsOwner())
				{
					zdo.Set(Keys.NestId, sorterStation.NestId);
					zdo.SetConnection((ConnectionType)0, ZDOID.None);
				}
				return sorterStation;
			}
		}

		public ZDOID StationId
		{
			get
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				SorterStation station = Station;
				ZNetView val = (Object.op_Implicit((Object)(object)station) ? ((Component)station).GetComponent<ZNetView>() : null);
				if (!Object.op_Implicit((Object)(object)val) || !val.IsValid())
				{
					return ZDOID.None;
				}
				return val.GetZDO().m_uid;
			}
		}

		private bool Crossing => Object.op_Implicit((Object)(object)_door);

		public Pickable CropTarget => _crop;

		public Character AnimalTarget => _animal;

		private float Speed
		{
			get
			{
				float num = (ModConfig.Run.Value ? base.m_character.m_runSpeed : base.m_character.m_walkSpeed);
				if (!(num > 0.5f))
				{
					return 4f;
				}
				return num;
			}
		}

		private float Fullness
		{
			get
			{
				int num = Mathf.Max(1, ModConfig.CarryStacks.Value);
				return Mathf.Clamp01((float)(num - _carry.Inventory.GetEmptySlots()) / (float)num);
			}
		}

		public Smelter SmelterTarget => _smelter;

		public Vector3 FeedGoal => SmelterIndex.FeedPoint(_smelter, _feedPrefab);

		public Component UpkeepTarget
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_fire))
				{
					return _tap;
				}
				return (Component)(object)_fire;
			}
		}

		public override void Awake()
		{
			((BaseAI)this).Awake();
			_carry = ((Component)this).GetComponent<WorkerCarry>();
			if (Object.op_Implicit((Object)(object)base.m_nview))
			{
				base.m_nview.Register("gs_CallHome", (Action<long>)RPC_CallHome);
			}
		}

		private void Start()
		{
			SetState((_carry.Inventory.NrOfItems() > 0) ? State.Plan : State.Idle);
			if (Object.op_Implicit((Object)(object)base.m_nview) && base.m_nview.IsValid() && base.m_nview.IsOwner())
			{
				base.m_nview.GetZDO().Set(Keys.Problem, "");
			}
		}

		public override bool UpdateAI(float dt)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0624: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_066b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0703: Unknown result type (might be due to invalid IL or missing references)
			//IL_0772: Unknown result type (might be due to invalid IL or missing references)
			//IL_075b: Unknown result type (might be due to invalid IL or missing references)
			if (!((BaseAI)this).UpdateAI(dt))
			{
				return false;
			}
			SorterStation station = Station;
			_orphanTimer -= dt;
			int num;
			if (_orphanTimer <= 0f)
			{
				_orphanTimer = 1f;
				if (Object.op_Implicit((Object)(object)station))
				{
					ZDOID workerId = station.WorkerId;
					if (!((ZDOID)(ref workerId)).IsNone())
					{
						num = ((station.WorkerId != base.m_nview.GetZDO().m_uid) ? 1 : 0);
						goto IL_0092;
					}
				}
				num = 0;
				goto IL_0092;
			}
			goto IL_011e;
			IL_0092:
			bool flag = (byte)num != 0;
			_stationMissingFor = (Object.op_Implicit((Object)(object)station) ? 0f : (_stationMissingFor + 1f));
			if (flag || _stationMissingFor > 30f)
			{
				Plugin.Log.LogInfo((object)string.Format("Kvist {0} has no station ({1}); dropping carry and despawning", base.m_nview.GetZDO().m_uid, flag ? "replaced" : "nest gone"));
				_carry.DropAll();
				ZNetScene.instance.Destroy(((Component)this).gameObject);
				return false;
			}
			goto IL_011e;
			IL_011e:
			if (!Object.op_Implicit((Object)(object)station))
			{
				((BaseAI)this).StopMoving();
				return true;
			}
			_station = station;
			if (_orphanTimer >= 1f - dt && (RescueIfUnderground(station) || RescueIfEmbedded(station)))
			{
				return true;
			}
			if (CheckIdleTrapped(station))
			{
				return true;
			}
			UpdateMeter();
			if (UpdateHop())
			{
				return true;
			}
			if (_state != State.Return && _state != State.Idle && Vector3.Distance(((Component)this).transform.position, ((Component)station).transform.position) > ModConfig.WorkRadius.Value + 10f)
			{
				SetState(State.Return);
			}
			if (station.CurrentMode == SorterStation.Mode.Farming || station.CurrentMode == SorterStation.Mode.Custom)
			{
				StepSoilScan(station);
			}
			if (Time.time < _pauseUntil)
			{
				((BaseAI)this).StopMoving();
				return true;
			}
			UpdateDoorClosing();
			CloseLid();
			_tickTimer -= dt;
			bool flag2 = _tickTimer <= 0f;
			if (flag2)
			{
				_tickTimer = ModConfig.AITickSeconds.Value;
			}
			switch (_state)
			{
			case State.Idle:
				if (station.CurrentMode == SorterStation.Mode.Smelting)
				{
					UpdateIdleSmelting(dt, station, flag2);
				}
				else if (station.CurrentMode == SorterStation.Mode.Upkeep)
				{
					UpdateIdleUpkeep(dt, station, flag2);
				}
				else if (station.CurrentMode == SorterStation.Mode.Farming)
				{
					UpdateIdleFarming(dt, station, flag2);
				}
				else if (station.CurrentMode == SorterStation.Mode.Husbandry)
				{
					UpdateIdleHusbandry(dt, station, flag2);
				}
				else if (station.CurrentMode == SorterStation.Mode.Custom)
				{
					UpdateIdleCustom(dt, station, flag2);
				}
				else
				{
					UpdateIdle(dt, station, flag2);
				}
				break;
			case State.Plan:
				if (flag2)
				{
					DoPlan(station);
				}
				else
				{
					((BaseAI)this).StopMoving();
				}
				break;
			case State.Load:
				UpdateMove(dt, station.SpawnPosition, flag2, delegate
				{
					DoLoad(station);
				}, -1f, (Component)(object)station);
				break;
			case State.Return:
				UpdateMove(dt, station.SpawnPosition, flag2, delegate
				{
					DoReturn(station);
				}, -1f, (Component)(object)station);
				break;
			case State.Deliver:
				if (!Object.op_Implicit((Object)(object)_target))
				{
					SetState(State.Plan);
					break;
				}
				UpdateMove(dt, ((Component)_target).transform.position, flag2, delegate
				{
					DoDeliver(station);
				}, -1f, (Component)(object)_target);
				break;
			case State.Fetch:
				if (!Object.op_Implicit((Object)(object)_target))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_target).transform.position, flag2, DoFetch, -1f, (Component)(object)_target);
				}
				break;
			case State.Feed:
				if (!Object.op_Implicit((Object)(object)_smelter))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, FeedGoal, flag2, DoFeed, 2.5f, (Component)(object)_smelter);
				}
				break;
			case State.Empty:
				if (!Object.op_Implicit((Object)(object)_smelter))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, SmelterIndex.OutputPoint(_smelter), flag2, DoEmpty, 2.5f, (Component)(object)_smelter);
				}
				break;
			case State.Collect:
				if (!Object.op_Implicit((Object)(object)_drop))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_drop).transform.position, flag2, DoCollect, 1.5f);
				}
				break;
			case State.Refuel:
				if (!Object.op_Implicit((Object)(object)_fire))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_fire).transform.position, flag2, DoRefuel, 2.5f, (Component)(object)_fire);
				}
				break;
			case State.Extract:
				if (!Object.op_Implicit((Object)(object)_tap))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, _tapPoint, flag2, DoExtract, 2.5f, _tap);
				}
				break;
			case State.Harvest:
				if (!Object.op_Implicit((Object)(object)_crop))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_crop).transform.position, flag2, DoHarvest, 1.5f, (Component)(object)_crop);
				}
				break;
			case State.Plant:
				UpdateMove(dt, _plantSpot, flag2, delegate
				{
					DoPlant(station);
				}, 1.5f);
				break;
			case State.FeedAnimal:
				if (!Object.op_Implicit((Object)(object)_animal))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_animal).transform.position, flag2, DoFeedAnimal, 2.5f, (Component)(object)_animal);
				}
				break;
			case State.Butcher:
				if (!Object.op_Implicit((Object)(object)_animal))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_animal).transform.position, flag2, DoButcher, 2.5f, (Component)(object)_animal);
				}
				break;
			case State.TakeFood:
				if (!Object.op_Implicit((Object)(object)_cooker))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, ((Component)_cooker).transform.position, flag2, DoTakeFood, 2.5f, (Component)(object)_cooker);
				}
				break;
			case State.FuelOven:
				if (!Object.op_Implicit((Object)(object)_cooker))
				{
					DecideNext();
				}
				else
				{
					UpdateMove(dt, Object.op_Implicit((Object)(object)_cooker.m_addFuelSwitch) ? ((Component)_cooker.m_addFuelSwitch).transform.position : ((Component)_cooker).transform.position, flag2, DoFuelOven, 2.5f, (Component)(object)_cooker);
				}
				break;
			}
			return true;
		}

		private void UpdateIdle(float dt, SorterStation station, bool tick)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).RandomMovementArroundPoint(dt, ((Component)station).transform.position, 4f, ModConfig.Run.Value);
			if (tick && !(Time.time - _stateStart < ModConfig.IdleSeconds.Value))
			{
				if (_carry.Inventory.NrOfItems() > 0)
				{
					SetState(State.Plan);
				}
				else if (station.Priority(WorkTask.SortNest) > 0 && _carry.Inventory.HaveEmptySlot() && station.Container.GetInventory().GetAllItems().Any((ItemData i) => Placeable(station, i)))
				{
					SetState(State.Load);
				}
				else
				{
					SetState(State.Idle);
				}
			}
		}

		private void UpdateMove(float dt, Vector3 goal, bool tick, Action arrive, float arriveDist = -1f, Component near = null)
		{
			//IL_001c: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			if ((Crossing && UpdateCrossing(dt)) || UpdateSidestep())
			{
				return;
			}
			_moveGoal = goal;
			_moveNear = near;
			if (_longReach)
			{
				((BaseAI)this).StopMoving();
				if (tick)
				{
					RememberReach(goal, ((Component)this).transform.position);
					arrive();
				}
			}
			else
			{
				if (UpdateReachSpot(dt, goal))
				{
					return;
				}
				if (arriveDist < 0f)
				{
					arriveDist = ModConfig.ArriveDistance.Value;
				}
				bool flag = ((BaseAI)this).MoveTo(dt, goal, arriveDist, ModConfig.Run.Value);
				float num = Utils.DistanceXZ(goal, ((Component)this).transform.position);
				if (flag && (num <= arriveDist + 0.75f || (Object.op_Implicit((Object)(object)near) && DistanceToOutline(near) <= ModConfig.ArriveDistance.Value)))
				{
					((BaseAI)this).StopMoving();
					Reached((Object)(object)near);
					if (tick)
					{
						arrive();
					}
					return;
				}
				if (num < _bestDist - 0.5f)
				{
					_bestDist = num;
					_lastProgress = Time.time;
				}
				if (!flag)
				{
					_noPathSince = -1f;
				}
				else if (_noPathSince < 0f)
				{
					_noPathSince = Time.time;
				}
				bool flag2 = flag && Time.time - _noPathSince > 3f;
				if (flag2 || Time.time - _lastProgress > ModConfig.StuckSeconds.Value)
				{
					if (!flag2 && !_sidestepped && !Crossing)
					{
						StartSidestep(goal);
					}
					else if (!(Vector3.Distance(goal, ((Component)this).transform.position) <= 4f) && !Crossing && _doorTries < 2 && TryStartDoorCrossing(goal))
					{
						_doorTries++;
					}
					else
					{
						GiveUp(flag2 ? "no path" : "stuck");
					}
				}
			}
		}

		private void ResetProgress()
		{
			_bestDist = float.MaxValue;
			_lastProgress = Time.time;
			_noPathSince = -1f;
		}

		private float DistanceToOutline(Component target)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			float num = float.MaxValue;
			Collider[] componentsInChildren = target.GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (val.enabled && !val.isTrigger)
				{
					Bounds bounds = val.bounds;
					Vector3 val2 = ((Bounds)(ref bounds)).ClosestPoint(((Component)this).transform.position);
					num = Mathf.Min(num, Utils.DistanceXZ(val2, ((Component)this).transform.position));
				}
			}
			if (num != float.MaxValue)
			{
				return num;
			}
			return Utils.DistanceXZ(target.transform.position, ((Component)this).transform.position);
		}

		private bool UnstickIfTrapped()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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)
			_giveUps.Add(Time.time);
			_giveUps.RemoveAll((float t) => Time.time - t > 45f);
			SorterStation station = Station;
			if (_giveUps.Count < 1 || !Object.op_Implicit((Object)(object)station))
			{
				return false;
			}
			Vector3 spawnPosition = station.SpawnPosition;
			if (PathReaches(((Component)this).transform.position, spawnPosition, 3f))
			{
				_hoppedSinceHome = false;
				return false;
			}
			if (_doorTries < 2 && Object.op_Implicit((Object)(object)FindCrossing(spawnPosition, anyDoor: true, out var _, out var _)))
			{
				_hoppedSinceHome = false;
				return false;
			}
			_giveUps.Clear();
			bool flag = Object.op_Implicit((Object)(object)_lastCrossDoor) && Time.time - _lastCrossTime < 120f;
			if (flag && !_trapDoors.ContainsKey(((Object)_lastCrossDoor).GetInstanceID()))
			{
				_trapDoors[((Object)_lastCrossDoor).GetInstanceID()] = Time.time + 1800f;
				Plugin.Log.LogInfo((object)$"Kvist: {_lastCrossDoor.m_name} at {((Component)_lastCrossDoor).transform.position} led into a trap; not using it for {30f:0} min");
			}
			if (ModConfig.TeleportWhenStuck.Value)
			{
				Report("Kvist got stuck and went back to his nest");
				TeleportTo(HomeSpot(station), "out of a trap");
				DecideNext();
				return true;
			}
			if (!_hoppedSinceHome)
			{
				_hoppedSinceHome = true;
				_hopDir = (flag ? _lastCrossFrom : spawnPosition) - ((Component)this).transform.position;
				_hopDir.y = 0f;
				((Vector3)(ref _hopDir)).Normalize();
				_hopUntil = Time.time + 3f;
				_lastHop = -1000f;
				Plugin.Log.LogInfo((object)string.Format("Kvist: trapped at {0}; jumping towards {1}", ((Component)this).transform.position, flag ? "the way he came in" : "home"));
				return true;
			}
			_hoppedSinceHome = false;
			Plugin.Log.LogInfo((object)$"Kvist: still trapped at {((Component)this).transform.position}; back to the nest");
			Report("Kvist got stuck and went back to his nest");
			Vector3 position = HomeSpot(station);
			((Component)this).transform.position = position;
			if (Object.op_Implicit((Object)(object)base.m_body))
			{
				base.m_body.position = position;
				base.m_body.linearVelocity = Vector3.zero;
			}
			ForgetPath();
			DecideNext();
			return true;
		}

		private bool UpdateHop()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time >= _hopUntil)
			{
				return false;
			}
			((BaseAI)this).MoveTowards(_hopDir, true);
			if (base.m_character.IsOnGround() && Time.time - _lastHop > 0.5f)
			{
				base.m_character.ForceJump(_hopDir * 4f + Vector3.up * 7f, true);
				_lastHop = Time.time;
			}
			if (Time.time + Time.deltaTime >= _hopUntil)
			{
				((BaseAI)this).StopMoving();
				ForgetPath();
				DecideNext();
			}
			return true;
		}

		private void GiveUp(string why)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).StopMoving();
			if (UnstickIfTrapped())
			{
				return;
			}
			if (!_longReach)
			{
				ReportTrouble(Station, TargetName(), _moveGoal);
			}
			if (ModConfig.TeleportWhenStuck.Value && !_longReach && _state != State.Plant && _state != State.Return && TeleportNear(_moveGoal))
			{
				Plugin.Log.LogInfo((object)("Kvist: " + why + " going to " + (TargetName() ?? _state.ToString()) + "; teleported beside it"));
				_longReach = true;
				return;
			}
			float num = (Object.op_Implicit((Object)(object)_moveNear) ? Mathf.Min(Utils.DistanceXZ(_moveGoal, ((Component)this).transform.position), DistanceToOutline(_moveNear)) : Utils.DistanceXZ(_moveGoal, ((Component)this).transform.position));
			if (ModConfig.ReachWhenBlocked.Value && !_longReach && num <= ExtendedReach)
			{
				Plugin.Log.LogInfo((object)$"Kvist: {why} going to {TargetName() ?? _state.ToString()}; reaching {num:0.0} m from here");
				_longReach = true;
				return;
			}
			if (_state == State.Plant)
			{
				PlantUnreachable(why);
				return;
			}
			string text = TargetName();
			if (text != null)
			{
				Report("Can't reach " + text);
			}
			if (_state == State.Deliver && Object.op_Implicit((Object)(object)_target))
			{
				float num2 = Backoff((Object)(object)_target);
				Plugin.Log.LogInfo((object)$"Kvist: {why} going to {_target.m_name} at {((Component)_target).transform.position}; skipping it for {num2:0}s");
				ChestIndex.Blacklist(_target, num2);
				SetState(State.Plan);
			}
			else if ((_state == State.Feed || _state == State.Empty) && Object.op_Implicit((Object)(object)_smelter))
			{
				float num3 = Backoff((Object)(object)_smelter);
				Plugin.Log.LogInfo((object)$"Kvist: {why} going to {_smelter.m_name}; skipping it for {num3:0}s");
				Ignore((Object)(object)_smelter, num3);
				DecideNext();
			}
			else if (_state == State.Refuel && Object.op_Implicit((Object)(object)_fire))
			{
				Ignore((Object)(object)_fire, Backoff((Object)(object)_fire));
				DecideNext();
			}
			else if (_state == State.Extract && Object.op_Implicit((Object)(object)_tap))
			{
				Ignore((Object)(object)_tap, Backoff((Object)(object)_tap));
				DecideNext();
			}
			else if (_state == State.Harvest && Object.op_Implicit((Object)(object)_crop))
			{
				Ignore((Object)(object)_crop, Backoff((Object)(object)_crop));
				DecideNext();
			}
			else if ((_state == State.FeedAnimal || _state == State.Butcher) && Object.op_Implicit((Object)(object)_animal))
			{
				Ignore((Object)(object)_animal, Backoff((Object)(object)_animal));
				DecideNext();
			}
			else if ((_state == State.TakeFood || _state == State.FuelOven) && Object.op_Implicit((Object)(object)_cooker))
			{
				Ignore((Object)(object)_cooker, Backoff((Object)(object)_cooker));
				DecideNext();
			}
			else if (_state == State.Collect && Object.op_Implicit((Object)(object)_drop))
			{
				Ignore((Object)(object)_drop, Backoff((Object)(object)_drop));
				DecideNext();
			}
			else if (_state == State.Fetch && Object.op_Implicit((Object)(object)_target))
			{
				ChestIndex.Blacklist(_target, Backoff((Object)(object)_target));
				DecideNext();
			}
			else
			{
				Plugin.Log.LogInfo((object)("Kvist: " + why + " going back to the station"));
				SetState(State.Idle);
			}
		}

		private bool Placeable(SorterStation station, ItemData item)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			return (Object)(object)ChestIndex.FindTarget(ItemClassifier.Classify(item), item, ((Component)station).transform.position, ModConfig.WorkRadius.Value, ((Component)this).transform.position) != (Object)null;
		}

		private void DoLoad(SorterStation station)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Container container = station.Container;
			if (!TryAccess(container))
			{
				return;
			}
			OpenLid(container);
			Inventory inventory = container.GetInventory();
			int num = 0;
			foreach (ItemData item in inventory.GetAllItems().ToList())
			{
				if (!_carry.Inventory.HaveEmptySlot())
				{
					break;
				}
				if (Placeable(station, item) && ContainerAccess.Move(inventory, _carry.Inventory, item, ((Component)this).transform.position) > 0)
				{
					num++;
				}
			}
			_carry.Save();
			Plugin.Log.LogInfo((object)$"Kvist: loaded {num} stacks");
			SetState(State.Plan);
		}

		private void DoPlan(SorterStation station)
		{
			//IL_0080: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).StopMoving();
			List<ItemData> list = (from i in _carry.Inventory.GetAllItems()
				where !KeptInHand(station, i)
				select i).ToList();
			if (list.Count == 0)
			{
				SetState(State.Idle);
				return;
			}
			Container val = null;
			float num = float.MaxValue;
			foreach (ItemData item in list)
			{
				Container val2 = ChestIndex.FindTarget(ItemClassifier.Classify(item), item, ((Component)station).transform.position, ModConfig.WorkRadius.Value, ((Component)this).transform.position);
				if (Object.op_Implicit((Object)(object)val2))
				{
					float num2 = Vector3.Distance(((Component)val2).transform.position, ((Component)this).transform.position);
					if (num2 < num)
					{
						val = val2;
						num = num2;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				_target = val;
				SetState(State.Deliver);
				return;
			}
			List<Container> chests = ChestIndex.Labelled(((Component)station).transform.position, ModConfig.WorkRadius.Value);
			IEnumerable<string> source = (from i in list
				select ItemClassifier.Classify(i) into c
				group c by c.Id).Select(delegate(IGrouping<string, Category> g)
			{
				List<Container> list2 = chests.Where((Container c) => ChestLabel.Get(c) == g.Key).ToList();
				if (list2.Count == 0)
				{
					return "No chest for: " + g.First().Name;
				}
				return list2.Any(ChestIndex.IsBlacklisted) ? (g.First().Name + " chest: out of reach or open, trying again soon") : (g.First().Name + " chest is full");
			});
			Report(string.Join(" · ", source.Distinct()));
			SetState(State.Return);
		}

		private bool BelongsHere(SorterStation station, ItemData item)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!KeptInHand(station, item))
			{
				return (Object)(object)ChestIndex.FindTarget(ItemClassifier.Classify(item), item, ((Component)station).transform.position, ModConfig.WorkRadius.Value, ((Component)this).transform.position) == (Object)(object)_target;
			}
			return false;
		}

		private void DoDeliver(SorterStation station)
		{
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if (!_carry.Inventory.GetAllItems().Any((ItemData i) => BelongsHere(station, i)))
			{
				SetState(State.Plan);
			}
			else
			{
				if (!TryAccess(_target))
				{
					return;
				}
				OpenLid(_target);
				Inventory inventory = _target.GetInventory();
				int num = 0;
				List<string> list = new List<string>();
				foreach (ItemData item in _carry.Inventory.GetAllItems().ToList())
				{
					if (BelongsHere(station, item))
					{
						list.Add(ItemClassifier.PrefabName(item));
						if (ChestLabel.Get(_target) == "auto")
						{
							Category category = ItemClassifier.Classify(item);
							ChestLabel.SetOwned(_target, category.Id);
							Plugin.Log.LogInfo((object)("Kvist: claimed an Auto chest for " + category.Name));
						}
						num += ContainerAccess.Move(_carry.Inventory, inventory, item, ((Component)this).transform.position);
					}
				}
				_carry.Save();
				Plugin.Log.LogInfo((object)string.Format("Kvist: put {0} items ({1}) in {2} [{3}]", num, string.Join(", ", list.Distinct()), _target.m_name, ChestLabel.Get(_target)));
				CountStat(station, SorterStation.Stat.Sorted, num);
				if (!TryPiggyback(station))
				{
					SetState(State.Plan);
				}
			}
		}

		private void OpenLid(Container c)
		{
			ContainerAccess.Open(c);
			_openChest = c;
			_pauseUntil = Time.time + ModConfig.DepositSeconds.Value;
		}

		private void CloseLid()
		{
			if (Object.op_Implicit((Object)(object)_openChest))
			{
				ContainerAccess.Close(_openChest);
			}
			_openChest = null;
		}

		public override void OnDisable()
		{
			CloseLid();
			if (_openedDoor && Object.op_Implicit((Object)(object)_door) && _door.m_nview.IsValid() && DoorState(_door) != 0)
			{
				_door.m_nview.InvokeRPC("UseDoor", new object[1] { false });
			}
			if (Object.op_Implicit((Object)(object)_doorToClose) && _doorToClose.m_nview.IsValid() && DoorState(_doorToClose) != 0)
			{
				_doorToClose.m_nview.InvokeRPC("UseDoor", new object[1] { false });
			}
			((BaseAI)this).OnDisable();
		}

		private void DoReturn(SorterStation station)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (_carry.Inventory.NrOfItems() == 0)
			{
				SetState(State.Idle);
				return;
			}
			Container container = station.Container;
			if (!TryAccess(container))
			{
				return;
			}
			OpenLid(container);
			Inventory inventory = container.GetInventory();
			foreach (ItemData item in _carry.Inventory.GetAllItems().ToList())
			{
				if (!KeptInHand(station, item))
				{
					string arg = $"{item.m_stack} {ItemClassifier.PrefabName(item)}";
					int num = ContainerAccess.Move(_carry.Inventory, inventory, item, ((Component)this).transform.position);
					Plugin.Log.LogInfo((object)$"Kvist: returned {num} of {arg} to the nest");
				}
			}
			_carry.Save();
			SetState(State.Idle);
		}

		private bool TryAccess(Container c)
		{
			if (ContainerAccess.Request(c) == ContainerAccess.State.Granted)
			{
				_waitStart = -1f;
				return true;
			}
			if (_waitStart < 0f)
			{
				_waitStart = Time.time;
			}
			if (Time.time - _waitStart > 5f)
			{
				_waitStart = -1f;
				if (_state == State.Deliver || _state == State.Fetch)
				{
					Report("Chest in use: " + Localization.instance.Localize(c.m_name));
					ChestIndex.Blacklist(c, 10f);
					if (_state == State.Deliver)
					{
						SetState(State.Plan);
					}
					else
					{
						DecideNext();
					}
				}
				else
				{
					SetState(State.Idle);
				}
			}
			return false;
		}

		private void Report(string problem)
		{
			if (Object.op_Implicit((Object)(object)base.m_nview) && base.m_nview.IsValid() && base.m_nview.IsOwner())
			{
				base.m_nview.GetZDO().Set(Keys.Problem, problem);
				base.m_nview.GetZDO().Set(Keys.ProblemAt, ZNet.instance.GetTime().Ticks);
			}
		}

		private void CountStat(SorterStation station, SorterStation.Stat stat, int amount)
		{
			if (amount > 0 && Object.op_Implicit((Object)(object)station))
			{
				MeterItems(amount);
				ZNetView component = ((Component)station).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid())
				{
					component.InvokeRPC("gs_Stat", new object[2]
					{
						(int)stat,
						amount
					});
				}
			}
		}

		private string TargetName()
		{
			if (Object.op_Implicit((Object)(object)_target))
			{
				return Localization.instance.Localize(_target.m_name);
			}
			if (Object.op_Implicit((Object)(object)_smelter))
			{
				return Localization.instance.Localize(_smelter.m_name);
			}
			if (Object.op_Implicit((Object)(object)_fire))
			{
				return Localization.instance.Localize(_fire.m_name);
			}
			if (Object.op_Implicit((Object)(object)_tap))
			{
				return Utils.GetPrefabName(_tap.gameObject);
			}
			if (Object.op_Implicit((Object)(object)_crop))
			{
				return Utils.GetPrefabName(((Component)_crop).gameObject);
			}
			if (Object.op_Implicit((Object)(object)_animal))
			{
				return Utils.GetPrefabName(((Component)_animal).gameObject);
			}
			if (Object.op_Implicit((Object)(object)_drop))
			{
				return Utils.GetPrefabName(((Component)_drop).gameObject);
			}
			if (Object.op_Implicit((Object)(object)_cooker))
			{
				return Localization.instance.Localize(_cooker.m_name);
			}
			if (_state == State.Plant)
			{
				return "a spot to plant";
			}
			return null;
		}

		private void SetState(State s)
		{
			if (Crossing)
			{
				EndCrossing(through: false);
			}
			if (s != State.Deliver && s != State.Fetch)
			{
				_target = null;
			}
			if (s != State.Feed && s != State.Empty)
			{
				_smelter = null;
			}
			if (s != State.Feed)
			{
				_feedPrefab = null;
			}
			if (s != State.Collect)
			{
				_drop = null;
			}
			if (s != State.Refuel)
			{
				_fire = null;
			}
			if (s != State.Extract)
			{
				_tap = null;
			}
			if (s != State.Harvest)
			{
				_crop = null;
			}
			if (s != State.FeedAnimal && s != State.Butcher)
			{
				_animal = null;
			}
			if (s != State.TakeFood && s != State.FuelOven)
			{
				_cooker = null;
			}
			if (s != State.Idle && s != State.Plan && s != _state)
			{
				CountJob();
			}
			if (s != State.Plan && s != State.Deliver && s != State.Return && s != State.Idle)
			{
				_flushAll = false;
			}
			_state = s;
			_stateStart = Time.time;
			_bestDist = float.MaxValue;
			_lastProgress = Time.time;
			_noPathSince = -1f;
			_longReach = false;
			_sidestepped = false;
			_sidestepUntil = -1f;
			_reachStand = null;
			_reachLooked = false;
			_doorTries = 0;
			_waitStart = -1f;
			if (Object.op_Implicit((Object)(object)base.m_nview) && base.m_nview.IsValid() && base.m_nview.IsOwner())
			{
				base.m_nview.GetZDO().Set(Keys.State, (int)s, false);
			}
		}

		public override void OnDeath()
		{
			//IL_0018: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).OnDeath();
			CloseLid();
			_carry.DropAll();
			ZDOID stationId = StationId;
			ZDO val = (((ZDOID)(ref stationId)).IsNone() ? null : ZDOMan.instance.GetZDO(stationId));
			if (val != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(val.GetOwner(), stationId, "gs_WorkerDied", Array.Empty<object>());
			}
		}

		private void UpdateIdleCustom(float dt, SorterStation station, bool tick)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).RandomMovementArroundPoint(dt, ((Component)station).transform.position, 4f, ModConfig.Run.Value);
			if (tick && !(Time.time - _stateStart < ModConfig.IdleSeconds.Value))
			{
				DecideCustom(station);
			}
		}

		private void DecideCustom(SorterStation station)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			List<Tame> tames = Herd.Around(((Component)station).transform.position, ModConfig.WorkRadius.Value);
			NoteHerd(tames);
			if (HusbandryWithCarry(station, tames) || ContinuePlantingTrip(station))
			{
				return;
			}
			HashSet<string> inUse = new HashSet<string>();
			OfferSorting(station);
			OfferSmelting(station, inUse);
			OfferUpkeep(station, inUse);
			float bonus = OfferFarming(station, inUse);
			OfferHusbandry(station, tames);
			OfferDelivery(station, inUse, bonus);
			if (!TakeBestJob())
			{
				if (station.Priority(WorkTask.Planting) > 0 && _soil.FreeCells.Count > 0)
				{
					ReportIdleSoil(station);
				}
				SetState(State.Idle);
			}
		}

		private void OfferSorting(SorterStation station)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (!_carry.Inventory.HaveEmptySlot())
			{
				return;
			}
			int num = station.Container.GetInventory().GetAllItems().Count((ItemData i) => Placeable(station, i));
			if (num != 0)
			{
				_offerTask = WorkTask.SortNest;
				Offer($"sort {num} stacks from the nest", station.SpawnPosition, (float)Mathf.Min(num, ModConfig.CarryStacks.Value) * 1.5f + 0.5f, ModConfig.DepositSeconds.Value, delegate
				{
					SetState(State.Load);
				});
			}
		}

		private bool TaskOn(WorkTask t)
		{
			if (Object.op_Implicit((Object)(object)_station))
			{
				return _station.Priority(t) > 0;
			}
			return false;
		}

		private bool TryStartDoorCrossing(Vector3 goal)
		{
			//IL_0001: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Vector3 bestNear;
			Vector3 bestFar;
			Door val = FindCrossing(goal, anyDoor: false, out bestNear, out bestFar);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			_door = val;
			_doorNear = bestNear;
			_doorFar = bestFar;
			_crossPhase = CrossPhase.Approach;
			_crossStart = Time.time;
			_openedDoor = false;
			_doorTried[((Object)val).GetInstanceID()] = Time.time + 15f;
			_lastCrossDoor = val;
			_lastCrossFrom = bestNear;
			_lastCrossTime = Time.time;
			ForgetPath();
			Plugin.Log.LogInfo((object)$"Kvist: going through {val.m_name} at {((Component)val).transform.position}");
			return true;
		}

		private Door FindCrossing(Vector3 goal, bool anyDoor, out Vector3 bestNear, out Vector3 bestFar)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_018f: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			Door result = null;
			float num = float.MaxValue;
			bes