Decompiled source of DSP RecipeSlots v1.2.0

BepInEx\plugins\DSP-RecipeSlots\DSP-RecipeSlots.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DSP-RecipeSlots")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+328be68d533c2fb4665ba9a6b02bb6f97ece069e")]
[assembly: AssemblyProduct("DSP-RecipeSlots")]
[assembly: AssemblyTitle("DSP-RecipeSlots")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DSPRecipeSlots
{
	[HarmonyPatch(typeof(UIAssemblerWindow), "_OnUpdate")]
	internal static class AssemblerUiPatch
	{
		private sealed class Slot
		{
			public GameObject Root;

			public Image Icon;

			public Text Count;

			public Image Progress;

			public Image ExtraProgress;

			public Button Button;

			public UIButton Tips;
		}

		private sealed class WinState
		{
			public readonly List<Slot> Extras = new List<Slot>();

			public readonly List<Slot> GridProducts = new List<Slot>();

			public readonly List<Slot> Inputs = new List<Slot>();

			public int ServingCols;

			public bool Multi;
		}

		private static readonly Dictionary<UIAssemblerWindow, WinState> Cache = new Dictionary<UIAssemblerWindow, WinState>();

		private static bool _errorLogged;

		private const float SlotSize = 64f;

		private const float RowH = 72f;

		private const int InPerRow = 6;

		private const int OutPerRow = 6;

		private const int MultiOutTrigger = 4;

		[HarmonyPostfix]
		private static void Postfix(UIAssemblerWindow __instance)
		{
			try
			{
				Update(__instance);
			}
			catch (Exception ex)
			{
				if (!_errorLogged)
				{
					_errorLogged = true;
					Plugin.Log.LogError((object)("[ui] assembler window patch failed: " + ex));
				}
			}
		}

		private static WinState GetState(UIAssemblerWindow w)
		{
			if (Cache.TryGetValue(w, out var value) && value != null)
			{
				return value;
			}
			value = new WinState();
			Cache[w] = value;
			return value;
		}

		private static void Update(UIAssemblerWindow w)
		{
			int assemblerId = w.assemblerId;
			PlanetFactory val = GameMain.localPlanet?.factory;
			if (val == null || assemblerId <= 0)
			{
				return;
			}
			ref AssemblerComponent reference = ref val.factorySystem.assemblerPool[assemblerId];
			if (reference.id != assemblerId)
			{
				return;
			}
			RecipeExecuteData recipeExecuteData = reference.recipeExecuteData;
			if (recipeExecuteData != null)
			{
				int num = recipeExecuteData.products.Length;
				int num2 = recipeExecuteData.requires.Length;
				WinState state = GetState(w);
				if (state.Multi = num2 > 6 || num > 4)
				{
					ApplyMulti(w, ref reference, recipeExecuteData, num2, num, state);
				}
				else
				{
					ApplySingle(w, ref reference, recipeExecuteData, num2, num, state);
				}
				ClampWindow(w);
			}
		}

		private static void ApplySingle(UIAssemblerWindow w, ref AssemblerComponent a, RecipeExecuteData data, int nIn, int nOut, WinState st)
		{
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: 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_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			HideAll(st.GridProducts);
			HideAll(st.Inputs);
			if ((Object)(object)w.productGroup != (Object)null)
			{
				((Component)w.productGroup).gameObject.SetActive(true);
			}
			if ((Object)(object)w.servingGroup != (Object)null)
			{
				((Component)w.servingGroup).gameObject.SetActive(true);
			}
			if ((Object)(object)w.servingBox != (Object)null)
			{
				int num = Mathf.Max(1, nIn);
				if (st.ServingCols != num || w.servingBox.colCount != num)
				{
					st.ServingCols = num;
					w.servingBox.colCount = num;
					w.servingBox.OnStorageSizeChanged();
				}
			}
			if (nOut > 2)
			{
				EnsureSlots(w, st.Extras, nOut - 2, input: false);
			}
			for (int i = 0; i < st.Extras.Count; i++)
			{
				int num2 = i + 2;
				Slot slot = st.Extras[i];
				if (!((Object)(object)slot.Root == (Object)null))
				{
					if (nOut <= num2)
					{
						slot.Root.SetActive(false);
						continue;
					}
					slot.Root.SetActive(true);
					RectTransform val = (RectTransform)slot.Root.transform;
					val.anchoredPosition = new Vector2(19f + 64f * (float)num2, 0f);
					val.sizeDelta = new Vector2(64f, 64f);
					FillProduct(slot, a, data, num2, w);
				}
			}
			if ((Object)(object)w.productGroup != (Object)null)
			{
				w.productGroup.sizeDelta = new Vector2(64f * (float)Math.Max(1, nOut), 64f);
			}
			float num3 = 64f * (float)(Math.Max(1, nOut) - 1);
			if ((Object)(object)w.speedGroup != (Object)null)
			{
				w.speedGroup.anchoredPosition = new Vector2(80f + num3, 0f);
			}
			SetArrowDirection(w, down: false);
			if ((Object)(object)w.servingGroup != (Object)null)
			{
				w.servingGroup.anchoredPosition = new Vector2(160f + num3, 0f);
			}
			float num4 = 50f * (float)Math.Max(1, nIn) + 4f;
			float val2 = 160f + num3 + num4 + 24f;
			float num5 = Math.Max(80f + (float)(((Object)(object)w.playerInventory != (Object)null) ? w.playerInventory.colCount : 10) * 50f, val2);
			if ((Object)(object)w.windowTrans != (Object)null)
			{
				w.windowTrans.sizeDelta = new Vector2(num5, 420f);
			}
			if ((Object)(object)w.playerInventoryGroup != (Object)null)
			{
				w.playerInventoryGroup.anchoredPosition = new Vector2(w.playerInventoryGroup.anchoredPosition.x, -180f);
			}
		}

		private static void ApplyMulti(UIAssemblerWindow w, ref AssemblerComponent a, RecipeExecuteData data, int nIn, int nOut, WinState st)
		{
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: 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_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: 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)
			if ((Object)(object)w.productGroup != (Object)null)
			{
				((Component)w.productGroup).gameObject.SetActive(false);
			}
			if ((Object)(object)w.servingGroup != (Object)null)
			{
				((Component)w.servingGroup).gameObject.SetActive(false);
			}
			HideAll(st.Extras);
			int num = Mathf.Min(6, Mathf.Max(1, nIn));
			int num2 = Mathf.CeilToInt((float)nIn / (float)num);
			int num3 = Mathf.Max(1, Mathf.CeilToInt((float)nOut / 6f));
			float num4 = -75f;
			float num5 = num4 - (float)(num2 - 1) * 72f - 32f - 40f;
			float num6 = num5 - 70f;
			float num7 = num6 - (float)(num3 - 1) * 72f - 32f - 64f;
			float num8 = 0f - num7 + 204f + 20f;
			float num9 = (float)Mathf.Min(nIn, num) * 64f;
			EnsureSlots(w, st.Inputs, nIn, input: true);
			for (int i = 0; i < st.Inputs.Count; i++)
			{
				Slot slot = st.Inputs[i];
				if (!((Object)(object)slot.Root == (Object)null))
				{
					if (i >= nIn)
					{
						slot.Root.SetActive(false);
						continue;
					}
					slot.Root.SetActive(true);
					RectTransform val = (RectTransform)slot.Root.transform;
					val.sizeDelta = new Vector2(64f, 64f);
					float num10 = num4 - (float)(i / num) * 72f;
					val.anchoredPosition = new Vector2(19f + (float)(i % num) * 64f, num10 + 100f);
					FillInput(slot, a, data, i);
				}
			}
			float num11 = (float)Mathf.Min(nOut, 6) * 64f;
			float num12 = Mathf.Max(Mathf.Max(num9, num11), 120f);
			float num13 = 19f + num12 * 0.5f;
			if ((Object)(object)w.speedGroup != (Object)null)
			{
				w.speedGroup.anchoredPosition = new Vector2(num13, num5 + 100f);
				SetArrowDirection(w, down: true);
			}
			EnsureSlots(w, st.GridProducts, nOut, input: false);
			for (int j = 0; j < st.GridProducts.Count; j++)
			{
				Slot slot2 = st.GridProducts[j];
				if (!((Object)(object)slot2.Root == (Object)null))
				{
					if (j >= nOut)
					{
						slot2.Root.SetActive(false);
						continue;
					}
					slot2.Root.SetActive(true);
					RectTransform val2 = (RectTransform)slot2.Root.transform;
					val2.sizeDelta = new Vector2(64f, 64f);
					float num14 = num6 - (float)(j / 6) * 72f;
					val2.anchoredPosition = new Vector2(19f + (float)(j % 6) * 64f, num14 + 100f);
					FillProduct(slot2, a, data, j, w);
				}
			}
			float num15 = 19f + num12 + 40f;
			float num16 = Mathf.Max(80f + (float)(((Object)(object)w.playerInventory != (Object)null) ? w.playerInventory.colCount : 10) * 50f, num15);
			if ((Object)(object)w.windowTrans != (Object)null)
			{
				w.windowTrans.sizeDelta = new Vector2(num16, num8);
			}
			if ((Object)(object)w.playerInventoryGroup != (Object)null)
			{
				w.playerInventoryGroup.anchoredPosition = new Vector2(w.playerInventoryGroup.anchoredPosition.x, num7);
			}
		}

		private static void SetArrowDirection(UIAssemblerWindow w, bool down)
		{
			//IL_0022: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (w.speedArrows == null)
			{
				return;
			}
			Quaternion val = (down ? Quaternion.Euler(0f, 0f, 90f) : Quaternion.identity);
			for (int i = 0; i < w.speedArrows.Length; i++)
			{
				Image val2 = w.speedArrows[i];
				if (!((Object)(object)val2 == (Object)null))
				{
					Transform transform = ((Component)val2).transform;
					if (transform.localRotation != val)
					{
						transform.localRotation = val;
					}
				}
			}
		}

		private static void FillProduct(Slot s, AssemblerComponent a, RecipeExecuteData data, int idx, UIAssemblerWindow w)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			int num = data.products[idx];
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num);
			if ((Object)(object)s.Icon != (Object)null)
			{
				s.Icon.sprite = ((val != null) ? val.iconSprite : null);
			}
			if ((Object)(object)s.Count != (Object)null)
			{
				s.Count.text = a.produced[idx].ToString();
			}
			if ((Object)(object)s.Button != (Object)null)
			{
				((Selectable)s.Button).interactable = a.produced[idx] > 0;
			}
			if ((Object)(object)s.Tips != (Object)null && val != null)
			{
				s.Tips.tips.itemId = num;
				s.Tips.tips.itemInc = 0;
				s.Tips.tips.itemCount = 0;
				s.Tips.tips.type = (ItemTipType)0;
				s.Tips.tips.corner = 2;
				s.Tips.tips.delay = 0.2f;
			}
			if ((Object)(object)s.Progress != (Object)null)
			{
				s.Progress.fillAmount = (((Object)(object)w.productProgress0 != (Object)null) ? w.productProgress0.fillAmount : 0f);
			}
			if ((Object)(object)s.ExtraProgress != (Object)null)
			{
				s.ExtraProgress.fillAmount = (((Object)(object)w.extraProductProgress0 != (Object)null) ? w.extraProductProgress0.fillAmount : 0f);
			}
		}

		private static void FillInput(Slot s, AssemblerComponent a, RecipeExecuteData data, int idx)
		{
			//IL_003a: 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_0050: 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)
			int num = data.requires[idx];
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num);
			if ((Object)(object)s.Icon != (Object)null)
			{
				s.Icon.sprite = ((val != null) ? val.iconSprite : null);
			}
			int num2 = ((a.served != null && idx < a.served.Length) ? a.served[idx] : 0);
			if ((Object)(object)s.Count != (Object)null)
			{
				s.Count.text = num2.ToString();
			}
			if ((Object)(object)s.Button != (Object)null)
			{
				((Selectable)s.Button).interactable = false;
			}
			if ((Object)(object)s.Tips != (Object)null && val != null)
			{
				int num3 = ((data.requireCounts == null || idx >= data.requireCounts.Length) ? 1 : data.requireCounts[idx]);
				s.Tips.tips.itemId = num;
				s.Tips.tips.itemInc = 0;
				s.Tips.tips.itemCount = 0;
				s.Tips.tips.type = (ItemTipType)0;
				s.Tips.tips.corner = 2;
				s.Tips.tips.delay = 0.2f;
				s.Tips.tips.tipText = num3 + " / 次";
			}
		}

		private static void HideAll(List<Slot> list)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] != null && (Object)(object)list[i].Root != (Object)null)
				{
					list[i].Root.SetActive(false);
				}
			}
		}

		private static void EnsureSlots(UIAssemblerWindow w, List<Slot> list, int need, bool input)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			if ((Object)(object)w.productGroup == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)w.productGroup).transform.parent;
			while (list.Count < need)
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)w.productGroup).gameObject, parent);
				((Object)obj).name = (input ? "recipeslots-input-" : "recipeslots-product-") + list.Count;
				Slot slot = BuildSlot(obj, input);
				if (!input)
				{
					int captured = list.Count;
					if ((Object)(object)slot.Button != (Object)null)
					{
						((UnityEventBase)slot.Button.onClick).RemoveAllListeners();
						((UnityEvent)slot.Button.onClick).AddListener((UnityAction)delegate
						{
							TakeProduct(w, captured);
						});
					}
				}
				list.Add(slot);
			}
			if (input)
			{
				return;
			}
			for (int num = 0; num < list.Count; num++)
			{
				Button button = list[num].Button;
				if (!((Object)(object)button == (Object)null))
				{
					int captured2 = num;
					((UnityEventBase)button.onClick).RemoveAllListeners();
					((UnityEvent)button.onClick).AddListener((UnityAction)delegate
					{
						TakeProduct(w, captured2);
					});
				}
			}
		}

		private static Slot BuildSlot(GameObject go, bool input)
		{
			//IL_002f: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			Slot slot = new Slot
			{
				Root = go
			};
			Transform transform = go.transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val != (Object)null)
			{
				val.sizeDelta = new Vector2(64f, 64f);
			}
			HideChild(transform, "product-icon-1");
			HideChild(transform, "circle-fg-1");
			HideChild(transform, "extra-circle-fg-1");
			HideChild(transform, "cnt-text-1");
			HideChild(transform, "stop-btn");
			if (input)
			{
				HideChild(transform, "circle-fg");
				HideChild(transform, "extra-circle-fg");
			}
			Transform val2 = transform.Find("product-icon");
			if ((Object)(object)val2 != (Object)null)
			{
				slot.Icon = ((Component)val2).GetComponent<Image>();
				slot.Button = ((Component)val2).GetComponent<Button>();
				slot.Tips = ((Component)val2).GetComponent<UIButton>();
			}
			Transform val3 = transform.Find("cnt-text");
			if ((Object)(object)val3 != (Object)null)
			{
				slot.Count = ((Component)val3).GetComponent<Text>();
				RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					val4.anchorMin = new Vector2(1f, 0f);
					val4.anchorMax = new Vector2(1f, 0f);
					val4.pivot = new Vector2(1f, 0f);
					val4.anchoredPosition = new Vector2(-9f, 7f);
					if ((Object)(object)slot.Count != (Object)null)
					{
						slot.Count.alignment = (TextAnchor)8;
					}
				}
				if (input && (Object)(object)slot.Button != (Object)null)
				{
					((Selectable)slot.Button).transition = (Transition)0;
				}
			}
			Transform val5 = transform.Find("circle-fg");
			if ((Object)(object)val5 != (Object)null)
			{
				slot.Progress = ((Component)val5).GetComponent<Image>();
			}
			Transform val6 = transform.Find("extra-circle-fg");
			if ((Object)(object)val6 != (Object)null)
			{
				slot.ExtraProgress = ((Component)val6).GetComponent<Image>();
			}
			return slot;
		}

		private static void HideChild(Transform t, string name)
		{
			Transform val = t.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
		}

		internal static void DumpSlots(StringBuilder o)
		{
			//IL_0137: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<UIAssemblerWindow, WinState> item in Cache)
			{
				UIAssemblerWindow key = item.Key;
				WinState value = item.Value;
				if (!((Object)(object)key == (Object)null) && value != null)
				{
					o.AppendLine("  assemblerId=" + key.assemblerId + " multi=" + value.Multi);
					AppendRect(o, "window", key.windowTrans);
					AppendRect(o, "productGroup", key.productGroup);
					AppendRect(o, "produce", key.produceGroup);
					AppendRect(o, "playerStorage", key.playerInventoryGroup);
					o.AppendLine("  extras=" + Describe(value.Extras));
					o.AppendLine("  gridProducts=" + Describe(value.GridProducts));
					o.AppendLine("  inputs=" + Describe(value.Inputs));
					RectTransform val = (RectTransform)(((Object)(object)key.windowTrans != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
					if ((Object)(object)val != (Object)null)
					{
						Rect rect = val.rect;
						o.AppendLine("  windowParent rect=" + ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString() + " pos=" + ((object)((Transform)val).position/*cast due to .constrained prefix*/).ToString());
					}
				}
			}
		}

		private static string Describe(List<Slot> list)
		{
			//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_01bb: 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_0130: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('[');
			for (int i = 0; i < list.Count; i++)
			{
				Slot slot = list[i];
				if (i > 0)
				{
					stringBuilder.Append(',');
				}
				if (slot == null || (Object)(object)slot.Root == (Object)null)
				{
					stringBuilder.Append("null");
					continue;
				}
				Transform transform = slot.Root.transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				StringBuilder stringBuilder2 = stringBuilder.Append(((Object)slot.Root).name).Append(slot.Root.activeSelf ? "" : "(off)").Append('@');
				object value;
				Vector2 val2;
				if (!((Object)(object)val != (Object)null))
				{
					value = "?";
				}
				else
				{
					val2 = val.anchoredPosition;
					value = ((Vector2)(ref val2)).ToString("F0");
				}
				stringBuilder2.Append((string?)value);
				if ((Object)(object)slot.Count != (Object)null)
				{
					RectTransform rectTransform = ((Graphic)slot.Count).rectTransform;
					StringBuilder stringBuilder3 = stringBuilder.Append(" cnt='").Append(slot.Count.text).Append("'")
						.Append(((Component)slot.Count).gameObject.activeSelf ? "" : "(off)")
						.Append(" a=");
					val2 = rectTransform.anchorMin;
					StringBuilder stringBuilder4 = stringBuilder3.Append(((Vector2)(ref val2)).ToString("F2")).Append(" p=");
					val2 = rectTransform.pivot;
					StringBuilder stringBuilder5 = stringBuilder4.Append(((Vector2)(ref val2)).ToString("F2")).Append(" pos=");
					val2 = rectTransform.anchoredPosition;
					stringBuilder5.Append(((Vector2)(ref val2)).ToString("F0"));
				}
				else
				{
					stringBuilder.Append(" cnt=null");
				}
				if ((Object)(object)val != (Object)null)
				{
					Vector3[] array = (Vector3[])(object)new Vector3[4];
					val.GetWorldCorners(array);
					Vector3 val3 = array[0];
					stringBuilder.Append(" scr=").Append(((Vector3)(ref val3)).ToString("F0"));
				}
			}
			stringBuilder.Append(']');
			return stringBuilder.ToString();
		}

		private static void AppendRect(StringBuilder o, string name, RectTransform rt)
		{
			//IL_004e: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00a9: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rt == (Object)null)
			{
				o.AppendLine("  " + name + "=null");
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			rt.GetWorldCorners(array);
			string[] obj = new string[16]
			{
				"  ", name, " pos=", null, null, null, null, null, null, null,
				null, null, null, null, null, null
			};
			Vector2 val = rt.anchoredPosition;
			obj[3] = ((Vector2)(ref val)).ToString("F0");
			obj[4] = " size=";
			val = rt.sizeDelta;
			obj[5] = ((Vector2)(ref val)).ToString("F0");
			obj[6] = " anchor=";
			val = rt.anchorMin;
			obj[7] = ((Vector2)(ref val)).ToString("F2");
			obj[8] = "/";
			val = rt.anchorMax;
			obj[9] = ((Vector2)(ref val)).ToString("F2");
			obj[10] = " pivot=";
			val = rt.pivot;
			obj[11] = ((Vector2)(ref val)).ToString("F2");
			obj[12] = " wMin=";
			obj[13] = ((Vector3)(ref array[0])).ToString("F0");
			obj[14] = " wMax=";
			obj[15] = ((Vector3)(ref array[2])).ToString("F0");
			o.AppendLine(string.Concat(obj));
		}

		internal static void ClampWindow(UIAssemblerWindow w)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005b: 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_0075: 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_0090: 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_00ab: 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_00bd: 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_00f4: 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_0120: 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_0162: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)w == (Object)null || (Object)(object)w.windowTrans == (Object)null)
			{
				return;
			}
			Transform parent = ((Transform)w.windowTrans).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			RectTransform windowTrans = w.windowTrans;
			Rect rect = val.rect;
			float width = ((Rect)(ref rect)).width;
			rect = val.rect;
			float height = ((Rect)(ref rect)).height;
			float x = windowTrans.sizeDelta.x;
			float y = windowTrans.sizeDelta.y;
			if (windowTrans.anchorMin.x == windowTrans.anchorMax.x && windowTrans.anchorMin.y == windowTrans.anchorMax.y)
			{
				Vector2 anchoredPosition = windowTrans.anchoredPosition;
				float num = (0f - width) * 0.5f + x * windowTrans.pivot.x;
				float num2 = width * 0.5f - x * (1f - windowTrans.pivot.x);
				float num3 = (0f - height) * 0.5f + y * windowTrans.pivot.y;
				float num4 = height * 0.5f - y * (1f - windowTrans.pivot.y);
				float num5 = Mathf.Clamp(anchoredPosition.x, Mathf.Min(num, num2), Mathf.Max(num, num2));
				float num6 = Mathf.Clamp(anchoredPosition.y, Mathf.Min(num3, num4), Mathf.Max(num3, num4));
				if (Mathf.Abs(num5 - anchoredPosition.x) > 0.5f || Mathf.Abs(num6 - anchoredPosition.y) > 0.5f)
				{
					windowTrans.anchoredPosition = new Vector2(num5, num6);
				}
			}
		}

		internal static bool ClickProduct(int index)
		{
			UIRoot instance = UIRoot.instance;
			UIAssemblerWindow val = (((Object)(object)instance != (Object)null && (Object)(object)instance.uiGame != (Object)null) ? instance.uiGame.assemblerWindow : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			TakeProduct(val, index);
			return true;
		}

		private static void TakeProduct(UIAssemblerWindow w, int index)
		{
			PlanetFactory val = GameMain.localPlanet?.factory;
			Player mainPlayer = GameMain.mainPlayer;
			if (val == null || mainPlayer == null)
			{
				return;
			}
			int assemblerId = w.assemblerId;
			if (assemblerId <= 0)
			{
				return;
			}
			ref AssemblerComponent reference = ref val.factorySystem.assemblerPool[assemblerId];
			if (reference.id != assemblerId || reference.recipeExecuteData == null)
			{
				return;
			}
			int[] products = reference.recipeExecuteData.products;
			if (index >= 0 && index < products.Length && reference.produced[index] > 0 && mainPlayer.inhandItemId <= 0)
			{
				int num = mainPlayer.TryAddItemToPackage(products[index], reference.produced[index], 0, false, 0, false);
				val.factorySystem.assemblerPool[assemblerId].produced[index] = 0;
				if (num > 0)
				{
					UIItemup.Up(products[index], num);
				}
			}
		}
	}
	internal static class DevChannel
	{
		internal static void Init(ConfigFile config)
		{
		}

		internal static void Tick()
		{
		}
	}
	internal static class LabPatches
	{
		[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
		[HarmonyPriority(0)]
		internal static class LabInitPatch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				try
				{
					ExtendMatrices();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] ExtendMatrices failed: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(FactorySystem), "GameTickLabResearchMode")]
		internal static class LabMatrixRemapTickPatch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				try
				{
					GameHistoryData history = GameMain.history;
					RemapMatrixPoints((history != null) ? history.currentTech : 0);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] remap tick: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(GameHistoryData), "Import")]
		internal static class LabMatrixRemapImportPatch
		{
			[HarmonyPostfix]
			private static void Postfix(GameHistoryData __instance)
			{
				try
				{
					RemapMatrixPoints((__instance != null) ? __instance.currentTech : 0);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] remap import: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(LabComponent), "SetFunction")]
		internal static class LabNeedsResizePatch
		{
			[HarmonyPostfix]
			private static void Postfix(ref LabComponent __instance)
			{
				try
				{
					if (__instance.researchMode)
					{
						return;
					}
					RecipeExecuteData recipeExecuteData = __instance.recipeExecuteData;
					if (recipeExecuteData != null && recipeExecuteData.requires != null)
					{
						int num = Math.Max(6, recipeExecuteData.requires.Length);
						if (__instance.needs == null || __instance.needs.Length != num)
						{
							__instance.needs = new int[num];
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[m2] lab resize needs: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(LabComponent), "UpdateNeedsResearch")]
		internal static class LabUpdateNeedsResearchPatch
		{
			[HarmonyPostfix]
			private static void Postfix(ref LabComponent __instance)
			{
				try
				{
					int[] matrixIds = LabComponent.matrixIds;
					int[] array = __instance.matrixServed;
					int[] matrixIncServed = __instance.matrixIncServed;
					if (matrixIds == null || array == null)
					{
						return;
					}
					int num = matrixIds.Length;
					if (__instance.needs == null || __instance.needs.Length != num)
					{
						__instance.needs = new int[num];
					}
					if (array.Length != num)
					{
						int[] array2 = new int[num];
						Array.Copy(array, array2, Math.Min(array.Length, num));
						__instance.matrixServed = array2;
						array = array2;
					}
					if (matrixIncServed == null || matrixIncServed.Length != num)
					{
						int[] array3 = new int[num];
						if (matrixIncServed != null)
						{
							Array.Copy(matrixIncServed, array3, Math.Min(matrixIncServed.Length, num));
						}
						__instance.matrixIncServed = array3;
					}
					int[] needs = __instance.needs;
					for (int i = 0; i < num; i++)
					{
						needs[i] = ((array[i] < 36000) ? matrixIds[i] : 0);
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] UpdateNeedsResearch patch: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(LabComponent), "UpdateNeedsAssemble")]
		internal static class LabUpdateNeedsAssemblePatch
		{
			[HarmonyPostfix]
			private static void Postfix(ref LabComponent __instance)
			{
				RecipeExecuteData recipeExecuteData = __instance.recipeExecuteData;
				if (recipeExecuteData == null)
				{
					return;
				}
				int[] requires = recipeExecuteData.requires;
				int[] needs = __instance.needs;
				int[] served = __instance.served;
				if (requires == null || needs == null || served == null)
				{
					return;
				}
				int num = requires.Length;
				if (num <= 6)
				{
					return;
				}
				int num2 = ((recipeExecuteData.timeSpend > 5400000) ? 6 : (3 * ((__instance.speedOverride + 5001) / 10000) + 3));
				int num3 = needs.Length;
				int i = 0;
				if (num3 >= num)
				{
					for (int j = 0; j < num; j++)
					{
						needs[j] = ((j < served.Length && served[j] < num2) ? requires[j] : 0);
					}
					for (int k = num; k < num3; k++)
					{
						needs[k] = 0;
					}
					return;
				}
				int num4 = (int)(GameMain.gameTick % num);
				if (num4 < 0)
				{
					num4 += num;
				}
				for (int l = 0; l < num; l++)
				{
					if (i >= num3)
					{
						break;
					}
					int num5 = num4 + l;
					if (num5 >= num)
					{
						num5 -= num;
					}
					if (num5 < served.Length && served[num5] < num2)
					{
						needs[i++] = requires[num5];
					}
				}
				for (; i < num3; i++)
				{
					needs[i] = 0;
				}
			}
		}

		[HarmonyPatch(typeof(LabComponent), "InternalUpdateAssemble")]
		internal static class LabInternalUpdateAssemblePatch
		{
			private const int ShaderStateLen = 10;

			[HarmonyPostfix]
			private static void Postfix(ref LabComponent __instance, ref uint __result)
			{
				try
				{
					if (__result == 0)
					{
						return;
					}
					RecipeExecuteData recipeExecuteData = __instance.recipeExecuteData;
					if (recipeExecuteData != null && recipeExecuteData.products != null && recipeExecuteData.products.Length != 0)
					{
						int num = Array.IndexOf(LabComponent.matrixIds, recipeExecuteData.products[0]);
						if (num >= 0)
						{
							__result = (uint)(num + 1);
						}
						if (__result >= 10)
						{
							__result = 0u;
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] InternalUpdateAssemble patch: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(LabComponent), "InternalUpdateResearch")]
		internal static class LabInternalUpdateResearchPatch
		{
			[HarmonyPrefix]
			private static bool Prefix(ref LabComponent __instance, ref uint __result)
			{
				try
				{
					int[] matrixServed = __instance.matrixServed;
					int[] matrixPoints = LabComponent.matrixPoints;
					if (matrixServed == null || matrixPoints == null)
					{
						return true;
					}
					int num = Math.Min(matrixServed.Length, matrixPoints.Length);
					for (int i = 0; i < num; i++)
					{
						if (matrixPoints[i] > 0 && matrixServed[i] < matrixPoints[i])
						{
							__instance.replicating = false;
							__result = 0u;
							return false;
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] InternalUpdateResearch patch: " + ex));
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(LabComponent), "UpdateOutputToNext")]
		internal static class LabUpdateOutputToNextPatch
		{
			[HarmonyPrefix]
			private static bool Prefix(ref LabComponent __instance, LabComponent[] labPool)
			{
				//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_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: 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_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_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					int[] matrixServed = __instance.matrixServed;
					if (matrixServed == null || matrixServed.Length <= 6)
					{
						return true;
					}
					int nextLabId = __instance.nextLabId;
					if (nextLabId <= 0 || nextLabId >= labPool.Length)
					{
						return true;
					}
					LabComponent val = labPool[nextLabId];
					if (val.id == 0 || val.id != nextLabId)
					{
						__instance.nextLabId = 0;
						return false;
					}
					if (val.needs == null || __instance.recipeId != val.recipeId || __instance.techId != val.techId)
					{
						return false;
					}
					int[] matrixServed2 = val.matrixServed;
					int[] matrixIncServed = __instance.matrixIncServed;
					int[] matrixIncServed2 = val.matrixIncServed;
					int[] matrixIds = LabComponent.matrixIds;
					if (matrixServed2 == null || matrixIncServed == null || matrixIncServed2 == null || matrixIds == null)
					{
						return false;
					}
					int num = Math.Min(Math.Min(matrixServed.Length, matrixServed2.Length), Math.Min(matrixIds.Length, val.needs.Length));
					lock (matrixServed)
					{
						lock (matrixServed2)
						{
							for (int i = 0; i < num; i++)
							{
								if (val.needs[i] == matrixIds[i] && matrixServed[i] >= 7200)
								{
									int num2 = (matrixServed[i] - 7200) / 3600 * 3600;
									if (num2 > 36000)
									{
										num2 = 36000;
									}
									int num3 = SplitInc(ref matrixServed[i], ref matrixIncServed[i], num2);
									matrixIncServed2[i] += num3;
									matrixServed2[i] += num2;
								}
							}
						}
					}
					return false;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("[lab] UpdateOutputToNext patch: " + ex));
					return true;
				}
			}

			private static int SplitInc(ref int n, ref int m, int p)
			{
				int num = m / n;
				int num2 = m - num * n;
				n -= p;
				num2 -= n;
				m -= ((num2 > 0) ? (num * p + num2) : (num * p));
				return num;
			}
		}

		internal static void ExtendMatrices()
		{
			string value = Plugin.LabExtraMatrixIds.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return;
			}
			List<int> list = new List<int>();
			string[] array = value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				if (int.TryParse(array[i].Trim(), out var result) && result > 0)
				{
					list.Add(result);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			int[] matrixIds = LabComponent.matrixIds;
			if (matrixIds == null || matrixIds.Length == 0)
			{
				return;
			}
			List<int> list2 = new List<int>();
			foreach (int item in list)
			{
				if (Array.IndexOf(matrixIds, item) < 0 && !list2.Contains(item))
				{
					if (((ProtoSet<ItemProto>)(object)LDB.items).Select(item) == null)
					{
						Plugin.Log.LogWarning((object)("[lab] extra matrix item " + item + " not in LDB yet (will be registered later?)"));
					}
					list2.Add(item);
				}
			}
			if (list2.Count != 0)
			{
				int num = matrixIds.Length + list2.Count;
				int[] array2 = new int[num];
				Array.Copy(matrixIds, array2, matrixIds.Length);
				for (int j = 0; j < list2.Count; j++)
				{
					array2[matrixIds.Length + j] = list2[j];
				}
				LabComponent.matrixIds = array2;
				TechProto.matrixIds = array2;
				int[] matrixPoints = LabComponent.matrixPoints;
				int[] array3 = new int[num];
				if (matrixPoints != null)
				{
					Array.Copy(matrixPoints, array3, Math.Min(matrixPoints.Length, num));
				}
				LabComponent.matrixPoints = array3;
				Plugin.Log.LogInfo((object)("[lab] matrix extended: ids=[" + string.Join(",", array2) + "] pointsLen=" + num));
			}
		}

		internal static void RemapMatrixPoints(int techId)
		{
			int[] matrixIds = LabComponent.matrixIds;
			int[] matrixPoints = LabComponent.matrixPoints;
			if (matrixIds == null || matrixPoints == null || matrixIds.Length <= 6)
			{
				return;
			}
			Array.Clear(matrixPoints, 0, matrixPoints.Length);
			if (techId <= 0)
			{
				return;
			}
			TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(techId);
			if (val == null || val.Items == null)
			{
				return;
			}
			for (int i = 0; i < val.Items.Length; i++)
			{
				int num = Array.IndexOf(matrixIds, val.Items[i]);
				if (num >= 0 && num < matrixPoints.Length)
				{
					matrixPoints[num] = val.ItemPoints[i];
				}
			}
		}
	}
	internal static class LabUiPatch
	{
		private sealed class Full
		{
			public UIButton[] Buttons;

			public Image[] Icons;

			public Image[] Percents;

			public Text[] Counts;

			public Image[] Locks;

			public Image[] Incs;
		}

		[HarmonyPatch(typeof(UILabWindow), "_OnInit")]
		internal static class OnInitPatch
		{
			[HarmonyPrefix]
			private static void Prefix(UILabWindow __instance)
			{
				try
				{
					Ensure(__instance);
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}
		}

		[HarmonyPatch(typeof(UILabWindow), "_OnUpdate")]
		internal static class OnUpdatePatch
		{
			[HarmonyPrefix]
			private static void Prefix(UILabWindow __instance)
			{
				try
				{
					Trim(__instance);
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}

			[HarmonyFinalizer]
			private static void Finalizer(UILabWindow __instance)
			{
				try
				{
					Restore(__instance);
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(UILabWindow __instance)
			{
				try
				{
					Arrange(__instance);
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}
		}

		private const int SlotCount = 9;

		private static readonly Dictionary<UILabWindow, Full> Cache = new Dictionary<UILabWindow, Full>();

		private static FieldInfo _protosField;

		private static FieldInfo _recipesField;

		private static bool _err;

		private static void Log(Exception ex)
		{
			if (!_err)
			{
				_err = true;
				Plugin.Log.LogError((object)("[lab-ui] " + ex));
			}
		}

		private static void Ensure(UILabWindow w)
		{
			if (w.itemButtons == null || w.itemButtons.Length == 0)
			{
				return;
			}
			int[] matrixIds = LabComponent.matrixIds;
			int val = ((matrixIds != null) ? matrixIds.Length : 6);
			int num = Math.Max(9, val);
			if (Cache.TryGetValue(w, out var value) && value != null && value.Buttons != null && value.Buttons.Length >= num)
			{
				return;
			}
			int num2 = w.itemButtons.Length;
			int num3 = Math.Max(num, num2);
			UIButton[] array = (UIButton[])(object)new UIButton[num3];
			Image[] array2 = (Image[])(object)new Image[num3];
			Image[] array3 = (Image[])(object)new Image[num3];
			Text[] array4 = (Text[])(object)new Text[num3];
			Image[] array5 = (Image[])(object)new Image[num3];
			Image[] array6 = (Image[])(object)new Image[num3 * 3];
			for (int i = 0; i < num2; i++)
			{
				array[i] = w.itemButtons[i];
				array2[i] = Get(w.itemIcons, i);
				array3[i] = Get(w.itemPercents, i);
				array4[i] = ((w.itemCountTexts != null && i < w.itemCountTexts.Length) ? w.itemCountTexts[i] : null);
				array5[i] = Get(w.itemLocks, i);
				for (int j = 0; j < 3; j++)
				{
					if (w.itemIncs != null && i * 3 + j < w.itemIncs.Length)
					{
						array6[i * 3 + j] = w.itemIncs[i * 3 + j];
					}
				}
			}
			if (num2 > 0 && (Object)(object)w.itemButtons[0] != (Object)null)
			{
				Transform parent = ((Component)w.itemButtons[0]).transform.parent;
				GameObject gameObject = ((Component)w.itemButtons[0]).gameObject;
				for (int k = num2; k < num3; k++)
				{
					GameObject val2 = Object.Instantiate<GameObject>(gameObject, parent);
					((Object)val2).name = "circle-ext-" + k;
					array[k] = val2.GetComponent<UIButton>();
					Transform transform = val2.transform;
					array2[k] = ChildImage(transform, "icon");
					array3[k] = ChildImage(transform, "fg");
					array4[k] = ChildText(transform, "cnt-text");
					array5[k] = ChildImage(transform, "locked");
					for (int l = 0; l < 3; l++)
					{
						array6[k * 3 + l] = ChildImage(transform, "icon/inc-" + (l + 1));
					}
				}
			}
			value = new Full
			{
				Buttons = array,
				Icons = array2,
				Percents = array3,
				Counts = array4,
				Locks = array5,
				Incs = array6
			};
			Cache[w] = value;
			Apply(w, value);
			Plugin.Log.LogInfo((object)("[lab-ui] matrix slots ready: " + num2 + " -> " + num3 + " (matrixIds=" + val + ")"));
		}

		private static void Apply(UILabWindow w, Full full)
		{
			w.itemButtons = full.Buttons;
			w.itemIcons = full.Icons;
			w.itemPercents = full.Percents;
			w.itemCountTexts = full.Counts;
			w.itemLocks = full.Locks;
			w.itemIncs = full.Incs;
		}

		private static int VanillaBound(UILabWindow w, Full full)
		{
			if (_protosField == null)
			{
				_protosField = AccessTools.Field(typeof(UILabWindow), "matrixProtos");
			}
			if (_recipesField == null)
			{
				_recipesField = AccessTools.Field(typeof(UILabWindow), "matrixRecipes");
			}
			int num = 0;
			if (_protosField != null && _protosField.GetValue(w) is ItemProto[] array)
			{
				num = array.Length;
			}
			if (_recipesField != null && _recipesField.GetValue(w) is RecipeProto[] array2)
			{
				num = ((num == 0) ? array2.Length : Math.Min(num, array2.Length));
			}
			if (num <= 0)
			{
				int[] matrixIds = LabComponent.matrixIds;
				num = ((matrixIds != null) ? matrixIds.Length : 6);
			}
			return Math.Min(num, full.Buttons.Length);
		}

		private static void Trim(UILabWindow w)
		{
			if (Cache.TryGetValue(w, out var value) && value != null)
			{
				int num = VanillaBound(w, value);
				if (num >= value.Buttons.Length)
				{
					Apply(w, value);
					return;
				}
				UIButton[] array = (UIButton[])(object)new UIButton[num];
				Image[] array2 = (Image[])(object)new Image[num];
				Image[] array3 = (Image[])(object)new Image[num];
				Text[] array4 = (Text[])(object)new Text[num];
				Image[] array5 = (Image[])(object)new Image[num];
				Image[] array6 = (Image[])(object)new Image[num * 3];
				Array.Copy(value.Buttons, array, num);
				Array.Copy(value.Icons, array2, num);
				Array.Copy(value.Percents, array3, num);
				Array.Copy(value.Counts, array4, num);
				Array.Copy(value.Locks, array5, num);
				Array.Copy(value.Incs, array6, num * 3);
				w.itemButtons = array;
				w.itemIcons = array2;
				w.itemPercents = array3;
				w.itemCountTexts = array4;
				w.itemLocks = array5;
				w.itemIncs = array6;
			}
		}

		private static void Restore(UILabWindow w)
		{
			if (Cache.TryGetValue(w, out var value) && value != null)
			{
				Apply(w, value);
			}
		}

		private static void Arrange(UILabWindow w)
		{
			//IL_00d3: 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)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if (!Cache.TryGetValue(w, out var value) || value == null || (Object)(object)w.windowTrans == (Object)null)
			{
				return;
			}
			int[] matrixIds = LabComponent.matrixIds;
			int num = ((matrixIds != null) ? matrixIds.Length : 6);
			Transform val = ((Component)w).transform.Find("matrix-group/matrix/lines");
			if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(false);
			}
			for (int i = 0; i < value.Buttons.Length; i++)
			{
				UIButton val2 = value.Buttons[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val2).gameObject;
				if (!gameObject.activeSelf)
				{
					gameObject.SetActive(true);
				}
				Transform transform = ((Component)val2).transform;
				RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)val3 != (Object)null)
				{
					val3.anchoredPosition = new Vector2((float)(i % 3 - 1) * 96f, (float)(1 - i / 3) * 96f);
					if (((Transform)val3).localScale != Vector3.one)
					{
						((Transform)val3).localScale = Vector3.one;
					}
				}
				if (i < num)
				{
					continue;
				}
				if ((Object)(object)value.Icons[i] != (Object)null)
				{
					value.Icons[i].sprite = null;
					((Behaviour)value.Icons[i]).enabled = false;
				}
				if ((Object)(object)value.Percents[i] != (Object)null)
				{
					value.Percents[i].fillAmount = 0f;
				}
				if ((Object)(object)value.Counts[i] != (Object)null)
				{
					value.Counts[i].text = "";
				}
				if ((Object)(object)value.Locks[i] != (Object)null)
				{
					((Behaviour)value.Locks[i]).enabled = true;
				}
				for (int j = 0; j < 3; j++)
				{
					if ((Object)(object)value.Incs[i * 3 + j] != (Object)null)
					{
						((Behaviour)value.Incs[i * 3 + j]).enabled = false;
					}
				}
				if ((Object)(object)val2.button != (Object)null)
				{
					((Selectable)val2.button).interactable = false;
				}
				val2.tips.itemId = 0;
			}
			CenterGrid(w, value);
		}

		private static void CenterGrid(UILabWindow w, Full full)
		{
			//IL_0032: 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)
			//IL_0056: 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_0044: 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_00df: 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_00ea: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: 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_031d: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = ((Component)w).transform.Find("matrix-group/matrix");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val == (Object)null || full.Buttons == null || full.Buttons.Length == 0)
			{
				return;
			}
			if (((Transform)val).localScale != Vector3.one)
			{
				((Transform)val).localScale = Vector3.one;
			}
			RectTransform windowTrans = w.windowTrans;
			Rect rect = windowTrans.rect;
			float num = ((Rect)(ref rect)).xMax;
			Transform parent = ((Transform)val).parent;
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform child = parent.GetChild(i);
				RectTransform val2 = (RectTransform)(object)((child is RectTransform) ? child : null);
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && ((Component)val2).gameObject.activeInHierarchy && !(((Object)val2).name == "lines"))
				{
					val2.GetWorldCorners(array);
					Vector3 val3 = ((Transform)windowTrans).InverseTransformPoint(array[0]);
					Vector3 val4 = ((Transform)windowTrans).InverseTransformPoint(array[2]);
					if (!(val4.x - val3.x < 1f) && !(val4.y - val3.y < 1f) && val3.x > ((Rect)(ref rect)).xMin + ((Rect)(ref rect)).width * 0.35f)
					{
						num = Mathf.Min(num, val3.x);
					}
				}
			}
			float num2 = ((Rect)(ref rect)).xMin + 18f;
			float num3 = Mathf.Min(num - 16f, ((Rect)(ref rect)).xMax - 18f);
			if (num3 < num2 + 60f)
			{
				num3 = ((Rect)(ref rect)).xMax - 18f;
			}
			float num4 = ((Rect)(ref rect)).yMax - 56f;
			float num5 = ((Rect)(ref rect)).yMin + 14f;
			float num6 = Mathf.Max(60f, num3 - num2);
			float num7 = Mathf.Max(60f, num4 - num5);
			float num8 = Mathf.Clamp(Mathf.Min(num6 / 3f, num7 / 3f), 46f, 96f);
			float num9 = num8 * 3f;
			float num10 = num8 * 3f;
			float num11 = num2 + (num6 - num9) * 0.5f;
			float num12 = num4 - (num7 - num10) * 0.5f;
			float num13 = num8 / 96f;
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(num13, num13, 1f);
			Vector3 val8 = default(Vector3);
			for (int j = 0; j < full.Buttons.Length; j++)
			{
				UIButton val6 = full.Buttons[j];
				if ((Object)(object)val6 == (Object)null)
				{
					continue;
				}
				Transform transform = ((Component)val6).transform;
				RectTransform val7 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (!((Object)(object)val7 == (Object)null))
				{
					int num14 = j % 3;
					int num15 = j / 3;
					((Vector3)(ref val8))..ctor(num11 + ((float)num14 + 0.5f) * num8, num12 - ((float)num15 + 0.5f) * num8, 0f);
					Vector3 val9 = ((Transform)windowTrans).TransformPoint(val8);
					Vector3 val10 = ((Transform)val7).position - val9;
					if (((Vector3)(ref val10)).sqrMagnitude > 0.25f)
					{
						((Transform)val7).position = val9;
					}
					val10 = ((Transform)val7).localScale - val5;
					if (((Vector3)(ref val10)).sqrMagnitude > 1E-06f)
					{
						((Transform)val7).localScale = val5;
					}
				}
			}
		}

		private static Image Get(Image[] arr, int i)
		{
			if (arr == null || i >= arr.Length)
			{
				return null;
			}
			return arr[i];
		}

		private static Image ChildImage(Transform t, string path)
		{
			Transform val = t.Find(path);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<Image>();
		}

		private static Text ChildText(Transform t, string path)
		{
			Transform val = t.Find(path);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<Text>();
		}
	}
	internal static class NeedsUtil
	{
		public static bool Contains(int[] needs, int item)
		{
			if (needs == null)
			{
				return false;
			}
			for (int i = 0; i < needs.Length; i++)
			{
				if (needs[i] == item)
				{
					return true;
				}
			}
			return false;
		}

		public static int IndexOf(int[] needs, int item)
		{
			if (needs == null)
			{
				return -1;
			}
			for (int i = 0; i < needs.Length; i++)
			{
				if (needs[i] == item)
				{
					return i;
				}
			}
			return -1;
		}

		public static int SplitInc(ref int n, ref int m, int p)
		{
			if (n == 0)
			{
				return 0;
			}
			int num = m / n;
			int num2 = m - num * n;
			n -= p;
			num2 -= n;
			num = ((num2 > 0) ? (num * p + num2) : (num * p));
			m -= num;
			return num;
		}

		internal static bool Enabled()
		{
			try
			{
				return Plugin.EnableNeedsLoop == null || Plugin.EnableNeedsLoop.Value;
			}
			catch
			{
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(AssemblerComponent), "SetRecipe")]
	internal static class AssemblerNeedsResizePatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref AssemblerComponent __instance)
		{
			try
			{
				RecipeExecuteData recipeExecuteData = __instance.recipeExecuteData;
				if (recipeExecuteData != null && recipeExecuteData.requires != null)
				{
					int num = Math.Max(6, recipeExecuteData.requires.Length);
					if (__instance.needs == null || __instance.needs.Length != num)
					{
						__instance.needs = new int[num];
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] resize needs: " + ex));
			}
		}
	}
	internal static class CargoPathFields
	{
		internal static readonly FieldRef<CargoPath, int> BufLen = AccessTools.FieldRefAccess<CargoPath, int>("bufferLength");

		internal static readonly FieldRef<CargoPath, int> UpdLen = AccessTools.FieldRefAccess<CargoPath, int>("updateLen");
	}
	[HarmonyPatch]
	internal static class CargoPathTryPickItemPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(CargoPath), "TryPickItem", new Type[6]
			{
				typeof(int),
				typeof(int),
				typeof(int),
				typeof(int[]),
				typeof(byte).MakeByRefType(),
				typeof(byte).MakeByRefType()
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(CargoPath __instance, int index, int length, int filter, int[] needs, out byte stack, out byte inc, ref int __result)
		{
			stack = 1;
			inc = 0;
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				byte[] buffer = __instance.buffer;
				CargoContainer cargoContainer = __instance.cargoContainer;
				lock (buffer)
				{
					int num = CargoPathFields.BufLen.Invoke(__instance);
					if (index < 0)
					{
						index = 0;
					}
					else if (index >= num)
					{
						index = num - 1;
					}
					int num2 = index + length;
					if (num2 > num)
					{
						num2 = num;
					}
					for (int i = index; i < num2; i++)
					{
						if (buffer[i] < 246)
						{
							continue;
						}
						i += 250 - buffer[i];
						int num3 = buffer[i + 1] - 1 + (buffer[i + 2] - 1) * 100 + (buffer[i + 3] - 1) * 10000 + (buffer[i + 4] - 1) * 1000000;
						int item = cargoContainer.cargoPool[num3].item;
						stack = cargoContainer.cargoPool[num3].stack;
						inc = cargoContainer.cargoPool[num3].inc;
						if ((filter == 0 || item == filter) && NeedsUtil.Contains(needs, item))
						{
							Array.Clear(buffer, i - 4, 10);
							int num4 = i + 5 + 1;
							if (CargoPathFields.UpdLen.Invoke(__instance) < num4)
							{
								CargoPathFields.UpdLen.Invoke(__instance) = num4;
							}
							cargoContainer.RemoveCargo(num3);
							__result = item;
							return false;
						}
						__result = 0;
						return false;
					}
				}
				__result = 0;
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] CargoPath.TryPickItem: " + ex));
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(CargoPath), "TryPickItemAtRear")]
	internal static class CargoPathTryPickItemAtRearPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(CargoPath __instance, int[] needs, out int needIdx, out byte stack, out byte inc, ref int __result)
		{
			needIdx = -1;
			stack = 1;
			inc = 0;
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				byte[] buffer = __instance.buffer;
				CargoContainer cargoContainer = __instance.cargoContainer;
				lock (buffer)
				{
					int num = CargoPathFields.BufLen.Invoke(__instance) - 5 - 1;
					if (num >= 0 && num < buffer.Length && buffer[num] == 250)
					{
						int num2 = buffer[num + 1] - 1 + (buffer[num + 2] - 1) * 100 + (buffer[num + 3] - 1) * 10000 + (buffer[num + 4] - 1) * 1000000;
						int item = cargoContainer.cargoPool[num2].item;
						stack = cargoContainer.cargoPool[num2].stack;
						inc = cargoContainer.cargoPool[num2].inc;
						int num3 = NeedsUtil.IndexOf(needs, item);
						if (num3 >= 0)
						{
							Array.Clear(buffer, num - 4, 10);
							int num4 = num + 5 + 1;
							if (CargoPathFields.UpdLen.Invoke(__instance) < num4)
							{
								CargoPathFields.UpdLen.Invoke(__instance) = num4;
							}
							cargoContainer.RemoveCargo(num2);
							needIdx = num3;
							__result = item;
							return false;
						}
					}
				}
				__result = 0;
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] CargoPath.TryPickItemAtRear: " + ex));
				return true;
			}
		}
	}
	[HarmonyPatch(typeof(CargoPath), "CanPickItemFromRear")]
	internal static class CargoPathCanPickItemFromRearPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(CargoPath __instance, int[] needs, ref bool __result)
		{
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				byte[] buffer = __instance.buffer;
				CargoContainer cargoContainer = __instance.cargoContainer;
				int num = CargoPathFields.BufLen.Invoke(__instance) - 5 - 1;
				if (num >= 0 && num < buffer.Length && buffer[num] == 250)
				{
					int num2 = buffer[num + 1] - 1 + (buffer[num + 2] - 1) * 100 + (buffer[num + 3] - 1) * 10000 + (buffer[num + 4] - 1) * 1000000;
					int item = cargoContainer.cargoPool[num2].item;
					if (item != 0 && NeedsUtil.Contains(needs, item))
					{
						__result = true;
						return false;
					}
				}
				__result = false;
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] CanPickItemFromRear: " + ex));
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class StorageTakeTailItemsPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(StorageComponent), "TakeTailItems", new Type[5]
			{
				typeof(int).MakeByRefType(),
				typeof(int).MakeByRefType(),
				typeof(int[]),
				typeof(int).MakeByRefType(),
				typeof(bool)
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(StorageComponent __instance, ref int itemId, ref int count, int[] needs, out int inc, bool useBan, ref bool __result)
		{
			inc = 0;
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				if (count == 0)
				{
					itemId = 0;
					count = 0;
					__result = false;
					return false;
				}
				bool flag = false;
				int num = count;
				count = 0;
				GRID[] grids = __instance.grids;
				int num2 = (useBan ? (__instance.size - __instance.bans - 1) : (__instance.size - 1));
				if (num2 >= grids.Length)
				{
					num2 = grids.Length - 1;
				}
				for (int num3 = num2; num3 >= 0; num3--)
				{
					if (grids[num3].itemId != 0 && grids[num3].count != 0 && (itemId == 0 || grids[num3].itemId == itemId))
					{
						flag = true;
						if (NeedsUtil.Contains(needs, grids[num3].itemId))
						{
							itemId = grids[num3].itemId;
							if (grids[num3].count > num)
							{
								inc += NeedsUtil.SplitInc(ref grids[num3].count, ref grids[num3].inc, num);
								count += num;
								num = 0;
								break;
							}
							inc += grids[num3].inc;
							count += grids[num3].count;
							num -= grids[num3].count;
							grids[num3].itemId = grids[num3].filter;
							grids[num3].count = 0;
							grids[num3].inc = 0;
							if (grids[num3].filter == 0)
							{
								grids[num3].stackSize = 0;
							}
						}
					}
				}
				if (count == 0)
				{
					itemId = 0;
					count = 0;
				}
				else
				{
					__instance.lastFullItem = -1;
					__instance.NotifyStorageChange();
				}
				__result = flag;
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] TakeTailItems: " + ex));
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class StationTakeItemPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(StationComponent), "TakeItem", new Type[4]
			{
				typeof(int).MakeByRefType(),
				typeof(int).MakeByRefType(),
				typeof(int[]),
				typeof(int).MakeByRefType()
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(StationComponent __instance, ref int _itemId, ref int _count, int[] _needs, out int _inc)
		{
			_inc = 0;
			if (_needs == null || _needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				if (_itemId > 0 && _count > 0 && NeedsUtil.Contains(_needs, _itemId))
				{
					StationStore[] storage = __instance.storage;
					if (storage != null)
					{
						lock (storage)
						{
							for (int i = 0; i < storage.Length; i++)
							{
								if (storage[i].itemId == _itemId && storage[i].count > 0)
								{
									_count = ((_count < storage[i].count) ? _count : storage[i].count);
									_itemId = storage[i].itemId;
									_inc = NeedsUtil.SplitInc(ref storage[i].count, ref storage[i].inc, _count);
									return false;
								}
							}
						}
					}
				}
				_itemId = 0;
				_count = 0;
				_inc = 0;
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] StationComponent.TakeItem: " + ex));
				return true;
			}
		}
	}
	[HarmonyPatch]
	internal static class PickFromIntM2Patch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlanetFactory), "PickFrom", new Type[6]
			{
				typeof(int),
				typeof(int),
				typeof(int),
				typeof(int[]),
				typeof(byte).MakeByRefType(),
				typeof(byte).MakeByRefType()
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(PlanetFactory __instance, int entityId, int offset, int filter, int[] needs, out byte stack, out byte inc, ref int __result)
		{
			stack = 1;
			inc = 0;
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				if (entityId <= 0 || entityId >= __instance.entityCursor)
				{
					return true;
				}
				int assemblerId = __instance.entityPool[entityId].assemblerId;
				int labId = __instance.entityPool[entityId].labId;
				if (assemblerId <= 0 && labId <= 0)
				{
					return true;
				}
				lock (__instance.entityMutexs[entityId])
				{
					int[] products;
					int[] produced;
					if (assemblerId > 0)
					{
						ref AssemblerComponent reference = ref __instance.factorySystem.assemblerPool[assemblerId];
						products = reference.recipeExecuteData?.products;
						produced = reference.produced;
					}
					else
					{
						ref LabComponent reference2 = ref __instance.factorySystem.labPool[labId];
						products = reference2.recipeExecuteData?.products;
						produced = reference2.produced;
					}
					__result = M2Pick(products, produced, filter, needs);
					return false;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] PickFrom(int): " + ex));
				return true;
			}
		}

		internal static int M2Pick(int[] products, int[] produced, int filter, int[] needs)
		{
			if (products == null || produced == null)
			{
				return 0;
			}
			int num = products.Length;
			for (int i = 0; i < num; i++)
			{
				int num2 = products[i];
				if (num2 > 0 && produced[i] > 0 && (filter == 0 || filter == num2) && NeedsUtil.Contains(needs, num2))
				{
					produced[i]--;
					return num2;
				}
			}
			return 0;
		}
	}
	[HarmonyPatch]
	internal static class PickFromUIntM2Patch
	{
		private const uint AssemblerTag = 33554432u;

		private const uint LabTag = 117440512u;

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlanetFactory), "PickFrom", new Type[6]
			{
				typeof(uint),
				typeof(int),
				typeof(int),
				typeof(int[]),
				typeof(byte).MakeByRefType(),
				typeof(byte).MakeByRefType()
			}, (Type[])null);
		}

		[HarmonyPrefix]
		private static bool Prefix(PlanetFactory __instance, uint ioTargetTypedId, int offset, int filter, int[] needs, out byte stack, out byte inc, ref int __result)
		{
			stack = 1;
			inc = 0;
			if (needs == null || needs.Length <= 6 || !NeedsUtil.Enabled())
			{
				return true;
			}
			try
			{
				uint num = ioTargetTypedId & 0xFF000000u;
				if (num != 33554432 && num != 117440512)
				{
					return true;
				}
				int num2 = (int)(ioTargetTypedId & 0xFFFFFF);
				if (num == 33554432)
				{
					if (num2 <= 0 || num2 >= __instance.factorySystem.assemblerCursor)
					{
						return true;
					}
					ref AssemblerComponent reference = ref __instance.factorySystem.assemblerPool[num2];
					if (reference.id <= 0)
					{
						return true;
					}
					int[] products = reference.recipeExecuteData?.products;
					int[] produced = reference.produced;
					lock (__instance.entityMutexs[reference.entityId])
					{
						__result = PickFromIntM2Patch.M2Pick(products, produced, filter, needs);
					}
				}
				else
				{
					if (num2 <= 0 || num2 >= __instance.factorySystem.labCursor)
					{
						return true;
					}
					ref LabComponent reference2 = ref __instance.factorySystem.labPool[num2];
					if (reference2.id <= 0)
					{
						return true;
					}
					int[] products = reference2.recipeExecuteData?.products;
					int[] produced = reference2.produced;
					lock (__instance.entityMutexs[reference2.entityId])
					{
						__result = PickFromIntM2Patch.M2Pick(products, produced, filter, needs);
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[m2] PickFrom(uint): " + ex));
				return true;
			}
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(AssemblerComponent), "UpdateNeeds")]
		internal static class AssemblerUpdateNeedsPatch
		{
			private static long _hit;

			[HarmonyPostfix]
			private static void Postfix(ref AssemblerComponent __instance)
			{
				RecipeExecuteData recipeExecuteData = __instance.recipeExecuteData;
				if (recipeExecuteData == null)
				{
					return;
				}
				int[] requires = recipeExecuteData.requires;
				int[] needs = __instance.needs;
				int[] served = __instance.served;
				int[] requireCounts = recipeExecuteData.requireCounts;
				if (requires == null || needs == null || served == null || requireCounts == null)
				{
					return;
				}
				int num = requires.Length;
				if (num <= 6)
				{
					return;
				}
				int num2 = __instance.speedOverride * 180 / recipeExecuteData.timeSpend + 1;
				if (num2 < 2)
				{
					num2 = 2;
				}
				int num3 = needs.Length;
				if (num3 <= 0)
				{
					return;
				}
				int i = 0;
				if (num3 >= num)
				{
					for (int j = 0; j < num; j++)
					{
						if (i >= num3)
						{
							break;
						}
						if (j < served.Length && j < requireCounts.Length && served[j] < requireCounts[j] * num2)
						{
							needs[i++] = requires[j];
						}
					}
				}
				else
				{
					int num4 = (int)(GameMain.gameTick % num);
					if (num4 < 0)
					{
						num4 += num;
					}
					for (int k = 0; k < num; k++)
					{
						if (i >= num3)
						{
							break;
						}
						int num5 = num4 + k;
						if (num5 >= num)
						{
							num5 -= num;
						}
						if (num5 < served.Length && num5 < requireCounts.Length && served[num5] < requireCounts[num5] * num2)
						{
							needs[i++] = requires[num5];
						}
					}
				}
				for (; i < num3; i++)
				{
					needs[i] = 0;
				}
				if (Plugin.Verbose.Value && _hit++ % 120 == 0L)
				{
					Plugin.Log.LogInfo((object)("[needs] recipe=" + __instance.recipeId + " reqLen=" + num + " needs=" + Join(needs) + " served=" + Join(served)));
				}
			}
		}

		[HarmonyPatch]
		internal static class InsertIntoIntPatch
		{
			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(PlanetFactory), "InsertInto", new Type[6]
				{
					typeof(int),
					typeof(int),
					typeof(int),
					typeof(byte),
					typeof(byte),
					typeof(byte).MakeByRefType()
				}, (Type[])null);
			}

			[HarmonyPrefix]
			private static bool Prefix(PlanetFactory __instance, int entityId, int itemId, byte itemCount, byte itemInc, out byte remainInc, ref int __result)
			{
				remainInc = itemInc;
				if (entityId <= 0 || entityId >= __instance.entityPool.Length)
				{
					return true;
				}
				if (__instance.entityPool[entityId].beltId > 0)
				{
					return true;
				}
				int assemblerId = __instance.entityPool[entityId].assemblerId;
				if (assemblerId > 0)
				{
					ref AssemblerComponent reference = ref __instance.factorySystem.assemblerPool[assemblerId];
					if (reference.recipeExecuteData == null)
					{
						__result = 0;
						return false;
					}
					int[] requires = reference.recipeExecuteData.requires;
					if (requires == null || requires.Length <= 6)
					{
						return true;
					}
					lock (__instance.entityMutexs[entityId])
					{
						for (int i = 0; i < requires.Length; i++)
						{
							if (requires[i] == itemId)
							{
								reference.served[i] += itemCount;
								reference.incServed[i] += itemInc;
								remainInc = 0;
								__result = itemCount;
								if (Plugin.Verbose.Value)
								{
									Plugin.Log.LogInfo((object)("[insert-int] eid=" + entityId + " item=" + itemId + " slot=" + i + " served=" + reference.served[i]));
								}
								return false;
							}
						}
					}
					__result = 0;
					return false;
				}
				int labId = __instance.entityPool[entityId].labId;
				if (labId > 0)
				{
					return HandleLab(__instance, entityId, labId, itemId, itemCount, itemInc, out remainInc, ref __result);
				}
				return true;
			}
		}

		[HarmonyPatch]
		internal static class InsertIntoUIntPatch
		{
			private const uint AssemblerTag = 33554432u;

			private const uint LabTag = 117440512u;

			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(typeof(PlanetFactory), "InsertInto", new Type[6]
				{
					typeof(uint),
					typeof(int),
					typeof(int),
					typeof(byte),
					typeof(byte),
					typeof(byte).MakeByRefType()
				}, (Type[])null);
			}

			[HarmonyPrefix]
			private static bool Prefix(PlanetFactory __instance, uint ioTargetTypedId, int itemId, byte itemCount, byte itemInc, out byte remainInc, ref int __result)
			{
				remainInc = itemInc;
				switch (ioTargetTypedId & 0xFF000000u)
				{
				case 117440512u:
				{
					int num2 = (int)(ioTargetTypedId & 0xFFFFFF);
					LabComponent[] array2 = ((__instance.factorySystem != null) ? __instance.factorySystem.labPool : null);
					if (array2 == null || num2 <= 0 || num2 >= array2.Length)
					{
						__result = 0;
						return false;
					}
					return HandleLab(__instance, array2[num2].entityId, num2, itemId, itemCount, itemInc, out remainInc, ref __result);
				}
				default:
					return true;
				case 33554432u:
				{
					int num = (int)(ioTargetTypedId & 0xFFFFFF);
					AssemblerComponent[] array = ((__instance.factorySystem != null) ? __instance.factorySystem.assemblerPool : null);
					if (array == null || num <= 0 || num >= array.Length)
					{
						__result = 0;
						return false;
					}
					ref AssemblerComponent reference = ref array[num];
					if (reference.id <= 0)
					{
						__result = 0;
						return false;
					}
					if (reference.recipeExecuteData == null)
					{
						__result = 0;
						return false;
					}
					int[] requires = reference.recipeExecuteData.requires;
					if (requires == null || requires.Length <= 6)
					{
						return true;
					}
					int entityId = reference.entityId;
					if (entityId <= 0 || entityId >= __instance.entityMutexs.Length)
					{
						return true;
					}
					lock (__instance.entityMutexs[entityId])
					{
						for (int i = 0; i < requires.Length; i++)
						{
							if (requires[i] == itemId)
							{
								reference.served[i] += itemCount;
								reference.incServed[i] += itemInc;
								remainInc = 0;
								__result = itemCount;
								if (Plugin.Verbose.Value)
								{
									Plugin.Log.LogInfo((object)("[insert-uint] assembler=" + num + " item=" + itemId + " slot=" + i + " served=" + reference.served[i]));
								}
								return false;
							}
						}
					}
					__result = 0;
					return false;
				}
				}
			}
		}

		private static bool HandleLab(PlanetFactory factory, int entityId, int labId, int itemId, byte itemCount, byte itemInc, out byte remainInc, ref int __result)
		{
			remainInc = itemInc;
			LabComponent[] array = ((factory.factorySystem != null) ? factory.factorySystem.labPool : null);
			if (array == null || labId >= array.Length)
			{
				__result = 0;
				return false;
			}
			ref LabComponent reference = ref array[labId];
			if (reference.id <= 0)
			{
				__result = 0;
				return false;
			}
			lock (factory.entityMutexs[entityId])
			{
				if (reference.researchMode)
				{
					int num = Array.IndexOf(LabComponent.matrixIds, itemId);
					if (num >= 0 && reference.matrixServed != null && num < reference.matrixServed.Length)
					{
						reference.matrixServed[num] += 3600 * itemCount;
						reference.matrixIncServed[num] += 3600 * itemInc;
						remainInc = 0;
						__result = itemCount;
						return false;
					}
					__result = 0;
					return false;
				}
				int[] array2 = reference.recipeExecuteData?.requires;
				if (array2 != null && array2.Length > 6 && reference.served != null)
				{
					for (int i = 0; i < array2.Length && i < reference.served.Length; i++)
					{
						if (array2[i] == itemId)
						{
							reference.served[i] += itemCount;
							reference.incServed[i] += itemInc;
							remainInc = 0;
							__result = itemCount;
							return false;
						}
					}
					__result = 0;
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(PowerSystem), "GameTick", new Type[]
		{
			typeof(long),
			typeof(bool),
			typeof(bool),
			typeof(int)
		})]
		private static string Join(int[] a)
		{
			if (a == null)
			{
				return "null";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('[');
			for (int i = 0; i < a.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append(a[i]);
			}
			stringBuilder.Append(']');
			return stringBuilder.ToString();
		}
	}
	[BepInPlugin("star4wish.dsp.recipeslots", "DSP-RecipeSlots", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "star4wish.dsp.recipeslots";

		public const string NAME = "DSP-RecipeSlots";

		public const string VERSION = "1.2.0";

		public static Plugin Instance;

		public static ManualLogSource Log;

		public static Harmony Harmony;

		public static ConfigEntry<bool> Verbose;

		public static ConfigEntry<string> LabExtraMatrixIds;

		public static ConfigEntry<bool> EnablePatches;

		public static ConfigEntry<bool> EnableNeedsLoop;

		private void Awake()
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			EnablePatches = ((BaseUnityPlugin)this).Config.Bind<bool>("Core", "EnablePatches", true, "启用全部玩法补丁。false 时只保留调试通道,用于排查兼容性问题(区分「是不是本插件导致」)。");
			EnableNeedsLoop = ((BaseUnityPlugin)this).Config.Bind<bool>("Core", "EnableNeedsLoop", true, "M2:needs 按配方长度全长填充并把取料匹配改为循环(去掉轮转占空比损失)。关闭则回退到 6 格轮转。");
			Verbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Verbose", false, "打印补丁命中诊断日志。");
			LabExtraMatrixIds = ((BaseUnityPlugin)this).Config.Bind<string>("Lab", "ExtraMatrixIds", "", "额外矩阵物品 ID(逗号分隔,必须紧接 6006 连续,如 6007)。用于研究站/科技 >6 种消耗;留空=不扩展。");
			Harmony = new Harmony("star4wish.dsp.recipeslots");
			Log.LogInfo((object)("[boot] awake, EnablePatches=" + EnablePatches.Value + " EnableNeedsLoop=" + EnableNeedsLoop.Value));
			if (EnablePatches.Value)
			{
				try
				{
					Harmony.PatchAll();
					Log.LogInfo((object)("[boot] PatchAll ok, patched=" + Harmony.GetPatchedMethods().Count()));
				}
				catch (Exception ex)
				{
					Log.LogError((object)("[boot] PatchAll FAILED: " + ex));
				}
			}
			else
			{
				Log.LogWarning((object)"Core.EnablePatches=false,全部玩法补丁已跳过(仅调试通道可用)");
			}
			DevChannel.Init(((BaseUnityPlugin)this).Config);
			Application.runInBackground = true;
			Log.LogInfo((object)"DSP-RecipeSlots 1.2.0 loaded (gameTick hooks armed)");
		}

		private void Update()
		{
			DevChannel.Tick();
		}
	}
	[HarmonyPatch(typeof(UIRecipeEntry), "SetRecipe")]
	internal static class RecipeEntryPatch
	{
		private static bool _err;

		[HarmonyPrefix]
		private static bool Prefix(UIRecipeEntry __instance, RecipeProto recipe)
		{
			try
			{
				if (recipe == null)
				{
					return true;
				}
				Ensure(__instance, recipe.Results.Length + recipe.Items.Length);
				Fill(__instance, recipe);
				return false;
			}
			catch (Exception ex)
			{
				if (!_err)
				{
					_err = true;
					Plugin.Log.LogError((object)("[recipe-entry] " + ex));
				}
				return true;
			}
		}

		private static void Ensure(UIRecipeEntry e, int need)
		{
			if (e.icons == null || e.icons.Length == 0 || need <= e.icons.Length)
			{
				return;
			}
			int num = e.icons.Length;
			Image[] array = (Image[])(object)new Image[need];
			Text[] array2 = (Text[])(object)new Text[need];
			Array.Copy(e.icons, array, num);
			Array.Copy(e.countTexts, array2, Math.Min(e.countTexts.Length, num));
			Image val = e.icons[0];
			Transform parent = ((Component)val).transform.parent;
			bool flag = e.countTexts != null && e.countTexts.Length != 0 && (Object)(object)e.countTexts[0] != (Object)null && ((Component)e.countTexts[0]).transform.IsChildOf(((Component)val).transform);
			Transform val2 = ((!flag && e.countTexts != null && e.countTexts.Length != 0 && (Object)(object)e.countTexts[0] != (Object)null) ? ((Component)e.countTexts[0]).transform.parent : null);
			for (int i = num; i < need; i++)
			{
				GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
				((Object)val3).name = ((Object)((Component)val).gameObject).name + "-ext" + i;
				Image val4 = val3.GetComponent<Image>();
				if ((Object)(object)val4 == (Object)null)
				{
					val4 = val3.GetComponentInChildren<Image>(true);
				}
				array[i] = val4;
				Text val5 = null;
				if (flag)
				{
					val5 = val3.GetComponentInChildren<Text>(true);
				}
				else if ((Object)(object)val2 != (Object)null)
				{
					GameObject obj = Object.Instantiate<GameObject>(((Component)e.countTexts[0]).gameObject, val2);
					((Object)obj).name = ((Object)((Component)e.countTexts[0]).gameObject).name + "-ext" + i;
					val5 = obj.GetComponent<Text>();
				}
				array2[i] = val5;
				val3.SetActive(false);
			}
			e.icons = array;
			e.countTexts = array2;
		}

		private static void Fill(UIRecipeEntry e, RecipeProto recipe)
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Invalid comparison between Unknown and I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Invalid comparison between Unknown and I4
			Image[] icons = e.icons;
			Text[] countTexts = e.countTexts;
			int num = 0;
			float num2 = 0f;
			for (int i = 0; i < recipe.Results.Length; i++)
			{
				if (num >= icons.Length)
				{
					break;
				}
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(recipe.Results[i]);
				if ((Object)(object)icons[num] != (Object)null)
				{
					icons[num].sprite = ((val != null) ? val.iconSprite : null);
				}
				if (countTexts != null && num < countTexts.Length && (Object)(object)countTexts[num] != (Object)null)
				{
					countTexts[num].text = recipe.ResultCounts[i].ToString();
				}
				if ((Object)(object)icons[num] != (Object)null)
				{
					((Graphic)icons[num]).rectTransform.anchoredPosition = new Vector2(num2, 0f);
					((Component)icons[num]).gameObject.SetActive(true);
				}
				num++;
				num2 += 40f;
			}
			if ((Object)(object)e.arrow != (Object)null)
			{
				e.arrow.anchoredPosition = new Vector2(num2, -27f);
			}
			if ((Object)(object)e.timeText != (Object)null)
			{
				e.timeText.text = (((int)recipe.Type == 8) ? ((float)recipe.ResultCounts[0] / (float)recipe.ItemCounts[0] * 100f + "%") : ((float)recipe.TimeSpend / 60f + " s"));
			}
			num2 += 40f;
			for (int j = 0; j < recipe.Items.Length; j++)
			{
				if (num >= icons.Length)
				{
					break;
				}
				ItemProto val2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(recipe.Items[j]);
				if ((Object)(object)icons[num] != (Object)null)
				{
					icons[num].sprite = ((val2 != null) ? val2.iconSprite : null);
				}
				if (countTexts != null && num < countTexts.Length && (Object)(object)countTexts[num] != (Object)null)
				{
					countTexts[num].text = (((int)recipe.Type == 8) ? "1" : recipe.ItemCounts[j].ToString());
				}
				if ((Object)(object)icons[num] != (Object)null)
				{
					((Graphic)icons[num]).rectTransform.anchoredPosition = new Vector2(num2, 0f);
					((Component)icons[num]).gameObject.SetActive(true);
				}
				num++;
				num2 += 40f;
			}
			for (int k = num; k < icons.Length; k++)
			{
				if ((Object)(object)icons[k] != (Object)null)
				{
					((Component)icons[k]).gameObject.SetActive(false);
				}
			}
		}
	}
	internal static class TechUiPatch
	{
		[HarmonyPatch(typeof(UITechNode), "UpdateInfoComplete")]
		internal static class NodePatch
		{
			[HarmonyPrefix]
			private static void Prefix(UITechNode __instance)
			{
				try
				{
					TechProto techProto = __instance.techProto;
					if (techProto != null && techProto.itemArray != null)
					{
						int need = techProto.itemArray.Length;
						__instance.costIcons = TechUiPatch.Ensure<Image>(__instance.costIcons, need, "cost-icon");
						__instance.costIconBds = TechUiPatch.Ensure<Image>(__instance.costIconBds, need, "cost-icon-bd");
						__instance.costButtons = TechUiPatch.Ensure<UIButton>(__instance.costButtons, need, "cost-button");
						__instance.costCountTexts = TechUiPatch.Ensure<Text>(__instance.costCountTexts, need, "cost-count");
						__instance.pCostIcons = TechUiPatch.Ensure<Image>(__instance.pCostIcons, need, "pcost-icon");
						__instance.pCostCountTexts = TechUiPatch.Ensure<Text>(__instance.pCostCountTexts, need, "pcost-count");
					}
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(UITechNode __instance)
			{
				try
				{
					TechProto techProto = __instance.techProto;
					if (techProto != null && techProto.itemArray != null)
					{
						int num = techProto.itemArray.Length;
						if (num > 6)
						{
							Widen(__instance.costGroup, __instance.costBg, null, num);
							Widen(__instance.pCostGroup, null, null, num);
						}
					}
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}
		}

		[HarmonyPatch(typeof(UITechTip), "UpdateInfoComplete")]
		internal static class TipPatch
		{
			[HarmonyPrefix]
			private static void Prefix(UITechTip __instance)
			{
				try
				{
					TechProto techProto = __instance.techProto;
					if (techProto != null && techProto.itemArray != null)
					{
						int need = techProto.itemArray.Length;
						__instance.costIcons = TechUiPatch.Ensure<Image>(__instance.costIcons, need, "tip-cost-icon");
						__instance.costButtons = TechUiPatch.Ensure<UIButton>(__instance.costButtons, need, "tip-cost-button");
						__instance.costCountTexts = TechUiPatch.Ensure<Text>(__instance.costCountTexts, need, "tip-cost-count");
					}
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}

			[HarmonyPostfix]
			private static void Postfix(UITechTip __instance)
			{
				try
				{
					TechProto techProto = __instance.techProto;
					if (techProto != null && techProto.itemArray != null)
					{
						int num = techProto.itemArray.Length;
						if (num > 6)
						{
							Widen(__instance.costGroup, null, __instance.panelRect, num);
						}
					}
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}
		}

		[HarmonyPatch(typeof(UITechTip), "UpdateLayoutDynamic")]
		internal static class TipLayoutPatch
		{
			[HarmonyPostfix]
			private static void Postfix(UITechTip __instance)
			{
				try
				{
					TechProto techProto = __instance.techProto;
					if (techProto != null && techProto.itemArray != null)
					{
						int num = techProto.itemArray.Length;
						if (num > 6)
						{
							Widen(__instance.costGroup, null, __instance.panelRect, num);
						}
					}
				}
				catch (Exception ex)
				{
					Log(ex);
				}
			}
		}

		private static bool _err;

		private static T[] Ensure<T>(T[] arr, int need, string tag) where T : Component
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			if (arr == null || arr.Length == 0)
			{
				return arr;
			}
			if (need < arr.Length)
			{
				for (int i = need; i < arr.Length; i++)
				{
					if ((Object)(object)arr[i] != (Object)null)
					{
						((Component)arr[i]).gameObject.SetActive(false);
					}
				}
				return arr;
			}
			if (need == arr.Length)
			{
				return arr;
			}
			int num = arr.Length;
			T[] array = new T[need];
			Array.Copy(arr, array, num);
			T val = (((Object)(object)arr[0] != (Object)null) ? arr[0] : arr[num - 1]);
			if ((Object)(object)val == (Object)null)
			{
				return arr;
			}
			Transform parent = ((Component)val).transform.parent;
			Transform transform = ((Component)val).transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Vector2 val3 = (((Object)(object)val2 != (Object)null) ? val2.anchoredPosition : Vector2.zero);
			float num2 = 46f;
			if (num > 1 && (Object)(object)arr[1] != (Object)null)
			{
				Transform transform2 = ((Component)arr[1]).transform;
				RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					num2 = val4.anchoredPosition.x - val3.x;
				}
				if (Mathf.Abs(num2) < 1f)
				{
					num2 = 46f;
				}
			}
			for (int j = num; j < need; j++)
			{
				GameObject val5 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
				((Object)val5).name = ((Object)((Component)val).gameObject).name + "-ext" + j;
				Transform transform3 = val5.transform;
				RectTransform val6 = (RectTransform)(object)((transform3 is RectTransform) ? transform3 : null);
				if ((Object)(object)val6 != (Object)null)
				{
					val6.anchoredPosition = new Vector2(val3.x + num2 * (float)j, val3.y);
				}
				val5.SetActive(false);
				T val7 = val5.GetComponent<T>();
				if ((Object)(object)val7 == (Object)null)
				{
					val7 = val5.GetComponentInChildren<T>(true);
				}
				array[j] = val7;
				if ((Object)(object)val7 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("[tech-ui] clone " + tag + " i=" + j + " missing component " + typeof(T).Name));
				}
			}
			return array;
		}

		private static void Widen(RectTransform group, RectTransform bg, RectTransform panel, int need)
		{
			//IL_0019: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0061: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			float num = 46f * (float)need + 10f;
			if ((Object)(object)group != (Object)null && group.sizeDelta.x < num)
			{
				group.sizeDelta = new Vector2(num, group.sizeDelta.y);
			}
			if ((Object)(object)bg != (Object)null && bg.sizeDelta.x < num)
			{
				bg.sizeDelta = new Vector2(num, bg.sizeDelta.y);
			}
			if ((Object)(object)panel != (Object)null && panel.sizeDelta.x < num + 28f)
			{
				panel.sizeDelta = new Vector2(num + 28f, panel.sizeDelta.y);
			}
		}

		private static void Log(Exception ex)
		{
			if (!_err)
			{
				_err = true;
				Plugin.Log.LogError((object)("[tech-ui] " + ex));
			}
		}
	}
}