Decompiled source of BUG DeliveryItemChain v1.0.0

BUG_DeliveryItemChain.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[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 DeliveryItemChain
{
	public static class ChainUI
	{
		private sealed class CellView
		{
			public GameObject go;

			public UIButton button;

			public Image icon;

			public InputField limit;

			public ItemProto proto;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Hide;
		}

		private const float Cell = 46f;

		private const float CellH = 66f;

		private const float Left = 20f;

		private const float TabTop = 44f;

		private const float Tab = 70f;

		private const float GridTop = 124f;

		private const int MaxRows = 12;

		private const int MaxCols = 17;

		private static readonly Color Ink = Color32.op_Implicit(new Color32((byte)232, (byte)246, (byte)252, byte.MaxValue));

		private static readonly Color Soft = Color32.op_Implicit(new Color32((byte)176, (byte)208, (byte)220, byte.MaxValue));

		private static readonly Color Accent = Color32.op_Implicit(new Color32((byte)253, (byte)150, (byte)94, byte.MaxValue));

		private static readonly Color AccentInk = Color32.op_Implicit(new Color32((byte)28, (byte)14, (byte)6, byte.MaxValue));

		private static readonly Color Scrim = Color32.op_Implicit(new Color32((byte)4, (byte)22, (byte)30, (byte)168));

		private static readonly Color Well = Color32.op_Implicit(new Color32((byte)0, (byte)10, (byte)16, (byte)150));

		private static readonly Color[] Glass = (Color[])(object)new Color[4]
		{
			Color32.op_Implicit(new Color32((byte)167, (byte)233, byte.MaxValue, (byte)40)),
			Color32.op_Implicit(new Color32((byte)167, (byte)233, byte.MaxValue, (byte)92)),
			Color32.op_Implicit(new Color32((byte)167, (byte)233, byte.MaxValue, (byte)32)),
			Ink
		};

		private static readonly Color Faded = new Color(1f, 1f, 1f, 0.5f);

		private static UIDispenserWindow host;

		private static Image openIcon;

		private static Text openCount;

		private static UIButton openTip;

		private static GameObject openWhite;

		private static GameObject win;

		private static RectTransform root;

		private static Text summary;

		private static GameObject cellTpl;

		private static readonly List<GameObject> tabs = new List<GameObject>();

		private static readonly List<CellView> cells = new List<CellView>();

		private static Dictionary<int, List<ItemProto>> pages;

		private static int page;

		private static int rows;

		private static int cols;

		private const float SlotShift = 28f;

		private static PlanetFactory Factory
		{
			get
			{
				if (!((Object)(object)host == (Object)null))
				{
					return host.factory;
				}
				return null;
			}
		}

		private static DispenserComponent Dispenser
		{
			get
			{
				PlanetFactory factory = Factory;
				int num = ((!((Object)(object)host == (Object)null)) ? host.dispenserId : 0);
				if (factory != null && num > 0)
				{
					return factory.transport.dispenserPool[num];
				}
				return null;
			}
		}

		private static Chain Current
		{
			get
			{
				if (Factory != null)
				{
					return Store.Get(Factory.planetId, host.dispenserId);
				}
				return null;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIDispenserWindow), "_OnOpen")]
		private static void OnOpen(UIDispenserWindow __instance)
		{
			host = __instance;
			if ((Object)(object)openIcon == (Object)null)
			{
				BuildOpener(__instance);
			}
			RefreshOpener();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIDispenserWindow), "OnDispenserIdChange")]
		private static void OnIdChange(UIDispenserWindow __instance)
		{
			host = __instance;
			if ((Object)(object)openIcon == (Object)null)
			{
				return;
			}
			RefreshOpener();
			if ((Object)(object)win != (Object)null && win.activeSelf)
			{
				if (__instance.dispenserId > 0)
				{
					RefreshCells();
				}
				else
				{
					Hide();
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIDispenserWindow), "_OnClose")]
		private static void OnClose()
		{
			Hide();
		}

		private static void Hide()
		{
			if ((Object)(object)win != (Object)null)
			{
				win.SetActive(false);
			}
		}

		private static void BuildOpener(UIDispenserWindow w)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_004b: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)w.selectItemButton).gameObject;
			GameObject obj = Object.Instantiate<GameObject>(gameObject, gameObject.transform.parent, false);
			((Object)obj).name = "item-chain-slot";
			StripLocalizers(obj);
			obj.SetActive(true);
			RectTransform val = (RectTransform)obj.transform;
			val.anchoredPosition = new Vector2(108f, -24f);
			((Transform)val).localScale = new Vector3(0.5f, 0.5f, 1f);
			Transform obj2 = ((Transform)val).Find("white");
			openWhite = ((obj2 != null) ? ((Component)obj2).gameObject : null);
			openTip = obj.GetComponent<UIButton>();
			openTip.onClick += delegate
			{
				Toggle();
			};
			openTip.highlighted = false;
			if ((Object)(object)openTip.button != (Object)null)
			{
				((Selectable)openTip.button).interactable = true;
			}
			openTip.tips.itemId = 0;
			openTip.tips.type = (ItemTipType)2;
			if (openTip.tips.corner == 0)
			{
				openTip.tips.corner = 2;
			}
			openTip.tips.width = 220;
			openIcon = NewImage((Transform)(object)val, new Vector2(54f, 54f));
			((Graphic)openIcon).raycastTarget = true;
			openCount = Object.Instantiate<Text>(w.playerModeText, (Transform)(object)val, false);
			StripLocalizers(((Component)openCount).gameObject);
			((Graphic)openCount).material = null;
			((Graphic)openCount).raycastTarget = false;
			openCount.alignment = (TextAnchor)8;
			openCount.fontSize = 24;
			((Graphic)openCount).color = Ink;
			RectTransform rectTransform = ((Graphic)openCount).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.pivot = new Vector2(0.5f, 0.5f);
			rectTransform.anchoredPosition = new Vector2(2f, -2f);
			rectTransform.sizeDelta = Vector2.zero;
			RectTransform val2 = (RectTransform)((Component)w.playerModeToggle).transform.parent;
			val2.anchoredPosition += new Vector2(28f, 0f);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIDispenserWindow), "ValueToUI")]
		private static void AfterValueToUI(UIDispenserWindow __instance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)openIcon != (Object)null)
			{
				RectTransform storageModeBox = __instance.storageModeBox;
				storageModeBox.anchoredPosition += new Vector2(28f, 0f);
			}
		}

		private static void RefreshOpener()
		{
			Chain current = Current;
			int num = ((current != null) ? current.Items.Length : 0);
			ItemProto val = ((num > 0) ? ((ProtoSet<ItemProto>)(object)LDB.items).Select(current.Items[0]) : null);
			openIcon.sprite = ((val != null) ? val.iconSprite : null);
			((Behaviour)openIcon).enabled = val != null;
			if ((Object)(object)openWhite != (Object)null)
			{
				openWhite.SetActive(val == null);
			}
			openCount.text = ((num > 1) ? num.ToString(CultureInfo.InvariantCulture) : "");
			StringBuilder stringBuilder = new StringBuilder();
			if (num == 0)
			{
				stringBuilder.Append("No chain items. Click to choose more items for this distributor.");
			}
			for (int i = 0; i < num; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append('\n');
				}
				ItemProto obj = ((ProtoSet<ItemProto>)(object)LDB.items).Select(current.Items[i]);
				stringBuilder.Append(((obj != null) ? ((Proto)obj).name : null) ?? ("#" + current.Items[i]));
				stringBuilder.Append((current.Limits[i] > 0) ? ("  max " + current.Limits[i].ToString("N0", CultureInfo.InvariantCulture)) : "  unlimited");
			}
			openTip.tips.tipTitle = "Item chain";
			openTip.tips.tipText = stringBuilder.ToString();
		}

		private static void Toggle()
		{
			//IL_0075: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)win != (Object)null && win.activeSelf)
			{
				Hide();
			}
			else
			{
				if (Dispenser == null)
				{
					return;
				}
				if ((Object)(object)win == (Object)null)
				{
					BuildWindow();
				}
				LoadPages();
				Layout();
				win.SetActive(true);
				win.transform.SetAsLastSibling();
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				((RectTransform)((Component)host).transform).GetWorldCorners(array);
				root.GetWorldCorners(array2);
				float num = 10f * ((Transform)root).lossyScale.x;
				RectTransform obj = root;
				((Transform)obj).position = ((Transform)obj).position + new Vector3(array[1].x - num - array2[2].x, array[1].y - array2[1].y, 0f);
				Canvas componentInParent = ((Component)root).GetComponentInParent<Canvas>();
				Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
				if (!((Object)(object)val == (Object)null))
				{
					Vector3[] array3 = (Vector3[])(object)new Vector3[4];
					((RectTransform)((Component)val).transform).GetWorldCorners(array3);
					root.GetWorldCorners(array2);
					if (array2[0].x < array3[0].x)
					{
						RectTransform obj2 = root;
						((Transform)obj2).position = ((Transform)obj2).position + new Vector3(array[2].x + num - array2[0].x, 0f, 0f);
					}
					root.GetWorldCorners(array2);
					if (array2[2].x > array3[2].x)
					{
						RectTransform obj3 = root;
						((Transform)obj3).position = ((Transform)obj3).position + new Vector3(array3[2].x - array2[2].x, 0f, 0f);
					}
					if (array2[0].y < array3[0].y)
					{
						RectTransform obj4 = root;
						((Transform)obj4).position = ((Transform)obj4).position + new Vector3(0f, array3[0].y - array2[0].y, 0f);
					}
				}
			}
		}

		private static Dictionary<int, GameObject> ReplicatorTabs()
		{
			UIReplicatorWindow replicator = UIRoot.instance.uiGame.replicator;
			Dictionary<int, GameObject> dictionary = new Dictionary<int, GameObject>();
			if ((Object)(object)replicator == (Object)null)
			{
				return dictionary;
			}
			MonoBehaviour[] componentsInChildren = ((Component)replicator).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "UITabButton")
				{
					dictionary[Traverse.Create((object)val).Field<int>("tabIndex").Value] = ((Component)val).gameObject;
				}
			}
			if ((Object)(object)replicator.typeButton1 != (Object)null)
			{
				dictionary[1] = ((Component)replicator.typeButton1).gameObject;
			}
			if ((Object)(object)replicator.typeButton2 != (Object)null)
			{
				dictionary[2] = ((Component)replicator.typeButton2).gameObject;
			}
			return dictionary;
		}

		private static void LoadPages()
		{
			pages = new Dictionary<int, List<ItemProto>>();
			rows = (cols = 1);
			GameHistoryData history = GameMain.history;
			ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
			foreach (ItemProto val in dataArray)
			{
				if (val == null || val.GridIndex < 1101 || ((Proto)val).ID == 1099 || !history.ItemUnlocked(((Proto)val).ID))
				{
					continue;
				}
				int key = val.GridIndex / 1000;
				int num = val.GridIndex % 1000 / 100 - 1;
				int num2 = val.GridIndex % 100 - 1;
				if (num >= 0 && num2 >= 0 && num < 12 && num2 < 17)
				{
					if (!pages.TryGetValue(key, out var value))
					{
						value = (pages[key] = new List<ItemProto>());
					}
					value.Add(val);
					rows = Math.Max(rows, num + 1);
					cols = Math.Max(cols, num2 + 1);
				}
			}
			if (!pages.ContainsKey(page))
			{
				page = 0;
			}
			if (page != 0)
			{
				return;
			}
			foreach (int key2 in pages.Keys)
			{
				if (page == 0 || key2 < page)
				{
					page = key2;
				}
			}
		}

		private static void Layout()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_0111: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0135: 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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			float num = Math.Max((float)cols * 46f + 40f, 420f);
			float num2 = 124f + (float)rows * 66f + 44f;
			root.sizeDelta = new Vector2(num, num2);
			foreach (GameObject tab in tabs)
			{
				Object.Destroy((Object)(object)tab);
			}
			tabs.Clear();
			List<int> list = new List<int>(pages.Keys);
			list.Sort();
			Dictionary<int, GameObject> dictionary = ReplicatorTabs();
			Vector2 val = default(Vector2);
			Vector2 val4 = default(Vector2);
			for (int i = 0; i < list.Count; i++)
			{
				int key = list[i];
				((Vector2)(ref val))..ctor(20f + (float)i * 72f, -44f);
				GameObject val2;
				if (dictionary.TryGetValue(key, out var value))
				{
					val2 = Object.Instantiate<GameObject>(value, (Transform)(object)root, false);
					val2.SetActive(true);
					RectTransform val3 = (RectTransform)val2.transform;
					((Vector2)(ref val4))..ctor(0f, 1f);
					val3.pivot = val4;
					Vector2 anchorMin = (val3.anchorMax = val4);
					val3.anchorMin = anchorMin;
					val3.anchoredPosition = val;
					val3.sizeDelta = new Vector2(70f, 70f);
					val2.GetComponentInChildren<UIButton>(true).onClick += delegate
					{
						page = key;
						Layout();
					};
				}
				else
				{
					ItemProto val6 = pages[key][0];
					foreach (ItemProto item in pages[key])
					{
						if (item.GridIndex < val6.GridIndex)
						{
							val6 = item;
						}
					}
					val2 = NewButton((Transform)(object)root, val, new Vector2(70f, 70f), (UnityAction)delegate
					{
						page = key;
						Layout();
					});
					NewImage(val2.transform, new Vector2(32f, 32f)).sprite = val6.iconSprite;
				}
				UIButton componentInChildren = val2.GetComponentInChildren<UIButton>(true);
				componentInChildren.highlighted = key == page;
				if ((Object)(object)componentInChildren.button != (Object)null)
				{
					((Selectable)componentInChildren.button).interactable = key != page;
				}
				tabs.Add(val2);
			}
			for (int num3 = cells.Count; num3 < rows * cols; num3++)
			{
				cells.Add(NewCell());
			}
			for (int num4 = 0; num4 < cells.Count; num4++)
			{
				CellView cellView = cells[num4];
				cellView.proto = null;
				cellView.go.SetActive(false);
				((RectTransform)cellView.go.transform).anchoredPosition = new Vector2(20f + (float)(num4 % cols) * 46f, -124f - (float)(num4 / cols) * 66f);
			}
			if (pages.TryGetValue(page, out var value2))
			{
				foreach (ItemProto item2 in value2)
				{
					CellView cellView2 = cells[(item2.GridIndex % 1000 / 100 - 1) * cols + item2.GridIndex % 100 - 1];
					cellView2.proto = item2;
					cellView2.go.SetActive(true);
					cellView2.icon.sprite = item2.iconSprite;
					cellView2.button.tips.itemId = ((Proto)item2).ID;
				}
			}
			RefreshCells();
		}

		private static void RefreshCells()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Chain current = Current;
			foreach (CellView cell in cells)
			{
				if (cell.proto != null)
				{
					bool flag = current?.Has(((Proto)cell.proto).ID) ?? false;
					((Graphic)cell.icon).color = (flag ? Color.white : Faded);
					cell.button.highlighted = flag;
					((Component)cell.limit).gameObject.SetActive(flag);
					if (flag && !cell.limit.isFocused)
					{
						int num = current.Limit(((Proto)cell.proto).ID);
						cell.limit.text = ((num > 0) ? num.ToString(CultureInfo.InvariantCulture) : "");
					}
				}
			}
			int num2 = current?.Extra(Dispenser?.filter ?? 0) ?? 0;
			summary.text = num2 + " / " + Tech.Capacity + " chained items";
			RefreshOpener();
		}

		private static void Pick(int item)
		{
			Chain chain = Current ?? new Chain(new int[0], new int[0]);
			int num = Dispenser?.filter ?? 0;
			if (!chain.Has(item) && item != num && chain.Extra(num) >= Tech.Capacity)
			{
				UIRealtimeTip.Popup("Chain is full: research Distributor Item Chain for more (" + Tech.Capacity + "/" + 10 + ")", false, 0);
			}
			else
			{
				Apply((Chain x) => x.Toggle(item));
			}
		}

		private static void Apply(Func<Chain, Chain> change)
		{
			PlanetFactory factory = Factory;
			if (factory != null && Dispenser != null)
			{
				Store.Set(factory.planetId, host.dispenserId, change(Current ?? new Chain(new int[0], new int[0])));
				factory.transport.RefreshDispenserTraffic(0);
				RefreshCells();
			}
		}

		private static CellView NewCell()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			CellView v = new CellView();
			v.go = new GameObject("cell", new Type[1] { typeof(RectTransform) });
			RectTransform val = (RectTransform)v.go.transform;
			((Transform)val).SetParent((Transform)(object)root, false);
			Place(val, Vector2.zero, new Vector2(46f, 66f));
			GameObject val2 = NewButton((Transform)(object)val, new Vector2(2f, 0f), new Vector2(42f, 42f), (UnityAction)delegate
			{
				if (v.proto != null)
				{
					Pick(((Proto)v.proto).ID);
				}
			});
			v.button = val2.GetComponent<UIButton>();
			v.button.tips.type = (ItemTipType)0;
			v.button.tips.tipTitle = "";
			v.button.tips.corner = 2;
			v.button.tips.delay = 0.4f;
			v.icon = NewImage(val2.transform, new Vector2(36f, 36f));
			v.limit = NewField((Transform)(object)val, new Vector2(1f, -45f), new Vector2(44f, 18f));
			((UnityEvent<string>)(object)v.limit.onEndEdit).AddListener((UnityAction<string>)delegate(string text)
			{
				if (v.proto != null)
				{
					Apply((Chain c) => c.WithLimit(((Proto)v.proto).ID, Chain.ParseLimit(text)));
				}
			});
			return v;
		}

		private static void BuildWindow()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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)
			//IL_011c: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			Transform transform = ((Component)UIRoot.instance.uiGame.generatorWindow).transform;
			cellTpl = ((Component)transform.Find("ray-receiver/switch-button-1")).gameObject;
			win = Object.Instantiate<GameObject>(((Component)transform).gameObject, ((Component)host).transform.parent, false);
			((Object)win).name = "DeliveryItemChain";
			Object.DestroyImmediate((Object)(object)win.GetComponent<UIPowerGeneratorWindow>());
			foreach (Transform item in win.transform)
			{
				Transform val = item;
				if (((Object)val).name != "panel-bg")
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			RectTransform val2 = (RectTransform)win.transform.Find("panel-bg/btn-box");
			Object.DestroyImmediate((Object)(object)((Component)((Transform)val2).Find("menu-wnd-btn")).gameObject);
			val2.sizeDelta = new Vector2(48f, val2.sizeDelta.y);
			val2.anchoredPosition += new Vector2(8f, 0f);
			((RectTransform)((Transform)val2).Find("close-wnd-btn")).anchoredPosition = new Vector2(8f, 0f);
			StripLocalizers(win);
			Backdrop(win.transform.Find("panel-bg"));
			Button component = ((Component)win.transform.Find("panel-bg/btn-box/close-wnd-btn")).GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>O.<0>__Hide;
			if (obj == null)
			{
				UnityAction val3 = Hide;
				<>O.<0>__Hide = val3;
				obj = (object)val3;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			((Component)win.transform.Find("panel-bg/title-text")).GetComponent<Text>().text = "Item Chain";
			root = (RectTransform)win.transform;
			Text playerModeText = host.playerModeText;
			summary = NewText(playerModeText, (Transform)(object)root, new Vector2(-40f, -58f), new Vector2(200f, 24f), (TextAnchor)5);
			RectTransform rectTransform = ((Graphic)summary).rectTransform;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(1f, 1f);
			rectTransform.pivot = val4;
			Vector2 anchorMin = (rectTransform.anchorMax = val4);
			rectTransform.anchorMin = anchorMin;
			Text obj2 = NewText(playerModeText, (Transform)(object)root, new Vector2(20f, 14f), new Vector2(600f, 24f), (TextAnchor)3);
			RectTransform rectTransform2 = ((Graphic)obj2).rectTransform;
			((Vector2)(ref val4))..ctor(0f, 0f);
			rectTransform2.pivot = val4;
			anchorMin = (rectTransform2.anchorMax = val4);
			rectTransform2.anchorMin = anchorMin;
			obj2.text = "Click an item to add or remove it. Box under an item: most this depot holds; empty = unlimited.";
			obj2.fontSize = 12;
			win.SetActive(false);
		}

		private static GameObject NewButton(Transform parent, Vector2 pos, Vector2 size, UnityAction onClick)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(cellTpl, parent, false);
			StripLocalizers(val);
			val.SetActive(true);
			Place((RectTransform)val.transform, pos, size);
			Text[] componentsInChildren = val.GetComponentsInChildren<Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = "";
			}
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(onClick);
			UIButton component2 = val.GetComponent<UIButton>();
			component2.tips.tipTitle = "";
			component2.tips.tipText = "";
			Style(val, Glass);
			return val;
		}

		private static Image NewImage(Transform parent, Vector2 size)
		{
			//IL_0025: 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_0066: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Image component = new GameObject("icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			}).GetComponent<Image>();
			((Component)component).transform.SetParent(parent, false);
			RectTransform rectTransform = ((Graphic)component).rectTransform;
			RectTransform rectTransform2 = ((Graphic)component).rectTransform;
			RectTransform rectTransform3 = ((Graphic)component).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rectTransform3.pivot = val;
			Vector2 anchorMin = (rectTransform2.anchorMax = val);
			rectTransform.anchorMin = anchorMin;
			((Graphic)component).rectTransform.sizeDelta = size;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private static Text NewText(Text tpl, Transform parent, Vector2 pos, Vector2 size, TextAnchor alignment)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Text obj = Object.Instantiate<Text>(tpl, parent, false);
			StripLocalizers(((Component)obj).gameObject);
			Place(((Graphic)obj).rectTransform, pos, size);
			((Graphic)obj).material = null;
			obj.alignment = alignment;
			obj.horizontalOverflow = (HorizontalWrapMode)1;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).color = Soft;
			obj.text = "";
			return obj;
		}

		private static InputField NewField(Transform parent, Vector2 pos, Vector2 size)
		{
			//IL_0025: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			Image component = new GameObject("limit", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			}).GetComponent<Image>();
			((Component)component).transform.SetParent(parent, false);
			Place(((Graphic)component).rectTransform, pos, size);
			((Graphic)component).color = Well;
			Text val = NewText(host.playerModeText, ((Component)component).transform, new Vector2(2f, 0f), new Vector2(size.x - 4f, size.y), (TextAnchor)4);
			val.horizontalOverflow = (HorizontalWrapMode)0;
			val.supportRichText = false;
			val.fontSize = 11;
			((Graphic)val).color = Ink;
			Text val2 = NewText(host.playerModeText, ((Component)component).transform, new Vector2(2f, 0f), new Vector2(size.x - 4f, size.y), (TextAnchor)4);
			val2.fontSize = 12;
			val2.text = "∞";
			InputField obj = ((Component)component).gameObject.AddComponent<InputField>();
			obj.textComponent = val;
			obj.placeholder = (Graphic)(object)val2;
			((Selectable)obj).targetGraphic = (Graphic)(object)component;
			obj.contentType = (ContentType)2;
			obj.characterLimit = 9;
			obj.caretColor = Ink;
			obj.selectionColor = Color32.op_Implicit(new Color32((byte)253, (byte)150, (byte)94, (byte)110));
			return obj;
		}

		private static void Style(GameObject go, Color[] palette)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			UIButton component = go.GetComponent<UIButton>();
			if (component.transitions != null)
			{
				Transition[] transitions = component.transitions;
				foreach (Transition val in transitions)
				{
					if (!((Object)(object)val.target == (Object)null))
					{
						bool flag = val.target is Text;
						val.normalColor = (val.disabledColor = (flag ? palette[3] : palette[0]));
						val.mouseoverColor = (flag ? palette[3] : palette[1]);
						val.pressedColor = (flag ? palette[3] : palette[2]);
						val.highlightColorOverride = (Color)(flag ? AccentInk : new Color(Accent.r, Accent.g, Accent.b, 0.45f));
						val.alphaOnly = false;
						val.mouseoverSize = (val.pressedSize = (val.highlightSizeMultiplier = 1f));
					}
				}
			}
			component.highlighted = false;
			((Selectable)go.GetComponent<Button>()).transition = (Transition)0;
			Image component2 = go.GetComponent<Image>();
			((Graphic)component2).material = null;
			((Graphic)component2).color = palette[0];
		}

		private static void Backdrop(Transform panel)
		{
			//IL_002c: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_009b: 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)
			Image component = ((Component)panel).GetComponent<Image>();
			Image component2 = new GameObject("scrim", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			}).GetComponent<Image>();
			((Component)component2).transform.SetParent(panel, false);
			((Component)component2).transform.SetAsFirstSibling();
			((Graphic)component2).rectTransform.anchorMin = Vector2.zero;
			((Graphic)component2).rectTransform.anchorMax = Vector2.one;
			RectTransform rectTransform = ((Graphic)component2).rectTransform;
			Vector2 anchoredPosition = (((Graphic)component2).rectTransform.sizeDelta = Vector2.zero);
			rectTransform.anchoredPosition = anchoredPosition;
			component2.sprite = component.sprite;
			component2.type = component.type;
			((Graphic)component2).color = Scrim;
			((Graphic)component2).raycastTarget = false;
		}

		private static void Place(RectTransform rt, Vector2 pos, Vector2 size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rt.pivot = val;
			Vector2 anchorMin = (rt.anchorMax = val);
			rt.anchorMin = anchorMin;
			rt.anchoredPosition = pos;
			rt.sizeDelta = size;
			((Transform)rt).localScale = Vector3.one;
		}

		private static void StripLocalizers(GameObject go)
		{
			Localizer[] componentsInChildren = go.GetComponentsInChildren<Localizer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}
	}
	public sealed class Chain
	{
		public readonly int[] Items;

		public readonly int[] Limits;

		public Slot[] Slots = new Slot[0];

		internal int Cursor;

		public Chain(int[] items, int[] limits)
		{
			Items = items;
			Limits = limits;
		}

		public bool Has(int item)
		{
			return Array.IndexOf(Items, item) >= 0;
		}

		public int Limit(int item)
		{
			int num = Array.IndexOf(Items, item);
			if (num >= 0)
			{
				return Limits[num];
			}
			return 0;
		}

		public Chain Toggle(int item)
		{
			int num = Array.IndexOf(Items, item);
			List<int> list = new List<int>(Items);
			List<int> list2 = new List<int>(Limits);
			if (num >= 0)
			{
				list.RemoveAt(num);
				list2.RemoveAt(num);
			}
			else
			{
				list.Add(item);
				list2.Add(0);
			}
			return new Chain(list.ToArray(), list2.ToArray());
		}

		public Chain Take(int n)
		{
			if (n < Items.Length)
			{
				return new Chain(Sub(Items, n), Sub(Limits, n));
			}
			return this;
		}

		private static int[] Sub(int[] a, int n)
		{
			int[] array = new int[Math.Max(0, n)];
			Array.Copy(a, array, array.Length);
			return array;
		}

		public int Extra(int filter)
		{
			return Items.Length - (Has(filter) ? 1 : 0);
		}

		public Chain WithLimit(int item, int limit)
		{
			int[] array = (int[])Limits.Clone();
			int num = Array.IndexOf(Items, item);
			if (num >= 0)
			{
				array[num] = Math.Max(0, limit);
			}
			return new Chain(Items, array);
		}

		internal Slot SlotFor(int item)
		{
			Slot[] slots = Slots;
			foreach (Slot slot in slots)
			{
				if (slot.Item == item)
				{
					return slot;
				}
			}
			return null;
		}

		internal void ResetSlots(int filter)
		{
			List<Slot> list = new List<Slot>();
			int[] items = Items;
			foreach (int num in items)
			{
				if (num > 0 && num != 1099 && num != filter)
				{
					Slot slot = SlotFor(num) ?? new Slot
					{
						Item = num
					};
					slot.Count = (slot.PlayerCount = 0);
					list.Add(slot);
				}
			}
			Slots = list.ToArray();
			if (Cursor > Slots.Length)
			{
				Cursor = 0;
			}
		}

		public static int ParseLimit(string text)
		{
			if (!int.TryParse((text ?? "").Trim(), NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result <= 0)
			{
				return 0;
			}
			return result;
		}
	}
	public sealed class Slot
	{
		public int Item;

		public int Count;

		public int PlayerCount;

		public int Process;

		public SupplyDemandPair[] Pairs = (SupplyDemandPair[])(object)new SupplyDemandPair[8];

		public void Add(int sId, int sIdx, int dId, int dIdx)
		{
			//IL_0094: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < Count; i++)
			{
				if (Pairs[i].supplyId == sId && Pairs[i].supplyIndex == sIdx && Pairs[i].demandId == dId && Pairs[i].demandIndex == dIdx)
				{
					return;
				}
			}
			if (Count == Pairs.Length)
			{
				Array.Resize(ref Pairs, Count * 2);
			}
			Pairs[Count] = new SupplyDemandPair
			{
				supplyId = sId,
				supplyIndex = sIdx,
				demandId = dId,
				demandIndex = dIdx
			};
			Count++;
			if (sId < 0 || dId < 0)
			{
				PlayerCount++;
			}
		}
	}
	public static class Store
	{
		private static readonly object gate = new object();

		private static volatile Dictionary<long, Chain> map = new Dictionary<long, Chain>();

		public static bool Empty => map.Count == 0;

		public static Dictionary<long, Chain> Snapshot => map;

		public static long Key(int planetId, int dispenserId)
		{
			return ((long)planetId << 32) | (uint)dispenserId;
		}

		public static Chain Get(int planetId, int dispenserId)
		{
			Dictionary<long, Chain> dictionary = map;
			if (dictionary.Count == 0 || !dictionary.TryGetValue(Key(planetId, dispenserId), out var value))
			{
				return null;
			}
			return value;
		}

		public static void Set(int planetId, int dispenserId, Chain chain)
		{
			lock (gate)
			{
				Dictionary<long, Chain> dictionary = new Dictionary<long, Chain>(map);
				if (chain == null || chain.Items.Length == 0)
				{
					dictionary.Remove(Key(planetId, dispenserId));
				}
				else
				{
					dictionary[Key(planetId, dispenserId)] = chain;
				}
				map = dictionary;
			}
		}

		public static void Replace(Dictionary<long, Chain> all)
		{
			lock (gate)
			{
				map = all;
			}
		}

		public static void Export(BinaryWriter w)
		{
			Dictionary<long, Chain> dictionary = map;
			w.Write(1);
			w.Write(dictionary.Count);
			foreach (KeyValuePair<long, Chain> item in dictionary)
			{
				w.Write(item.Key);
				w.Write(item.Value.Items.Length);
				for (int i = 0; i < item.Value.Items.Length; i++)
				{
					w.Write(item.Value.Items[i]);
					w.Write(item.Value.Limits[i]);
				}
			}
		}

		public static Dictionary<long, Chain> Read(BinaryReader r)
		{
			int num = r.ReadInt32();
			if (num != 1)
			{
				throw new InvalidDataException("Unknown DeliveryItemChain save version " + num);
			}
			int num2 = r.ReadInt32();
			Dictionary<long, Chain> dictionary = new Dictionary<long, Chain>(num2);
			for (int i = 0; i < num2; i++)
			{
				long key = r.ReadInt64();
				int num3 = r.ReadInt32();
				int[] array = new int[num3];
				int[] array2 = new int[num3];
				for (int j = 0; j < num3; j++)
				{
					array[j] = r.ReadInt32();
					array2[j] = r.ReadInt32();
				}
				if (num3 > 0)
				{
					dictionary[key] = new Chain(array, array2);
				}
			}
			return dictionary;
		}
	}
	public static class Pairing
	{
		public const int Sand = 1099;

		private static bool Carries(DispenserComponent d, Chain c, int item)
		{
			if (item > 0)
			{
				if (d.filter != item)
				{
					return c?.Has(item) ?? false;
				}
				return true;
			}
			return false;
		}

		private static void Add(DispenserComponent d, Chain c, int item, int sId, int dId)
		{
			if (d.filter == item)
			{
				for (int i = 0; i < d.pairCount; i++)
				{
					if (d.pairs[i].supplyId == sId && d.pairs[i].demandId == dId && d.pairs[i].supplyIndex == 0 && d.pairs[i].demandIndex == 0)
					{
						return;
					}
				}
				d.AddPair(sId, 0, dId, 0);
			}
			else
			{
				c.SlotFor(item)?.Add(sId, 0, dId, 0);
			}
		}

		public static void Build(int planetId, DispenserComponent[] pool, int cursor, DeliveryPackage package, bool playerEnabled)
		{
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Invalid comparison between Unknown and I4
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Invalid comparison between Unknown and I4
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Invalid comparison between Unknown and I4
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Invalid comparison between Unknown and I4
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Invalid comparison between Unknown and I4
			Chain[] array = new Chain[cursor];
			bool flag = false;
			for (int i = 1; i < cursor; i++)
			{
				DispenserComponent val = pool[i];
				if (val != null && val.id == i)
				{
					Chain chain = Store.Get(planetId, i);
					if (chain != null)
					{
						chain.ResetSlots(val.filter);
						array[i] = chain;
						flag = true;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			if (playerEnabled && package != null)
			{
				GRID[] grids = package.grids;
				for (int j = 0; j < grids.Length; j++)
				{
					int itemId = grids[j].itemId;
					if (itemId <= 0 || itemId == 1099 || !package.IsGridActive(j))
					{
						continue;
					}
					for (int k = 1; k < cursor; k++)
					{
						Slot slot = array[k]?.SlotFor(itemId);
						if (slot != null)
						{
							EPlayerDeliveryMode playerMode = pool[k].playerMode;
							if ((int)playerMode == 3 || (int)playerMode == 2)
							{
								slot.Add(k, 0, -(j + 1), j);
							}
							if ((int)playerMode == 1 || (int)playerMode == 2)
							{
								slot.Add(-(j + 1), j, k, 0);
							}
						}
					}
				}
			}
			for (int l = 1; l < cursor; l++)
			{
				Chain chain2 = array[l];
				if (chain2 == null)
				{
					continue;
				}
				DispenserComponent val2 = pool[l];
				if ((int)val2.storageMode == 0)
				{
					continue;
				}
				for (int m = 1; m < cursor; m++)
				{
					DispenserComponent val3 = pool[m];
					if (m == l || val3 == null || val3.id != m || (array[m] != null && m < l))
					{
						continue;
					}
					bool flag2 = (int)val2.storageMode == 1 && (int)val3.storageMode == 2;
					if (!flag2 && ((int)val2.storageMode != 2 || (int)val3.storageMode != 1))
					{
						continue;
					}
					Chain c = array[m];
					int sId = (flag2 ? l : m);
					int dId = (flag2 ? m : l);
					for (int n = -1; n < chain2.Items.Length; n++)
					{
						int num = ((n < 0) ? val2.filter : chain2.Items[n]);
						if (num > 0 && num != 1099 && (n < 0 || num != val2.filter) && Carries(val3, c, num) && (val2.filter != num || val3.filter != num))
						{
							Add(val2, chain2, num, sId, dId);
							Add(val3, c, num, sId, dId);
						}
					}
				}
			}
		}

		public static Chain FromStock(DispenserComponent d)
		{
			List<int> list = new List<int>();
			for (StorageComponent val = d.storage; val != null; val = val.previousStorage)
			{
				for (int i = 0; i < val.size; i++)
				{
					int itemId = val.grids[i].itemId;
					if (itemId > 0 && itemId != 1099 && itemId != d.filter && val.grids[i].count > 0 && !list.Contains(itemId))
					{
						list.Add(itemId);
					}
				}
			}
			return new Chain(list.ToArray(), new int[list.Count]);
		}

		public static int SplitGuess(DispenserComponent d, int cap, Chain existing, out Chain rest)
		{
			int[] items = FromStock(d).Items;
			int num = ((d.filter == 0 && items.Length != 0) ? items[0] : 0);
			int num2 = ((num != 0) ? num : d.filter);
			rest = existing ?? new Chain(new int[0], new int[0]);
			int[] array = items;
			foreach (int num3 in array)
			{
				if (num3 != num2 && !rest.Has(num3) && rest.Extra(num2) < cap)
				{
					rest = rest.Toggle(num3);
				}
			}
			return num;
		}

		public static long Stock(DispenserComponent d, int item)
		{
			long num = 0L;
			for (StorageComponent val = d.storage; val != null; val = val.previousStorage)
			{
				num += val.GetItemCount(item);
			}
			return num;
		}

		public static int Cap(int result, int limit, long stock)
		{
			if (limit > 0)
			{
				return (int)Math.Max(0L, Math.Min(result, limit - stock));
			}
			return result;
		}
	}
	public static class Rotation
	{
		[ThreadStatic]
		public static PlanetFactory factory;

		[ThreadStatic]
		private static Slot slot;

		[ThreadStatic]
		private static int filter;

		[ThreadStatic]
		private static int pairCount;

		[ThreadStatic]
		private static int playerPairCount;

		[ThreadStatic]
		private static int pairProcess;

		[ThreadStatic]
		private static SupplyDemandPair[] pairs;

		[ThreadStatic]
		private static int gene;

		[ThreadStatic]
		private static bool geneMoved;

		public static bool Swapped => slot != null;

		public static void OpenWindow(DispenserComponent d, int phase)
		{
			if (d.gene != phase)
			{
				gene = d.gene;
				geneMoved = true;
				d.gene = phase;
			}
		}

		public static bool Enter(DispenserComponent d, Chain c)
		{
			int num = c.Slots.Length + 1;
			for (int i = 1; i <= num; i++)
			{
				int num2 = (c.Cursor + i) % num;
				bool num3;
				if (num2 != 0)
				{
					num3 = c.Slots[num2 - 1].Count == 0;
				}
				else
				{
					if (d.filter == 0)
					{
						continue;
					}
					num3 = d.pairCount == 0;
				}
				if (!num3)
				{
					c.Cursor = num2;
					if (num2 == 0)
					{
						return false;
					}
					Slot slot = (Rotation.slot = c.Slots[num2 - 1]);
					filter = d.filter;
					pairs = d.pairs;
					pairCount = d.pairCount;
					playerPairCount = d.playerPairCount;
					pairProcess = d.pairProcess;
					d.filter = slot.Item;
					d.pairs = slot.Pairs;
					d.pairCount = slot.Count;
					d.playerPairCount = slot.PlayerCount;
					d.pairProcess = slot.Process;
					return true;
				}
			}
			return false;
		}

		public static void Leave(DispenserComponent d)
		{
			if (geneMoved)
			{
				d.gene = gene;
				geneMoved = false;
			}
			if (slot != null)
			{
				slot.Process = d.pairProcess;
				d.filter = filter;
				d.pairs = pairs;
				d.pairCount = pairCount;
				d.playerPairCount = playerPairCount;
				d.pairProcess = pairProcess;
				slot = null;
				pairs = null;
			}
		}

		internal static Chain ChainOf(DispenserComponent d)
		{
			PlanetFactory val = factory;
			if (val == null || Store.Empty)
			{
				return null;
			}
			DispenserComponent[] array = val.transport?.dispenserPool;
			if (array == null || d.id <= 0 || d.id >= array.Length || array[d.id] != d)
			{
				return null;
			}
			return Store.Get(val.planetId, d.id);
		}
	}
	[BepInPlugin("bug.dsp.deliveryitemchain", "BUG_DeliveryItemChain", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin, IModCanSave
	{
		public const string Guid = "bug.dsp.deliveryitemchain";

		private static bool refreshPending;

		private static GameData energyFor;

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			Harmony val = new Harmony("bug.dsp.deliveryitemchain");
			val.PatchAll(typeof(Patches));
			val.PatchAll(typeof(ChainUI));
			Tech.Log = ((BaseUnityPlugin)this).Logger;
			val.PatchAll(typeof(Tech));
			Patches.HookMultiDistributor(val, ((BaseUnityPlugin)this).Logger);
		}

		private void Update()
		{
			if (GameMain.isRunning && GameMain.data != null)
			{
				if (Tech.Dirty || energyFor != GameMain.data)
				{
					Tech.Dirty = false;
					energyFor = GameMain.data;
					Tech.ApplyEnergy();
				}
				if (refreshPending)
				{
					refreshPending = false;
					RefreshAll();
				}
			}
		}

		public static void RefreshAll()
		{
			GameData data = GameMain.data;
			for (int i = 0; i < data.factoryCount; i++)
			{
				PlanetFactory obj = data.factories[i];
				if (obj != null)
				{
					PlanetTransport transport = obj.transport;
					if (transport != null)
					{
						transport.RefreshDispenserTraffic(0);
					}
				}
			}
		}

		public void Export(BinaryWriter w)
		{
			Store.Export(w);
		}

		public void Import(BinaryReader r)
		{
			Store.Replace(Store.Read(r));
			refreshPending = true;
		}

		public void IntoOtherSave()
		{
			Store.Replace(new Dictionary<long, Chain>());
		}
	}
	public static class Patches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(DispenserComponent), "InternalTick")]
		private static void TickPrefix(DispenserComponent __instance, PlanetFactory factory, long time)
		{
			Rotation.factory = factory;
			if (Store.Empty)
			{
				return;
			}
			Chain chain = Store.Get(factory.planetId, __instance.id);
			if (chain != null)
			{
				int num = (int)(time % 3);
				if (num < 0)
				{
					num += 3;
				}
				Rotation.OpenWindow(__instance, num);
				if (chain.Slots.Length != 0)
				{
					Rotation.Enter(__instance, chain);
				}
			}
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(DispenserComponent), "InternalTick")]
		private static Exception TickFinalizer(DispenserComponent __instance, Exception __exception)
		{
			Rotation.Leave(__instance);
			return __exception;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DispenserComponent), "GuessFilter")]
		private static void GuessPrefix(DispenserComponent __instance, out int __state)
		{
			__state = __instance.filter;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DispenserComponent), "GuessFilter")]
		private static void GuessPostfix(DispenserComponent __instance, PlanetFactory factory, int __state)
		{
			if (__state == 0 && __instance.filter >= 0 && __instance.storage != null && factory != null)
			{
				Chain chain = Store.Get(factory.planetId, __instance.id);
				Chain rest;
				int num = Pairing.SplitGuess(__instance, Tech.Capacity, chain, out rest);
				bool flag = rest != chain && rest.Items.Length != 0;
				if (flag)
				{
					Store.Set(factory.planetId, __instance.id, rest);
				}
				if (num > 0)
				{
					factory.transport.SetDispenserFilter(__instance.id, num);
				}
				else if (flag)
				{
					factory.transport.RefreshDispenserTraffic(0);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DispenserComponent), "OnRematchPairs")]
		private static void RematchPrefix(PlanetFactory factory)
		{
			Rotation.factory = factory;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DispenserComponent), "InsertIntoStoragePrecalc")]
		public static void LimitPostfix(DispenserComponent __instance, int itemId, ref int __result)
		{
			if (__result > 0)
			{
				int num = Rotation.ChainOf(__instance)?.Limit(itemId) ?? 0;
				if (num > 0)
				{
					__result = Pairing.Cap(__result, num, Pairing.Stock(__instance, itemId));
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlanetTransport), "RefreshDispenserTraffic")]
		private static void RefreshPostfix(PlanetTransport __instance)
		{
			if (!Store.Empty && __instance.factory != null)
			{
				Pairing.Build(__instance.factory.planetId, __instance.dispenserPool, __instance.dispenserCursor, __instance.playerDeliveryPackage, __instance.playerDeliveryEnabled);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlanetTransport), "RemoveDispenserComponent")]
		private static void RemovePostfix(PlanetTransport __instance, int id)
		{
			if (!Store.Empty && __instance.factory != null && Store.Get(__instance.factory.planetId, id) != null)
			{
				Store.Set(__instance.factory.planetId, id, null);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EntityBriefInfo), "SetBriefInfo", new Type[]
		{
			typeof(PlanetFactory),
			typeof(int)
		})]
		private static void BriefPostfix(EntityBriefInfo __instance, PlanetFactory _factory, int _entityId)
		{
			if (Store.Empty || _factory == null || _entityId <= 0)
			{
				return;
			}
			int dispenserId = _factory.entityPool[_entityId].dispenserId;
			Chain chain = ((dispenserId > 0) ? Store.Get(_factory.planetId, dispenserId) : null);
			DispenserComponent val = ((chain == null) ? null : _factory.transport.dispenserPool[dispenserId]);
			if (val == null || val.storage == null)
			{
				return;
			}
			int[] items = chain.Items;
			foreach (int num in items)
			{
				if (num != val.filter && num != 5003)
				{
					__instance.resource.items[num] = (int)Math.Min(2147483647L, Pairing.Stock(val, num));
				}
			}
		}

		public static void HookMultiDistributor(Harmony harmony, ManualLogSource log)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("DSPMultiDistributor.Main");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "FiltersMatch", (Type[])null, (Type[])null));
			if (!(methodInfo == null))
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "FiltersMatchPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				log.LogInfo((object)"DSPMultiDistributor found: chain items count as matching filters");
			}
		}

		public static void FiltersMatchPostfix(DispenserComponent left, DispenserComponent right, ref bool __result)
		{
			if (__result || Store.Empty)
			{
				return;
			}
			Chain chain = Rotation.ChainOf(left);
			Chain chain2 = Rotation.ChainOf(right);
			if (chain == null && chain2 == null)
			{
				return;
			}
			int[] array = chain?.Items ?? new int[1] { left.filter };
			foreach (int num in array)
			{
				if (num > 0 && (right.filter == num || (chain2 != null && chain2.Has(num))))
				{
					__result = true;
					return;
				}
			}
			if (chain != null && left.filter > 0 && chain2 != null && chain2.Has(left.filter))
			{
				__result = true;
			}
		}
	}
	public static class Tech
	{
		public const int Chain = 0;

		public const int Charge = 1;

		public const int Storage = 2;

		public const int MaxStage = 10;

		public const int Base = 9310;

		public const double ChargeStep = 0.5;

		public const double StorageStep = 1.0;

		private const int Distributor = 2107;

		private static readonly string[] Names = new string[3] { "Distributor Item Chain", "Distributor Charge Power", "Distributor Energy Storage" };

		private static readonly string[] Descs = new string[3] { "Each stage lets a logistics distributor chain one more item next to its own filter. Stage 1 is known from the start; stage 10 allows 10 chained items.", "Raises the highest charge power a logistics distributor can be set to by 50% of the original maximum per stage.", "Raises how much energy a logistics distributor stores by 100% of the original per stage." };

		private static readonly string[] Conclusions = new string[3] { "Distributors can chain more items.", "Distributors can charge faster.", "Distributors store more energy." };

		private static readonly string[] Icons = new string[3] { "tech-chain.png", "tech-charge.png", "tech-storage.png" };

		public static TechProto[][] Tiers;

		public static volatile bool Dirty;

		internal static ManualLogSource Log;

		public static int Capacity => Done(0);

		public static double ChargeScale => 1.0 + 0.5 * (double)Done(1);

		public static double StorageScale => 1.0 + 1.0 * (double)Done(2);

		public static int Cubes(int stage)
		{
			if (stage < 10)
			{
				if (stage != 9)
				{
					return (stage + 1) / 2;
				}
				return 5;
			}
			return 6;
		}

		public static List<int[]> TierRanges(int line)
		{
			List<int[]> list = new List<int[]>();
			for (int i = ((line != 0) ? 1 : 2); i <= 10; i++)
			{
				if (list.Count > 0 && Cubes(list[list.Count - 1][0]) == Cubes(i))
				{
					list[list.Count - 1][1] = i;
					continue;
				}
				list.Add(new int[2] { i, i });
			}
			return list;
		}

		public static int Done(int line, Func<int, TechState?> state)
		{
			//IL_0040: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			int num = ((line == 0) ? 1 : 0);
			if (Tiers == null || Tiers[line] == null)
			{
				return num;
			}
			TechProto[] array = Tiers[line];
			foreach (TechProto val in array)
			{
				TechState? val2 = state(((Proto)val).ID);
				if (val2.HasValue)
				{
					if (val2.Value.unlocked)
					{
						num = Math.Max(num, val.MaxLevel);
					}
					else if (val2.Value.curLevel > val.Level)
					{
						num = Math.Max(num, val2.Value.curLevel - 1);
					}
				}
			}
			return num;
		}

		private static int Done(int line)
		{
			Dictionary<int, TechState> states = GameMain.history?.techStates;
			TechState value;
			return Done(line, (int id) => (states == null || !states.TryGetValue(id, out value)) ? ((TechState?)null) : new TechState?(value));
		}

		public static long EnergyMax(PrefabDesc desc)
		{
			return (long)((double)desc.dispenserMaxEnergyAcc * StorageScale);
		}

		public static void ApplyEnergy()
		{
			GameData data = GameMain.data;
			if (data?.factories == null)
			{
				return;
			}
			for (int i = 0; i < data.factoryCount; i++)
			{
				PlanetFactory val = data.factories[i];
				PlanetTransport val2 = val?.transport;
				if (val2?.dispenserPool == null)
				{
					continue;
				}
				for (int j = 1; j < val2.dispenserCursor; j++)
				{
					DispenserComponent val3 = val2.dispenserPool[j];
					if (val3 != null && val3.id == j)
					{
						PrefabDesc val4 = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)val.entityPool[val3.entityId].protoId)?.prefabDesc;
						if (val4 != null && val4.dispenserMaxEnergyAcc > 0)
						{
							val3.energyMax = EnergyMax(val4);
						}
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
		[HarmonyAfter(new string[] { "me.xiaoye97.plugin.Dyson.LDBTool", "dsp.common-api.CommonAPI", "org.LoShin.GenesisBook" })]
		private static void Register()
		{
			if (Tiers != null)
			{
				return;
			}
			try
			{
				Build();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)("Upgrade techs not added: " + ex));
				}
				Tiers = new TechProto[3][];
			}
		}

		private static void Build()
		{
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			TechProtoSet techs = LDB.techs;
			int num = DistributorTech();
			Layout(((ProtoSet<TechProto>)(object)techs).dataArray, out var x, out var dx, out var y, out var dy);
			string iconTag = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2107)?.IconTag ?? "";
			List<TechProto> list = new List<TechProto>();
			Tiers = new TechProto[3][];
			for (int i = 0; i < 3; i++)
			{
				List<int[]> list2 = TierRanges(i);
				List<TechProto> list3 = new List<TechProto>();
				bool flag = false;
				for (int j = 0; j < list2.Count; j++)
				{
					flag |= ((ProtoSet<TechProto>)(object)techs).Exist(9310 + i * 10 + j + 1);
				}
				if (flag)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)(Names[i] + ": tech ids " + (9310 + i * 10 + 1) + "+ are taken by another mod, line skipped"));
					}
					continue;
				}
				for (int k = 0; k < list2.Count; k++)
				{
					int num2 = Cubes(list2[k][0]);
					int[] array = new int[num2];
					int[] array2 = new int[num2];
					for (int l = 0; l < num2; l++)
					{
						array[l] = TechProto.matrixIds[l];
						array2[l] = 20;
					}
					TechProto val = new TechProto();
					((Proto)val).ID = 9310 + i * 10 + k + 1;
					((Proto)val).Name = Names[i];
					val.Desc = Descs[i];
					val.Conclusion = Conclusions[i];
					val.Published = true;
					val.IsLabTech = true;
					val.IconPath = "";
					val.IconTag = iconTag;
					val.PreTechs = ((k == 0) ? new int[0] : new int[1] { ((Proto)list3[k - 1]).ID });
					val.PreTechsImplicit = ((k == 0 && num > 0) ? new int[1] { num } : new int[0]);
					val.PreItem = new int[0];
					val.Items = array;
					val.ItemPoints = array2;
					val.HashNeeded = 0L;
					val.LevelCoef1 = 18000;
					val.LevelCoef2 = 18000;
					val.Level = list2[k][0];
					val.MaxLevel = list2[k][1];
					val.UnlockRecipes = new int[0];
					val.UnlockFunctions = new int[0];
					val.UnlockValues = new double[0];
					val.AddItems = new int[0];
					val.AddItemCounts = new int[0];
					val.PropertyOverrideItems = new int[0];
					val.PropertyItemCounts = new int[0];
					val.PropertyOverrideItemArray = (IDCNT[])(object)new IDCNT[0];
					val.Position = new Vector2(x + (float)k * dx, y - (float)i * dy);
					TechProto item = val;
					list3.Add(item);
				}
				Tiers[i] = list3.ToArray();
				list.AddRange(list3);
			}
			if (list.Count == 0)
			{
				return;
			}
			TechProto[] dataArray = ((ProtoSet<TechProto>)(object)techs).dataArray;
			((ProtoTable)techs).Init(dataArray.Length + list.Count);
			Array.Copy(dataArray, ((ProtoSet<TechProto>)(object)techs).dataArray, dataArray.Length);
			for (int m = 0; m < list.Count; m++)
			{
				((ProtoSet<TechProto>)(object)techs).dataArray[dataArray.Length + m] = list[m];
			}
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			for (int n = 0; n < ((ProtoSet<TechProto>)(object)techs).dataArray.Length; n++)
			{
				dictionary[((Proto)((ProtoSet<TechProto>)(object)techs).dataArray[n]).ID] = n;
			}
			Traverse.Create((object)techs).Field("dataIndices").SetValue((object)dictionary);
			if (((ProtoSet<TechProto>)(object)techs).Select(((Proto)list[0]).ID) != list[0])
			{
				throw new InvalidOperationException("tech index not rebuilt");
			}
			foreach (TechProto item2 in list)
			{
				item2.Preload();
			}
			for (int num3 = 0; num3 < 3; num3++)
			{
				if (Tiers[num3] != null)
				{
					Sprite value = LoadIcon(Icons[num3]);
					TechProto[] array3 = Tiers[num3];
					foreach (TechProto obj in array3)
					{
						obj.Preload2();
						Traverse.Create((object)obj).Field("_iconSprite").SetValue((object)value);
					}
				}
			}
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Added " + list.Count + " upgrade techs at x " + x + " step " + dx + ", y " + y + " step " + dy + ", after tech " + num));
			}
		}

		private static int DistributorTech()
		{
			HashSet<int> hashSet = new HashSet<int>();
			RecipeProto[] dataArray = ((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray;
			foreach (RecipeProto val in dataArray)
			{
				if (val?.Results != null && Array.IndexOf(val.Results, 2107) >= 0)
				{
					hashSet.Add(((Proto)val).ID);
				}
			}
			TechProto[] dataArray2 = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
			foreach (TechProto val2 in dataArray2)
			{
				if (val2?.UnlockRecipes == null)
				{
					continue;
				}
				int[] unlockRecipes = val2.UnlockRecipes;
				foreach (int item in unlockRecipes)
				{
					if (hashSet.Contains(item))
					{
						return ((Proto)val2).ID;
					}
				}
			}
			return 0;
		}

		public static void Layout(TechProto[] techs, out float x0, out float dx, out float y0, out float dy)
		{
			//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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			Dictionary<float, float> dictionary = new Dictionary<float, float>();
			SortedSet<float> sortedSet = new SortedSet<float>();
			SortedSet<float> sortedSet2 = new SortedSet<float>();
			foreach (TechProto val in techs)
			{
				if (val != null && val.page == 1)
				{
					Vector2 position = val.Position;
					num = Math.Min(num, position.y);
					sortedSet.Add(position.y);
					sortedSet2.Add(position.x);
					dictionary[position.y] = (dictionary.TryGetValue(position.y, out var value) ? Math.Min(value, position.x) : position.x);
				}
			}
			dx = CommonGap(sortedSet2, 4f);
			dy = CommonGap(sortedSet, 4f);
			x0 = Mode(dictionary.Values, 0f);
			y0 = ((num == float.MaxValue) ? 0f : num) - dy;
		}

		private static float CommonGap(SortedSet<float> values, float fallback)
		{
			List<float> list = new List<float>();
			float num = float.NaN;
			foreach (float value in values)
			{
				if (!float.IsNaN(num) && value - num > 0.5f)
				{
					list.Add(value - num);
				}
				num = value;
			}
			return Mode(list, fallback);
		}

		private static float Mode(IEnumerable<float> values, float fallback)
		{
			Dictionary<float, int> dictionary = new Dictionary<float, int>();
			float num = fallback;
			int num2 = 0;
			foreach (float value2 in values)
			{
				dictionary[value2] = ((!dictionary.TryGetValue(value2, out var value)) ? 1 : (value + 1));
				if (dictionary[value2] > num2 || (dictionary[value2] == num2 && value2 < num))
				{
					num2 = dictionary[value2];
					num = value2;
				}
			}
			return num;
		}

		private static Sprite LoadIcon(string name)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(Tech).Assembly.GetManifestResourceStream(name);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			ImageConversion.LoadImage(val, array);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameHistoryData), "NotifyTechUnlock")]
		private static void Unlocked()
		{
			Dirty = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DispenserComponent), "Init")]
		private static void InitPostfix(DispenserComponent __instance, PrefabDesc _desc)
		{
			__instance.energyMax = EnergyMax(_desc);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(UIDispenserWindow), "OnDispenserIdChange")]
		private static void ChargePrefix(UIDispenserWindow __instance, out long __state)
		{
			__state = ChargeSetting(__instance, out var _, out var _);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIDispenserWindow), "OnDispenserIdChange")]
		private static void ChargePostfix(UIDispenserWindow __instance, long __state)
		{
			if (ChargeSetting(__instance, out var power, out var pc) >= 0 && __state >= 0)
			{
				Slider maxChargePowerSlider = __instance.maxChargePowerSlider;
				maxChargePowerSlider.maxValue = (float)((double)maxChargePowerSlider.maxValue * ChargeScale);
				power.consumerPool[pc].workEnergyPerTick = __state;
				maxChargePowerSlider.value = (float)__state / 5000f;
				power.consumerPool[pc].workEnergyPerTick = __state;
			}
		}

		private static long ChargeSetting(UIDispenserWindow w, out PowerSystem power, out int pc)
		{
			power = null;
			pc = 0;
			PlanetFactory factory = w.factory;
			DispenserComponent[] array = factory?.transport?.dispenserPool;
			int dispenserId = w.dispenserId;
			if (array == null || dispenserId <= 0 || dispenserId >= array.Length || array[dispenserId] == null || array[dispenserId].id != dispenserId || factory.powerSystem == null)
			{
				return -1L;
			}
			power = factory.powerSystem;
			pc = array[dispenserId].pcId;
			if (pc <= 0)
			{
				return -1L;
			}
			return power.consumerPool[pc].workEnergyPerTick;
		}
	}
}