Decompiled source of ControlPanelPlus v1.0.0

ControlPanelPlus.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityEngine.UI.Youthcat;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ControlPanelPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("DSP MOD - ControlPanelPlus (logistics control panel QoL)")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+40b5260f88af877ae006ed729e0bc1572ae3ac76")]
[assembly: AssemblyProduct("ControlPanelPlus")]
[assembly: AssemblyTitle("ControlPanelPlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ControlPanelPlus
{
	public static class AstroListTweaks
	{
		private sealed class StarGroup
		{
			public int starIndex;

			public readonly List<EntryData> entries = new List<EntryData>();

			public string SortName()
			{
				if (entries.Count <= 0)
				{
					return "";
				}
				return entries[0].text;
			}
		}

		public static void Rebuild(UIControlPanelFilterPanel panel)
		{
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			if ((Object)(object)panel == (Object)null)
			{
				return;
			}
			UIComboBox astroFilterBox = panel.astroFilterBox;
			if ((Object)(object)astroFilterBox == (Object)null)
			{
				return;
			}
			NativeUi.EnableRichText(astroFilterBox);
			bool value = Cfg.SortByName.Value;
			int entryCount = astroFilterBox.entryCount;
			if (entryCount <= 2)
			{
				return;
			}
			List<EntryData> list = new List<EntryData>(entryCount);
			for (int i = 0; i < entryCount; i++)
			{
				list.Add(astroFilterBox.GetEntry(i));
			}
			if (list.Count <= 2)
			{
				return;
			}
			List<StarGroup> list2 = new List<StarGroup>();
			Dictionary<int, StarGroup> dictionary = new Dictionary<int, StarGroup>();
			for (int j = 2; j < list.Count; j++)
			{
				EntryData val = list[j];
				if (val != null)
				{
					int num = val.value / 100;
					if (!dictionary.TryGetValue(num, out var value2))
					{
						value2 = new StarGroup();
						value2.starIndex = num;
						dictionary[num] = value2;
						list2.Add(value2);
					}
					value2.entries.Add(val);
				}
			}
			if (value)
			{
				list2.Sort((StarGroup a, StarGroup b) => string.Compare(a.SortName(), b.SortName(), StringComparison.CurrentCultureIgnoreCase));
			}
			int num2 = int.MinValue;
			if (astroFilterBox.selectedIndex >= 0)
			{
				EntryData entry = astroFilterBox.GetEntry(astroFilterBox.selectedIndex);
				if (entry != null)
				{
					num2 = entry.value;
				}
			}
			bool onChangeEventEnabled = astroFilterBox.onChangeEventEnabled;
			astroFilterBox.onChangeEventEnabled = false;
			try
			{
				astroFilterBox.ClearEntries();
				astroFilterBox.AddEntry(list[0]);
				astroFilterBox.AddEntry(list[1]);
				int num3 = 0;
				try
				{
					if (GameMain.localStar != null)
					{
						num3 = GameMain.localStar.astroId;
					}
				}
				catch (Exception)
				{
				}
				if (num3 != 0)
				{
					astroFilterBox.AddEntry(new EntryData(Lang.T("当前星系", "Current star system"), num3));
				}
				for (int num4 = 0; num4 < list2.Count; num4++)
				{
					StarGroup starGroup = list2[num4];
					for (int num5 = 0; num5 < starGroup.entries.Count; num5++)
					{
						EntryData val2 = starGroup.entries[num5];
						bool flag = val2.value > 0 && val2.value % 100 == 0;
						val2.text = (flag ? ("<color=yellow>" + val2.text + "</color>") : ("  " + val2.text));
						astroFilterBox.AddEntry(val2);
					}
				}
				if (num2 != int.MinValue)
				{
					for (int num6 = 0; num6 < astroFilterBox.entryCount; num6++)
					{
						EntryData entry2 = astroFilterBox.GetEntry(num6);
						if (entry2 != null && entry2.value == num2)
						{
							astroFilterBox.selectedIndex = num6;
							break;
						}
					}
				}
			}
			finally
			{
				astroFilterBox.onChangeEventEnabled = onChangeEventEnabled;
			}
			CppLog.Debug($"astro list rebuilt: groups={list2.Count} entries={astroFilterBox.entryCount} sorted={value}");
		}

		public static void HandleHotkeys(UIControlPanelWindow w)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			UIControlPanelFilterPanel filterPanel = w.filterPanel;
			if ((Object)(object)filterPanel == (Object)null || (Object)(object)filterPanel.astroFilterBox == (Object)null)
			{
				return;
			}
			KeyCode value = Cfg.ListUp.Value;
			KeyCode value2 = Cfg.ListDown.Value;
			if ((int)value != 0 && (int)value2 != 0 && value == value2)
			{
				if (Input.GetKeyDown(value2))
				{
					StepList(filterPanel, 1);
				}
			}
			else
			{
				if ((int)value != 0 && Input.GetKeyDown(value))
				{
					StepList(filterPanel, -1);
				}
				if ((int)value2 != 0 && Input.GetKeyDown(value2))
				{
					StepList(filterPanel, 1);
				}
			}
			if (!NativeUi.MouseOverStorageSlot())
			{
				if (Input.GetKeyDown((KeyCode)276))
				{
					StepPlanet(w, -1);
				}
				if (Input.GetKeyDown((KeyCode)275))
				{
					StepPlanet(w, 1);
				}
				if (Input.GetKeyDown((KeyCode)273))
				{
					StepSelection(w, -1);
				}
				if (Input.GetKeyDown((KeyCode)274))
				{
					StepSelection(w, 1);
				}
			}
		}

		public static void StepList(UIControlPanelFilterPanel panel, int direction)
		{
			UIComboBox astroFilterBox = panel.astroFilterBox;
			int entryCount = astroFilterBox.entryCount;
			if (entryCount <= 0)
			{
				return;
			}
			int num = astroFilterBox.selectedIndex;
			if (num < 0)
			{
				num = ((direction > 0) ? (-1) : 0);
			}
			bool control = VFInput.control;
			for (int i = 0; i <= entryCount; i++)
			{
				num += direction;
				if (num < 0)
				{
					num = entryCount - 1;
				}
				if (num >= entryCount)
				{
					num = 0;
				}
				if (!control)
				{
					break;
				}
				EntryData entry = astroFilterBox.GetEntry(num);
				if (entry != null && (entry.value == -1 || (entry.value > 0 && entry.value % 100 == 0)))
				{
					break;
				}
			}
			if (num >= 0 && num < entryCount)
			{
				astroFilterBox.selectedIndex = num;
				CppLog.Debug($"astro list hotkey direction={direction} -> index={num}");
			}
		}

		public static void StepPlanet(UIControlPanelWindow w, int direction)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			List<ControlPanelTarget> list = WindowAccess.Results(w);
			if (list == null || list.Count == 0)
			{
				return;
			}
			int allowed = (int)w.filter.typeFilter;
			List<int> list2 = new List<int>();
			for (int i = 0; i < list.Count; i++)
			{
				if ((int)list[i].entryType == 0 && FirstEntryOfPlanet(list, list[i].astroId, allowed, out var _))
				{
					list2.Add(list[i].astroId);
				}
			}
			if (list2.Count != 0)
			{
				int num = AnchorAstroId(w, list);
				int num2 = list2.IndexOf(num);
				if (num2 < 0)
				{
					num2 = ((direction > 0) ? (-1) : 0);
				}
				int num3 = num2 + direction;
				if (num3 < 0)
				{
					num3 = list2.Count - 1;
				}
				if (num3 >= list2.Count)
				{
					num3 = 0;
				}
				if (FirstEntryOfPlanet(list, list2[num3], allowed, out var target2))
				{
					SelectTarget(w, target2);
					CppLog.Debug($"planet hotkey direction={direction} anchor={num} -> planet={list2[num3]}");
				}
			}
		}

		private static bool FirstEntryOfPlanet(List<ControlPanelTarget> results, int astroId, int allowed, out ControlPanelTarget target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < results.Count; i++)
			{
				ControlPanelTarget val = results[i];
				if ((int)val.entryType != 0 && val.astroId == astroId && (allowed & TypeBit(val.entryType)) != 0)
				{
					target = val;
					return true;
				}
			}
			target = ControlPanelTarget.none;
			return false;
		}

		public static void StepSelection(UIControlPanelWindow w, int direction)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			List<ControlPanelTarget> list = WindowAccess.Results(w);
			if (list == null || list.Count == 0)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] == w.selection)
				{
					num = i;
					break;
				}
			}
			int num2 = num;
			for (int j = 0; j < list.Count; j++)
			{
				num2 = ((num >= 0) ? (num2 + direction) : ((direction <= 0) ? (list.Count - 1) : 0));
				if (num2 < 0)
				{
					num2 = list.Count - 1;
				}
				if (num2 >= list.Count)
				{
					num2 = 0;
				}
				if ((int)list[num2].entryType != 0)
				{
					SelectTarget(w, list[num2]);
					break;
				}
			}
		}

		private static void SelectTarget(UIControlPanelWindow w, ControlPanelTarget target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			w.selection = target;
			try
			{
				w.FocusToEntryByObjId(target.astroId, target.objId, target.objType, true);
			}
			catch (Exception ex)
			{
				CppLog.Warn("focus entry failed: " + ex.Message);
			}
		}

		private static int AnchorAstroId(UIControlPanelWindow w, List<ControlPanelTarget> results)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			ControlPanelTarget selection = w.selection;
			if (!((ControlPanelTarget)(ref selection)).isNull && selection.astroId != 0)
			{
				return selection.astroId;
			}
			PlanetData val = ((GameMain.data != null) ? GameMain.data.localPlanet : null);
			if (val != null)
			{
				return val.astroId;
			}
			for (int i = 0; i < results.Count; i++)
			{
				if ((int)results[i].entryType == 0)
				{
					return results[i].astroId;
				}
			}
			return 0;
		}

		private static int TypeBit(EControlPanelEntryType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return (type - 1) switch
			{
				0 => 2, 
				1 => 4, 
				2 => 8, 
				3 => 16, 
				4 => 32, 
				5 => 64, 
				_ => 0, 
			};
		}
	}
	[HarmonyPatch(typeof(UIControlPanelFilterPanel))]
	internal static class AstroFilterBoxPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("ReconstructAstroFilterBox")]
		public static void AfterReconstruct(UIControlPanelFilterPanel __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				AstroListTweaks.Rebuild(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("astro list rebuild failed: " + ex);
			}
		}
	}
	public static class Cfg
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> CollapseAllDefaultMulti;

		public static ConfigEntry<bool> ExpandDefaultSingle;

		public static ConfigEntry<bool> EnableStarmapButton;

		public static ConfigEntry<bool> AllowRemoteItemTransfer;

		public static ConfigEntry<bool> EnableSlots;

		public static ConfigEntry<bool>[] SlotSwitches = new ConfigEntry<bool>[5];

		public static ConfigEntry<bool> ForcePaste;

		public static ConfigEntry<bool> DestroyReplacedItems;

		public static ConfigEntry<bool> AllowMinerOverflow;

		public static ConfigEntry<bool> EnableSettings;

		public static ConfigEntry<bool> SetChargePower;

		public static ConfigEntry<bool> SetTripDrones;

		public static ConfigEntry<bool> SetTripShips;

		public static ConfigEntry<bool> SetWarpDistance;

		public static ConfigEntry<bool> SetWarperNecessary;

		public static ConfigEntry<bool> SetOrbitCollector;

		public static ConfigEntry<bool> SetDeliveryDrones;

		public static ConfigEntry<bool> SetDeliveryShips;

		public static ConfigEntry<bool> SetPilerCount;

		public static ConfigEntry<bool> EnablePriority;

		public static ConfigEntry<KeyCode> CopyKey;

		public static ConfigEntry<KeyCode> PasteKey;

		public static ConfigEntry<bool> ItemFilterIntersect;

		public static ConfigEntry<bool> SortByName;

		public static ConfigEntry<KeyCode> ListUp;

		public static ConfigEntry<KeyCode> ListDown;

		public static bool SlotOn(int slotIndex)
		{
			if (slotIndex >= 0 && slotIndex < SlotSwitches.Length && SlotSwitches[slotIndex] != null)
			{
				return SlotSwitches[slotIndex].Value;
			}
			return false;
		}

		private static ConfigDescription Ordered(string description, int order)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = order
				}
			});
		}

		public static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "本 MOD 总开关。关闭后所有功能停止工作(补丁保持加载但不做任何事)。 / Master switch; when off every feature stops (patches stay loaded but do nothing).");
			CollapseAllDefaultMulti = config.Bind<bool>("Expand", "CollapseAllDefaultMulti", true, "多星球结果(全星区 / 某星系含多个有物流设施的星球)时,星球条目默认全部折叠。 / Collapse all planet rows by default when the result spans multiple planets.");
			ExpandDefaultSingle = config.Bind<bool>("Expand", "ExpandDefaultSingle", true, "单星球结果(筛选为某星球,或某星系只有 1 个星球有物流设施)时,该星球条目默认展开。 / Expand the planet row by default when the result is a single planet.");
			EnableStarmapButton = config.Bind<bool>("Locate", "EnableStarmapButton", true, Ordered("在每个星球条目的导航按钮左侧显示“星图定位”按钮(左键:保留面板;右键:关闭面板;Shift+右键:关闭面板并点亮导航线)。 / Show the locate button left of the navigation button (left click keeps the panel, right click closes it, Shift+right click also points the navigation line).", 30));
			AllowRemoteItemTransfer = config.Bind<bool>("Station", "AllowRemoteItemTransfer", false, "允许在总控面板上从非本地星球取放物品(右键拿取 / 手持物品左键放入 / 清空按钮取回)。若安装了 CheatEnabler,则由其 Architect 模式决定,本项不生效。 / Allow taking/placing items on stations of non-local planets (right click takes, left click places, the clear button retrieves). Inactive when CheatEnabler is installed (its Architect mode wins).");
			CopyKey = config.Bind<KeyCode>("StationCopy", "CopyKey", (KeyCode)44, Ordered("复制物流塔设置的按键(默认 < ,即逗号键)。仅当总控面板选中物流塔时生效。 / Key that copies the selected station settings (default <, comma). Only works while a station is selected in the control panel.", 240));
			PasteKey = config.Bind<KeyCode>("StationCopy", "PasteKey", (KeyCode)46, Ordered("粘贴物流塔设置的按键(默认 > ,即句号键)。按住 Shift 时批量粘贴到当前星球槽位设置相同的塔。 / Key that pastes onto the selected station(s) (default >, period). Hold Shift to batch paste onto every station on the current planet with the same slot layout.", 230));
			EnableSlots = config.Bind<bool>("StationCopy", "EnableSlots", true, Ordered("复制/粘贴第一块:槽位设置(物品种类、数量上限、本地/远程供需、运输机/运输船自动填充)。 / Block 1: slot settings (item type, max count, local/remote supply-demand, auto-replenish flags).", 220));
			for (int i = 0; i < SlotSwitches.Length; i++)
			{
				int num = i + 1;
				SlotSwitches[i] = config.Bind<bool>("StationCopy", "Slot" + num, true, Ordered("粘贴时是否写入第 " + num + " 槽位(关闭后该槽位保持不变)。 / Paste gate for slot " + num + " (when off the slot is left untouched).", 210 - i * 10));
			}
			ForcePaste = config.Bind<bool>("StationCopy", "ForcePaste", false, Ordered("强制粘贴:目标槽位已有其他物品时直接覆盖(关闭时跳过该槽位,默认关闭)。 / Force paste: overwrite a slot that already holds a different item (off = skip it, default off).", 270));
			DestroyReplacedItems = config.Bind<bool>("StationCopy", "DestroyReplacedItems", false, Ordered("强制粘贴或远程清空时直接销毁被替换的物品(关闭时取回到背包,默认关闭)。 / Destroy the replaced items instead of returning them (also applies to clearing remote slots, default off).", 260));
			AllowMinerOverflow = config.Bind<bool>("StationCopy", "AllowMinerOverflow", false, Ordered("大型采矿机 / 轨道采集器保留原始槽位上限并允许溢出(关闭时自动缩减到目标塔容量,默认关闭)。 / Keep the original slot max for vein collectors / orbital collectors and allow overflow (off = clamp to the target capacity, default off).", 250));
			EnableSettings = config.Bind<bool>("StationCopy", "EnableSettings", true, Ordered("复制/粘贴第二块:塔设置(充电功率、运输机/运输船路程、曲速路程、起送量、集装数量、轨道采集器开关、翘曲器必备)。 / Block 2: station settings (charging power, trip ranges, warp distance, delivery counts, piler count, orbital collector flag, warper requirement).", 130));
			SetChargePower = config.Bind<bool>("StationCopy", "SetChargePower", true, Ordered("粘贴时是否写入充电功率。 / Paste the charging power.", 120));
			SetTripDrones = config.Bind<bool>("StationCopy", "SetTripDrones", true, Ordered("粘贴时是否写入物流运输机航程。 / Paste the logistics drone trip range.", 110));
			SetTripShips = config.Bind<bool>("StationCopy", "SetTripShips", true, Ordered("粘贴时是否写入物流运输船航程(仅星际物流站)。 / Paste the logistics ship trip range (interstellar stations).", 100));
			SetWarpDistance = config.Bind<bool>("StationCopy", "SetWarpDistance", true, Ordered("粘贴时是否写入曲速启用距离(仅星际物流站)。 / Paste the warp enable distance (interstellar stations).", 90));
			SetWarperNecessary = config.Bind<bool>("StationCopy", "SetWarperNecessary", true, Ordered("粘贴时是否写入“翘曲器必备”开关(仅星际物流站)。 / Paste the warper-required flag (interstellar stations).", 80));
			SetOrbitCollector = config.Bind<bool>("StationCopy", "SetOrbitCollector", true, Ordered("粘贴时是否写入“包含轨道采集器”开关(仅星际物流站)。 / Paste the include-orbital-collectors flag (interstellar stations).", 70));
			SetDeliveryDrones = config.Bind<bool>("StationCopy", "SetDeliveryDrones", true, Ordered("粘贴时是否写入配送运输机数量。 / Paste the delivery drone count.", 60));
			SetDeliveryShips = config.Bind<bool>("StationCopy", "SetDeliveryShips", true, Ordered("粘贴时是否写入配送运输船数量(仅星际物流站)。 / Paste the delivery ship count (interstellar stations).", 50));
			SetPilerCount = config.Bind<bool>("StationCopy", "SetPilerCount", true, Ordered("粘贴时是否写入集装数量。 / Paste the piler count.", 40));
			EnablePriority = config.Bind<bool>("StationCopy", "EnablePriority", true, Ordered("复制/粘贴第三块:优先级设置(塔名/点对点、星际航路优先级、分组、槽位优先级锁)。 / Block 3: priority settings (station name/P2P, route priority, group, slot priority locks).", 30));
			ItemFilterIntersect = config.Bind<bool>("Filter", "ItemFilterIntersect", false, "物品筛选由“并集”改为“交集”:选 A+B 时只显示同时含有 A 和 B 的条目(默认关闭,保持原版并集)。 / Item filter works as intersection instead of the vanilla union (A and B instead of A or B).");
			SortByName = config.Bind<bool>("AstroList", "SortByName", true, "位置下拉框按星系名称排序(前两项“查看全星系 / 查看当前星球”保持不动)。内置星系/星球区分:星系名黄色、星球名缩进两格。 / Sort the location dropdown by star name (first two entries stay pinned). Built-in star/planet distinction: stars yellow, planets indented.");
			ListUp = config.Bind<KeyCode>("Hotkeys", "ListUp", (KeyCode)280, "位置下拉框向上切换一项(按住 Ctrl 只切换星系)。 / Step the location dropdown up (hold Ctrl to switch stars only).");
			ListDown = config.Bind<KeyCode>("Hotkeys", "ListDown", (KeyCode)281, "位置下拉框向下切换一项(按住 Ctrl 只切换星系)。 / Step the location dropdown down (hold Ctrl to switch stars only).");
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public int Order;
	}
	public static class ConfigWatcher
	{
		private static bool _initialized;

		private static bool _intersect;

		private static bool _sort;

		public static void Reset()
		{
			_initialized = false;
		}

		public static void Poll(UIControlPanelWindow window)
		{
			if ((Object)(object)window == (Object)null || !((ManualBehaviour)window).active)
			{
				return;
			}
			bool value = Cfg.ItemFilterIntersect.Value;
			bool value2 = Cfg.SortByName.Value;
			if (!_initialized)
			{
				_initialized = true;
				_intersect = value;
				_sort = value2;
				return;
			}
			bool flag = value != _intersect;
			bool flag2 = value2 != _sort;
			_intersect = value;
			_sort = value2;
			try
			{
				if (flag)
				{
					window.DetermineFilterResults();
					window.DetermineEntryVisible();
					CppLog.Info("item filter mode switched at runtime, result list refreshed");
				}
				if (flag2)
				{
					UIControlPanelFilterPanel filterPanel = window.filterPanel;
					if ((Object)(object)filterPanel != (Object)null)
					{
						filterPanel.ReconstructAstroFilterBox();
						filterPanel.RefreshAstroFilterBox();
						CppLog.Info("astro list sorting switched at runtime, dropdown rebuilt");
					}
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("config change refresh failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelWindow))]
	internal static class ControlPanelWindowPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("_OnOpen")]
		public static void OnOpenPrefix(UIControlPanelWindow __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				ExpandCollapse.OnWindowOpening();
			}
			catch (Exception ex)
			{
				CppLog.Error("window open prefix hook failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnOpen")]
		public static void OnOpen(UIControlPanelWindow __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				ExpandCollapse.OnWindowOpened(__instance);
				StationCopyPaste.OnWindowOpened();
				ItemFilterIntersect.EnsureToggleButton(__instance);
				ItemFilterShortcuts.Reset();
				ConfigWatcher.Reset();
				StationCopyPaste.ClearMultiSelect();
			}
			catch (Exception ex)
			{
				CppLog.Error("window open hook failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnClose")]
		public static void OnClose(UIControlPanelWindow __instance)
		{
			try
			{
				ExpandCollapse.OnWindowClosed();
				StationCopyPaste.OnWindowClosed();
				ItemFilterShortcuts.Reset();
				ConfigWatcher.Reset();
			}
			catch (Exception ex)
			{
				CppLog.Error("window close hook failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("DetermineFilterResults")]
		public static void AfterDetermineFilterResults(UIControlPanelWindow __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				ItemFilterIntersect.Apply(__instance);
				ExpandCollapse.AfterResults(__instance);
				StationCopyPaste.OnFilterResultsDetermined(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("result hook failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelWindow))]
	internal static class ControlPanelWindowInitPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("_OnInit")]
		public static void OnInit(UIControlPanelWindow __instance)
		{
			try
			{
				ExpandCollapse.OnGameInit();
				StationCopyPaste.OnWindowClosed();
				ItemFilterShortcuts.Reset();
				ConfigWatcher.Reset();
			}
			catch (Exception ex)
			{
				CppLog.Error("window init hook failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelFilterPanel))]
	internal static class ControlPanelFilterPanelPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("_OnOpen")]
		public static void OnOpen(UIControlPanelFilterPanel __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				NativeUi.EnableRichText(__instance.astroFilterBox);
			}
			catch (Exception ex)
			{
				CppLog.Error("filter panel open hook failed: " + ex);
			}
		}
	}
	internal static class CppLog
	{
		public const string Prefix = "[CPP] ";

		public static bool Verbose = true;

		public static void Debug(string message)
		{
			if (Verbose)
			{
				ManualLogSource log = ControlPanelPlusPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[CPP] " + message));
				}
			}
		}

		public static void Info(string message)
		{
			ManualLogSource log = ControlPanelPlusPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[CPP] " + message));
			}
		}

		public static void Warn(string message)
		{
			ManualLogSource log = ControlPanelPlusPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("[CPP] " + message));
			}
		}

		public static void Error(string message)
		{
			ManualLogSource log = ControlPanelPlusPlugin.Log;
			if (log != null)
			{
				log.LogError((object)("[CPP] " + message));
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelObjectEntry), "_OnUpdate")]
	internal static class EntryFocusSpeedPatch
	{
		private const float SpeedUp = 5f;

		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (!(val.opcode != OpCodes.Call) && val.operand is MethodInfo methodInfo && !(methodInfo.DeclaringType != typeof(Time)) && !(methodInfo.Name != "get_deltaTime"))
				{
					list.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_R4, (object)5f));
					list.Insert(i + 2, new CodeInstruction(OpCodes.Mul, (object)null));
					return list;
				}
			}
			CppLog.Warn("focus animation speed patch: Time.deltaTime call not found, using vanilla duration");
			return instructions;
		}
	}
	public static class ExpandCollapse
	{
		public sealed class PlanetRow
		{
			public int astroId;

			public int index;
		}

		private const int LocalKey = 0;

		private static readonly FieldInfo ResultsField = AccessTools.Field(typeof(UIControlPanelWindow), "results");

		private static string _appliedSignature;

		private static bool _sessionOpened;

		private static bool _skipDefaultsForThisOpen;

		private const string ToggleButtonName = "cpt-expand-toggle";

		private static UIButton _toggleButton;

		public static List<ControlPanelTarget> Results(UIControlPanelWindow w)
		{
			if ((Object)(object)w == (Object)null || ResultsField == null)
			{
				return null;
			}
			return ResultsField.GetValue(w) as List<ControlPanelTarget>;
		}

		public static List<PlanetRow> PlanetRows(UIControlPanelWindow w)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			List<PlanetRow> list = new List<PlanetRow>();
			List<ControlPanelTarget> list2 = Results(w);
			if (list2 == null)
			{
				return list;
			}
			for (int i = 0; i < list2.Count; i++)
			{
				if ((int)list2[i].entryType == 0)
				{
					PlanetRow planetRow = new PlanetRow();
					planetRow.astroId = list2[i].astroId;
					planetRow.index = i;
					list.Add(planetRow);
				}
			}
			return list;
		}

		public static void OnWindowOpening()
		{
			_appliedSignature = null;
			_skipDefaultsForThisOpen = _sessionOpened;
			_sessionOpened = true;
		}

		public static void OnGameInit()
		{
			_sessionOpened = false;
			_skipDefaultsForThisOpen = false;
			_appliedSignature = null;
			_toggleButton = null;
		}

		public static void OnWindowOpened(UIControlPanelWindow w)
		{
			EnsureTopButtons(w);
		}

		public static void OnWindowClosed()
		{
			_appliedSignature = null;
		}

		public static void AfterResults(UIControlPanelWindow w)
		{
			if ((Object)(object)w == (Object)null)
			{
				return;
			}
			List<PlanetRow> list = PlanetRows(w);
			string text = Signature(w, list);
			if (text == _appliedSignature)
			{
				return;
			}
			_appliedSignature = text;
			if (_skipDefaultsForThisOpen)
			{
				_skipDefaultsForThisOpen = false;
				UpdateToggleLabel(w);
				CppLog.Debug("panel reopened: keeping the previous planet expand state");
				return;
			}
			if (list.Count == 0)
			{
				UpdateToggleLabel(w);
				return;
			}
			bool flag = list.Count == 1;
			if (flag ? Cfg.ExpandDefaultSingle.Value : Cfg.CollapseAllDefaultMulti.Value)
			{
				bool expand = flag;
				Apply(w, list, expand, flag ? "单星球默认展开" : "多星球默认折叠");
				UpdateToggleLabel(w);
			}
		}

		private static string Signature(UIControlPanelWindow w, List<PlanetRow> planets)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			//IL_0025: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected I4, but got Unknown
			//IL_0049: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder(128);
			ControlPanelFilter filter = w.filter;
			stringBuilder.Append((int)filter.typeFilter).Append('|').Append(filter.astroFilter)
				.Append('|')
				.Append((int)filter.sortMethod)
				.Append('|')
				.Append(filter.stateFilter)
				.Append('|')
				.Append(filter.tagFilter ?? "")
				.Append('|')
				.Append(filter.searchFilter ?? "");
			if (filter.itemsFilter != null)
			{
				stringBuilder.Append('|');
				for (int i = 0; i < filter.itemsFilter.Length; i++)
				{
					stringBuilder.Append(filter.itemsFilter[i]).Append(',');
				}
			}
			stringBuilder.Append("|p:");
			for (int j = 0; j < planets.Count; j++)
			{
				stringBuilder.Append(planets[j].astroId).Append(',');
			}
			return stringBuilder.ToString();
		}

		public static void Apply(UIControlPanelWindow w, List<PlanetRow> planets, bool expand, string reason)
		{
			int num = LocalAstroId();
			int num2 = 0;
			for (int i = 0; i < planets.Count; i++)
			{
				PlanetRow planetRow = planets[i];
				bool isLocal = planetRow.astroId == num && num != 0;
				if (IsExpanded(w, planetRow.astroId, isLocal) != expand)
				{
					SetExpandState(w, planetRow.astroId, isLocal, expand);
					w.SetPlanetEntryExpand(planetRow.index, expand);
					num2++;
				}
			}
			CppLog.Debug($"{reason}: planets={planets.Count} changed={num2}");
		}

		private static int LocalAstroId()
		{
			PlanetData val = ((GameMain.data != null) ? GameMain.data.localPlanet : null);
			if (val == null)
			{
				return 0;
			}
			return val.astroId;
		}

		public static bool IsExpanded(UIControlPanelWindow w, int astroId, bool isLocal)
		{
			if (isLocal)
			{
				return !w.astroExpands.Contains(0);
			}
			return w.astroExpands.Contains(astroId);
		}

		private static void SetExpandState(UIControlPanelWindow w, int astroId, bool isLocal, bool expand)
		{
			if (isLocal)
			{
				if (expand)
				{
					w.astroExpands.Remove(0);
				}
				else
				{
					w.astroExpands.Add(0);
				}
			}
			else if (expand)
			{
				w.astroExpands.Add(astroId);
			}
			else
			{
				w.astroExpands.Remove(astroId);
			}
		}

		private static void EnsureTopButtons(UIControlPanelWindow w)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			if ((Object)(object)w == (Object)null)
			{
				return;
			}
			Transform val = ((Component)w).transform.Find("cpt-expand-toggle");
			if ((Object)(object)val != (Object)null)
			{
				_toggleButton = ((Component)val).GetComponent<UIButton>();
				UpdateToggleLabel(w);
				return;
			}
			UIButton val2 = NativeUi.MakeSmallTextButton(Lang.T("全部展开", "Expand All"), new Vector2(72f, 22f), 13, "cpt-expand-toggle");
			if (!((Object)(object)val2 == (Object)null))
			{
				((Component)val2).transform.SetParent(((Component)w).transform, false);
				NativeUi.AnchorTopRight((RectTransform)((Component)val2).transform, -43f, -25f, new Vector2(72f, 22f));
				val2.onClick += OnToggleClick;
				_toggleButton = val2;
				UpdateToggleLabel(w);
				CppLog.Debug("expand/collapse toggle button injected");
			}
		}

		private static bool AllRowsExpanded(UIControlPanelWindow w, List<PlanetRow> planets)
		{
			bool flag = planets.Count > 0;
			for (int i = 0; i < planets.Count; i++)
			{
				flag &= IsRowExpanded(w, planets[i]);
			}
			return flag;
		}

		private static bool IsRowExpanded(UIControlPanelWindow w, PlanetRow row)
		{
			int num = LocalAstroId();
			bool isLocal = row.astroId == num && num != 0;
			return IsExpanded(w, row.astroId, isLocal);
		}

		public static void UpdateToggleLabel(UIControlPanelWindow w)
		{
			if (!((Object)(object)_toggleButton == (Object)null) && !((Object)(object)w == (Object)null))
			{
				Text val = NativeUi.TextOf(_toggleButton);
				if (!((Object)(object)val == (Object)null))
				{
					bool flag = AllRowsExpanded(w, PlanetRows(w));
					val.text = (flag ? Lang.T("全部折叠", "Collapse All") : Lang.T("全部展开", "Expand All"));
				}
			}
		}

		private static void OnToggleClick(int obj)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				UIControlPanelWindow val = NativeUi.CurrentWindow();
				if (!((Object)(object)val == (Object)null) && ((ManualBehaviour)val).active)
				{
					List<PlanetRow> planets = PlanetRows(val);
					bool flag = AllRowsExpanded(val, planets);
					_appliedSignature = Signature(val, planets);
					Apply(val, planets, !flag, flag ? "全部折叠按钮" : "全部展开按钮");
					UpdateToggleLabel(val);
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("expand/collapse toggle failed: " + ex);
			}
		}

		public static void SetAll(bool expand)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				UIControlPanelWindow val = NativeUi.CurrentWindow();
				if (!((Object)(object)val == (Object)null) && ((ManualBehaviour)val).active)
				{
					List<PlanetRow> planets = PlanetRows(val);
					_appliedSignature = Signature(val, planets);
					Apply(val, planets, expand, expand ? "全部展开按钮" : "全部折叠按钮");
					UpdateToggleLabel(val);
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("expand/collapse all failed: " + ex);
			}
		}
	}
	internal static class HotkeyDiagnostics
	{
		private static float _nextLogAt;

		public static void Tick(UIControlPanelWindow window)
		{
			if ((Object)(object)window == (Object)null || !AnyHotkeyPressed() || Time.unscaledTime < _nextLogAt)
			{
				return;
			}
			_nextLogAt = Time.unscaledTime + 0.4f;
			try
			{
				if (!VFInput.inFullscreenGUI && !NativeUi.IsInputFocused(window))
				{
					CppLog.Debug("[HOTKEY] " + Describe(window));
				}
				else
				{
					CppLog.Info("[HOTKEY BLOCKED] " + Describe(window));
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("hotkey diagnostics failed: " + ex.Message);
			}
		}

		public static bool AnyHotkeyPressed()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			if (!Pressed(Cfg.CopyKey.Value) && !Pressed(Cfg.PasteKey.Value) && !Pressed(Cfg.ListUp.Value) && !Pressed(Cfg.ListDown.Value) && !Pressed((KeyCode)276) && !Pressed((KeyCode)275) && !Pressed((KeyCode)273))
			{
				return Pressed((KeyCode)274);
			}
			return true;
		}

		private static bool Pressed(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				return Input.GetKeyDown(key);
			}
			return false;
		}

		private static string Describe(UIControlPanelWindow w)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//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_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)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			UIGame val = (((Object)(object)UIRoot.instance != (Object)null) ? UIRoot.instance.uiGame : null);
			UIControlPanelFilterPanel filterPanel = w.filterPanel;
			UIControlPanelInspector currentInspector = w.currentInspector;
			UIControlPanelStationInspector val2 = (UIControlPanelStationInspector)(object)((currentInspector is UIControlPanelStationInspector) ? currentInspector : null);
			bool flag = (Object)(object)val2 != (Object)null && (Object)(object)val2.nameInput != (Object)null && val2.nameInput.isFocused;
			bool flag2 = (Object)(object)filterPanel != (Object)null && (Object)(object)filterPanel.tagFilterInput != (Object)null && filterPanel.tagFilterInput.isFocused;
			bool flag3 = (Object)(object)filterPanel != (Object)null && (Object)(object)filterPanel.searchFilterInput != (Object)null && filterPanel.searchFilterInput.isFocused;
			bool flag4 = (Object)(object)filterPanel != (Object)null && (Object)(object)filterPanel.astroFilterBox != (Object)null && (Object)(object)filterPanel.astroFilterBox.searchInput != (Object)null && filterPanel.astroFilterBox.searchInput.isFocused;
			GameObject val3 = null;
			EventSystem current = EventSystem.current;
			if ((Object)(object)current != (Object)null)
			{
				val3 = current.currentSelectedGameObject;
			}
			string text = "copy=" + ((object)Cfg.CopyKey.Value/*cast due to .constrained prefix*/).ToString() + " paste=" + ((object)Cfg.PasteKey.Value/*cast due to .constrained prefix*/).ToString() + " pageUp=" + ((object)Cfg.ListUp.Value/*cast due to .constrained prefix*/).ToString() + " pageDown=" + ((object)Cfg.ListDown.Value/*cast due to .constrained prefix*/).ToString();
			return "panel=" + ((ManualBehaviour)w).active + " fullscreen=" + VFInput.inFullscreenGUI + " paused=" + GameMain.isPaused + " dash=" + ((Object)(object)val != (Object)null && ((ManualBehaviour)val.dashboard).active) + " tree=" + ((Object)(object)val != (Object)null && ((ManualBehaviour)val.techTree).active) + " star=" + ((Object)(object)val != (Object)null && ((ManualBehaviour)val.starmap).active) + " dyson=" + ((Object)(object)val != (Object)null && ((ManualBehaviour)val.dysonEditor).active) + " focused=" + NativeUi.IsInputFocused(w) + " nameFocused=" + flag + " tagFocused=" + flag2 + " searchFocused=" + flag3 + " comboFocused=" + flag4 + " inspector=" + (((Object)(object)w.currentInspector != (Object)null) ? ((object)w.currentInspector).GetType().Name : "null") + " selection=" + w.selection.astroId + "/" + w.selection.objId + " esSel=" + (((Object)(object)val3 != (Object)null) ? ((Object)val3).name : "null") + " | " + text;
		}
	}
	internal class HotkeyDriver : MonoBehaviour
	{
		private void Update()
		{
			if (!Cfg.Enabled.Value || (Object)(object)UIRoot.instance == (Object)null || (Object)(object)UIRoot.instance.uiGame == (Object)null || GameMain.data == null)
			{
				return;
			}
			UIControlPanelWindow controlPanelWindow = UIRoot.instance.uiGame.controlPanelWindow;
			if ((Object)(object)controlPanelWindow == (Object)null || !((ManualBehaviour)controlPanelWindow).active)
			{
				return;
			}
			HotkeyDiagnostics.Tick(controlPanelWindow);
			if (VFInput.inFullscreenGUI)
			{
				return;
			}
			ConfigWatcher.Poll(controlPanelWindow);
			if (NativeUi.IsInputFocused(controlPanelWindow))
			{
				return;
			}
			try
			{
				HandleStationCopyPaste(controlPanelWindow);
				AstroListTweaks.HandleHotkeys(controlPanelWindow);
			}
			catch (Exception ex)
			{
				CppLog.Error("hotkey handling failed: " + ex);
			}
		}

		private void LateUpdate()
		{
			if (Cfg.Enabled.Value)
			{
				ItemFilterShortcuts.Tick();
			}
		}

		private void HandleStationCopyPaste(UIControlPanelWindow window)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			KeyCode value = Cfg.CopyKey.Value;
			KeyCode value2 = Cfg.PasteKey.Value;
			UIControlPanelInspector currentInspector = window.currentInspector;
			UIControlPanelStationInspector val = (UIControlPanelStationInspector)(object)((currentInspector is UIControlPanelStationInspector) ? currentInspector : null);
			bool flag = (Object)(object)val != (Object)null && val.station != null && val.station.id > 0;
			if ((int)value != 0 && value != value2 && Input.GetKeyDown(value))
			{
				if (flag)
				{
					StationCopyPaste.CopyFromSelection(window);
				}
				else
				{
					CppLog.Debug("copy key pressed without a station inspector selection");
				}
			}
			if ((int)value2 != 0 && Input.GetKeyDown(value2))
			{
				if (flag || StationCopyPaste.MultiCount > 0)
				{
					StationCopyPaste.Paste(window, VFInput.shift);
				}
				else
				{
					CppLog.Debug("paste key pressed without a station selection");
				}
			}
		}
	}
	public static class ItemFilterIntersect
	{
		private const string ToggleButtonName = "cpt-filter-mode";

		private static UIButton _toggleButton;

		public static void Apply(UIControlPanelWindow w)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected I4, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if (!Cfg.Enabled.Value || !Cfg.ItemFilterIntersect.Value)
			{
				return;
			}
			ControlPanelFilter filter = w.filter;
			if (((ControlPanelFilter)(ref filter)).itemsFilterCount < 2)
			{
				return;
			}
			List<ControlPanelTarget> list = WindowAccess.Results(w);
			if (list == null || list.Count == 0)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				ControlPanelTarget val = list[i];
				if ((int)val.entryType != 0)
				{
					bool flag = true;
					EControlPanelEntryType entryType = val.entryType;
					switch (entryType - 1)
					{
					case 0:
					case 1:
					case 2:
					case 3:
						num++;
						flag = StationContainsAll(val, filter.itemsFilter);
						break;
					case 4:
						num++;
						flag = DispenserContainsAll(val, filter.itemsFilter);
						break;
					case 5:
						flag = true;
						break;
					}
					if (!flag)
					{
						hashSet.Add(i);
					}
				}
			}
			for (int j = 0; j < list.Count; j++)
			{
				if ((int)list[j].entryType != 0)
				{
					continue;
				}
				bool flag2 = false;
				for (int k = j + 1; k < list.Count && (int)list[k].entryType != 0; k++)
				{
					if (!hashSet.Contains(k))
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					hashSet.Add(j);
				}
			}
			if (hashSet.Count != 0)
			{
				List<int> list2 = new List<int>(hashSet);
				list2.Sort();
				for (int num2 = list2.Count - 1; num2 >= 0; num2--)
				{
					WindowAccess.RemoveResultAt(w, list2[num2]);
				}
				WindowAccess.MarkEntryVisibleDirty(w);
				w.ReconnSelectionOnDetermineResults();
				CppLog.Debug($"item filter intersect: inspected={num} removed={hashSet.Count} remaining={list.Count}");
			}
		}

		private static bool StationContainsAll(ControlPanelTarget target, int[] items)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			StationComponent val = ResolveStation(target);
			if (val == null || val.storage == null)
			{
				return false;
			}
			foreach (int num in items)
			{
				bool flag = false;
				for (int j = 0; j < val.storage.Length; j++)
				{
					if (val.storage[j].itemId == num)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			return true;
		}

		private static bool DispenserContainsAll(ControlPanelTarget target, int[] items)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			PlanetFactory val = ResolveFactory(target.astroId);
			if (val == null)
			{
				return false;
			}
			int objId = target.objId;
			if (objId <= 0 || objId >= val.entityPool.Length)
			{
				return false;
			}
			int dispenserId = val.entityPool[objId].dispenserId;
			if (dispenserId <= 0 || dispenserId >= val.transport.dispenserPool.Length)
			{
				return false;
			}
			DispenserComponent val2 = val.transport.dispenserPool[dispenserId];
			if (val2 == null || val2.id != dispenserId)
			{
				return false;
			}
			if (items.Length == 1)
			{
				return val2.filter == items[0];
			}
			return false;
		}

		private static StationComponent ResolveStation(ControlPanelTarget target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			PlanetFactory val = ResolveFactory(target.astroId);
			if (val == null)
			{
				return null;
			}
			int objId = target.objId;
			if (objId <= 0 || objId >= val.entityPool.Length)
			{
				return null;
			}
			int stationId = val.entityPool[objId].stationId;
			if (stationId <= 0 || stationId >= val.transport.stationPool.Length)
			{
				return null;
			}
			StationComponent val2 = val.transport.stationPool[stationId];
			if (val2 == null || val2.id != stationId)
			{
				return null;
			}
			return val2;
		}

		private static PlanetFactory ResolveFactory(int astroId)
		{
			GameData data = GameMain.data;
			if (data == null || data.galaxy == null)
			{
				return null;
			}
			return data.galaxy.PlanetById(astroId)?.factory;
		}

		public static void EnsureToggleButton(UIControlPanelWindow window)
		{
			//IL_0044: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			if ((Object)(object)window == (Object)null)
			{
				return;
			}
			Transform val = ((Component)window).transform.Find("cpt-filter-mode");
			if ((Object)(object)val != (Object)null)
			{
				_toggleButton = ((Component)val).GetComponent<UIButton>();
				UpdateToggleLabel();
				return;
			}
			UIButton val2 = NativeUi.MakeSmallTextButton(Label(), new Vector2(86f, 22f), 13, "cpt-filter-mode");
			if (!((Object)(object)val2 == (Object)null))
			{
				((Component)val2).transform.SetParent(((Component)window).transform, false);
				NativeUi.AnchorTopRight((RectTransform)((Component)val2).transform, -121f, -25f, new Vector2(86f, 22f));
				val2.onClick += OnToggleClick;
				_toggleButton = val2;
				UpdateToggleLabel();
			}
		}

		private static string Label()
		{
			if (!Cfg.ItemFilterIntersect.Value)
			{
				return Lang.T("筛选:并集", "Filter: Union");
			}
			return Lang.T("筛选:交集", "Filter: Intersect");
		}

		private static void UpdateToggleLabel()
		{
			if (!((Object)(object)_toggleButton == (Object)null))
			{
				Text val = NativeUi.TextOf(_toggleButton);
				if ((Object)(object)val != (Object)null)
				{
					val.text = Label();
				}
			}
		}

		private static void OnToggleClick(int obj)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				Cfg.ItemFilterIntersect.Value = !Cfg.ItemFilterIntersect.Value;
				UIControlPanelWindow val = NativeUi.CurrentWindow();
				if ((Object)(object)val != (Object)null && ((ManualBehaviour)val).active)
				{
					val.DetermineFilterResults();
					val.DetermineEntryVisible();
				}
				UpdateToggleLabel();
				ConfigWatcher.Reset();
				if ((Object)(object)val != (Object)null)
				{
					ConfigWatcher.Poll(val);
				}
				CppLog.Info("item filter mode switched: " + Label());
			}
			catch (Exception ex)
			{
				CppLog.Error("filter mode toggle failed: " + ex);
			}
		}
	}
	public static class ItemFilterShortcuts
	{
		private static readonly Dictionary<UIControlPanelObjectEntry, Action<int>[]> Handlers = new Dictionary<UIControlPanelObjectEntry, Action<int>[]>();

		private static readonly FieldInfo GridStorageField = AccessTools.Field(typeof(UIStorageGrid), "storage");

		private static readonly FieldInfo GridMouseXField = AccessTools.Field(typeof(UIStorageGrid), "mouseOnX");

		private static readonly FieldInfo GridMouseYField = AccessTools.Field(typeof(UIStorageGrid), "mouseOnY");

		private static readonly FieldInfo ReplicatorRecipeArrayField = AccessTools.Field(typeof(UIReplicatorWindow), "recipeProtoArray");

		private static readonly FieldInfo ReplicatorMouseIndexField = AccessTools.Field(typeof(UIReplicatorWindow), "mouseRecipeIndex");

		private static int[] _lastSeenItems;

		private static bool _pendingAppend;

		private static int _pendingItem;

		private static int[] _pendingBase;

		public static void AttachStationEntry(UIControlPanelStationEntry entry)
		{
			if (!((Object)(object)entry == (Object)null) && !Handlers.ContainsKey((UIControlPanelObjectEntry)(object)entry))
			{
				UIButton[] buttons = (UIButton[])(object)new UIButton[5]
				{
					ButtonOf(entry.storageItem0),
					ButtonOf(entry.storageItem1),
					ButtonOf(entry.storageItem2),
					ButtonOf(entry.storageItem3),
					ButtonOf(entry.storageItem4)
				};
				Register((UIControlPanelObjectEntry)(object)entry, buttons, 5);
			}
		}

		public static void AttachMinerEntry(UIControlPanelAdvancedMinerEntry entry)
		{
			if (!((Object)(object)entry == (Object)null) && !Handlers.ContainsKey((UIControlPanelObjectEntry)(object)entry))
			{
				Register((UIControlPanelObjectEntry)(object)entry, (UIButton[])(object)new UIButton[1] { ButtonOf(entry.storageItem) }, 1);
			}
		}

		private static UIButton ButtonOf(UIControlPanelStorageItem item)
		{
			if (!((Object)(object)item != (Object)null))
			{
				return null;
			}
			return item.itemButton;
		}

		private static void Register(UIControlPanelObjectEntry entry, UIButton[] buttons, int slots)
		{
			Action<int>[] array = new Action<int>[slots];
			for (int i = 0; i < slots; i++)
			{
				int slot = i;
				array[i] = delegate
				{
					OnIconRightClick(entry, slot);
				};
				if ((Object)(object)buttons[i] != (Object)null)
				{
					buttons[i].onRightClick += array[i];
				}
			}
			Handlers[entry] = array;
		}

		public static void Detach(UIControlPanelObjectEntry entry)
		{
			if ((Object)(object)entry == (Object)null || !Handlers.TryGetValue(entry, out var value))
			{
				return;
			}
			UIButton[] array = null;
			UIControlPanelStationEntry val = (UIControlPanelStationEntry)(object)((entry is UIControlPanelStationEntry) ? entry : null);
			if (val != null)
			{
				array = (UIButton[])(object)new UIButton[5]
				{
					ButtonOf(val.storageItem0),
					ButtonOf(val.storageItem1),
					ButtonOf(val.storageItem2),
					ButtonOf(val.storageItem3),
					ButtonOf(val.storageItem4)
				};
			}
			else
			{
				UIControlPanelAdvancedMinerEntry val2 = (UIControlPanelAdvancedMinerEntry)(object)((entry is UIControlPanelAdvancedMinerEntry) ? entry : null);
				if (val2 != null)
				{
					array = (UIButton[])(object)new UIButton[1] { ButtonOf(val2.storageItem) };
				}
			}
			if (array != null)
			{
				for (int i = 0; i < array.Length && i < value.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null)
					{
						array[i].onRightClick -= value[i];
					}
				}
			}
			Handlers.Remove(entry);
		}

		private static void OnIconRightClick(UIControlPanelObjectEntry entry, int slot)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				int num = ItemIdOf(entry, slot);
				if (num <= 0)
				{
					return;
				}
				UIControlPanelWindow val = NativeUi.CurrentWindow();
				if (!((Object)(object)val == (Object)null) && ((ManualBehaviour)val).active)
				{
					if (VFInput.shift)
					{
						ScheduleAppend(num);
					}
					else
					{
						SetSingleItem(val, num, refresh: true);
					}
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("right-click item filter failed: " + ex);
			}
		}

		private static int ItemIdOf(UIControlPanelObjectEntry entry, int slot)
		{
			StationComponent val = null;
			UIControlPanelStationEntry val2 = (UIControlPanelStationEntry)(object)((entry is UIControlPanelStationEntry) ? entry : null);
			if (val2 != null)
			{
				val = val2.station;
			}
			else
			{
				UIControlPanelAdvancedMinerEntry val3 = (UIControlPanelAdvancedMinerEntry)(object)((entry is UIControlPanelAdvancedMinerEntry) ? entry : null);
				if (val3 != null)
				{
					val = val3.station;
				}
			}
			if (val == null || val.storage == null)
			{
				return 0;
			}
			if (slot < 0 || slot >= val.storage.Length)
			{
				return 0;
			}
			return val.storage[slot].itemId;
		}

		private static void ScheduleAppend(int itemId)
		{
			_pendingBase = CopyItems(_lastSeenItems);
			_pendingItem = itemId;
			_pendingAppend = true;
		}

		public static void Tick()
		{
			UIControlPanelWindow val = NativeUi.CurrentWindow();
			if (_pendingAppend)
			{
				_pendingAppend = false;
				if ((Object)(object)val != (Object)null && ((ManualBehaviour)val).active)
				{
					ApplyUnion(val, _pendingBase, _pendingItem);
				}
				_pendingBase = null;
			}
			_lastSeenItems = (((Object)(object)val != (Object)null && ((ManualBehaviour)val).active) ? CopyItems(val.filter.itemsFilter) : null);
		}

		public static void Reset()
		{
			_pendingAppend = false;
			_pendingBase = null;
			_lastSeenItems = null;
		}

		private static int[] CopyItems(int[] items)
		{
			if (items == null || items.Length == 0)
			{
				return null;
			}
			int[] array = new int[items.Length];
			Array.Copy(items, array, items.Length);
			return array;
		}

		private static void ApplyUnion(UIControlPanelWindow window, int[] baseItems, int itemId)
		{
			//IL_0034: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			List<int> list = ((baseItems != null) ? new List<int>(baseItems) : new List<int>());
			if (!list.Contains(itemId))
			{
				list.Add(itemId);
			}
			while (list.Count > 5)
			{
				list.RemoveAt(0);
			}
			ControlPanelFilter filter = window.filter;
			filter.itemsFilter = ((list.Count > 0) ? list.ToArray() : null);
			window.filter = filter;
			Refresh(window);
			_lastSeenItems = CopyItems(window.filter.itemsFilter);
			CppLog.Info("item filter appended: " + string.Join(",", list.ConvertAll((int i) => i.ToString()).ToArray()));
		}

		public static void SetSingleItem(UIControlPanelWindow window, int itemId, bool refresh)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)window == (Object)null || itemId <= 0)
			{
				return;
			}
			int[] itemsFilter = window.filter.itemsFilter;
			if (itemsFilter == null || itemsFilter.Length != 1 || itemsFilter[0] != itemId)
			{
				ControlPanelFilter filter = window.filter;
				filter.itemsFilter = new int[1] { itemId };
				window.filter = filter;
				if (refresh && ((ManualBehaviour)window).active)
				{
					Refresh(window);
					CppLog.Info("item filter set by right click: " + itemId);
				}
				_lastSeenItems = CopyItems(window.filter.itemsFilter);
			}
		}

		public static void SetSingleItemForOpen(UIControlPanelWindow window, int itemId)
		{
			SetSingleItem(window, itemId, refresh: false);
		}

		private static void Refresh(UIControlPanelWindow window)
		{
			try
			{
				UIControlPanelFilterPanel filterPanel = window.filterPanel;
				if ((Object)(object)filterPanel != (Object)null)
				{
					filterPanel.RefreshFilterUI();
				}
				window.DetermineFilterResults();
				window.DetermineEntryVisible();
			}
			catch (Exception ex)
			{
				CppLog.Error("filter refresh failed: " + ex);
			}
		}

		public static int ItemIdHintUnderMouse()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player val = ((GameMain.data != null) ? GameMain.data.mainPlayer : null);
				if (val != null && val.inhandItemId > 0)
				{
					return val.inhandItemId;
				}
				EventSystem current = EventSystem.current;
				if ((Object)(object)current == (Object)null)
				{
					return 0;
				}
				PointerEventData val2 = new PointerEventData(current);
				val2.position = Vector2.op_Implicit(Input.mousePosition);
				List<RaycastResult> list = new List<RaycastResult>();
				current.RaycastAll(val2, list);
				for (int i = 0; i < list.Count; i++)
				{
					RaycastResult val3 = list[i];
					GameObject gameObject = ((RaycastResult)(ref val3)).gameObject;
					if (!((Object)(object)gameObject == (Object)null))
					{
						UIButton componentInParent = gameObject.GetComponentInParent<UIButton>();
						if ((Object)(object)componentInParent != (Object)null && componentInParent.tips.itemId > 0)
						{
							return componentInParent.tips.itemId;
						}
						UIReplicatorWindow componentInParent2 = gameObject.GetComponentInParent<UIReplicatorWindow>();
						if ((Object)(object)componentInParent2 != (Object)null)
						{
							return ReplicatorItem(componentInParent2);
						}
						UIStorageGrid componentInParent3 = gameObject.GetComponentInParent<UIStorageGrid>();
						if ((Object)(object)componentInParent3 != (Object)null)
						{
							return StorageGridItem(componentInParent3);
						}
						UIProductEntry componentInParent4 = gameObject.GetComponentInParent<UIProductEntry>();
						if ((Object)(object)componentInParent4 != (Object)null)
						{
							return ProductItem(componentInParent4);
						}
					}
				}
			}
			catch (Exception ex)
			{
				CppLog.Debug("hover item lookup failed: " + ex.Message);
			}
			return 0;
		}

		private static int ReplicatorItem(UIReplicatorWindow replicator)
		{
			if (ReplicatorMouseIndexField == null || ReplicatorRecipeArrayField == null)
			{
				return 0;
			}
			int num = (int)ReplicatorMouseIndexField.GetValue(replicator);
			if (num < 0)
			{
				return 0;
			}
			if (!(ReplicatorRecipeArrayField.GetValue(replicator) is RecipeProto[] array) || num >= array.Length)
			{
				return 0;
			}
			RecipeProto val = array[num];
			if (val == null || val.Results == null || val.Results.Length == 0)
			{
				return 0;
			}
			return val.Results[0];
		}

		private static int StorageGridItem(UIStorageGrid grid)
		{
			if (GridStorageField == null || GridMouseXField == null || GridMouseYField == null)
			{
				return 0;
			}
			object? value = GridStorageField.GetValue(grid);
			StorageComponent val = (StorageComponent)((value is StorageComponent) ? value : null);
			if (val == null || val.grids == null)
			{
				return 0;
			}
			int num = (int)GridMouseXField.GetValue(grid);
			int num2 = (int)GridMouseYField.GetValue(grid);
			if (num < 0 || num2 < 0)
			{
				return 0;
			}
			int num3 = num + num2 * grid.colCount;
			if (num3 < 0 || num3 >= val.grids.Length)
			{
				return 0;
			}
			return val.grids[num3].itemId;
		}

		private static int ProductItem(UIProductEntry product)
		{
			if ((Object)(object)product.productionStatWindow == (Object)null || !product.productionStatWindow.isProductionTab)
			{
				return 0;
			}
			if (product.entryData == null)
			{
				return 0;
			}
			return product.entryData.itemId;
		}
	}
	[HarmonyPatch(typeof(UIGame), "OpenControlPanelWindow")]
	internal static class AutoFilterOnOpenPatch
	{
		[HarmonyPrefix]
		public static void Prefix(UIGame __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				UIControlPanelWindow controlPanelWindow = __instance.controlPanelWindow;
				if (!((Object)(object)controlPanelWindow == (Object)null) && !((ManualBehaviour)controlPanelWindow).active)
				{
					int num = ItemFilterShortcuts.ItemIdHintUnderMouse();
					if (num > 0)
					{
						ItemFilterShortcuts.SetSingleItemForOpen(controlPanelWindow, num);
					}
				}
			}
			catch (Exception ex)
			{
				CppLog.Error("auto item filter on open failed: " + ex);
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelStationEntry))]
	internal static class StationEntryFilterPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("_OnRegEvent")]
		public static void OnRegEvent(UIControlPanelStationEntry __instance)
		{
			try
			{
				ItemFilterShortcuts.AttachStationEntry(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("attach station right-click filter failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnUnregEvent")]
		public static void OnUnregEvent(UIControlPanelStationEntry __instance)
		{
			ItemFilterShortcuts.Detach((UIControlPanelObjectEntry)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(UIControlPanelAdvancedMinerEntry))]
	internal static class MinerEntryFilterPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("_OnRegEvent")]
		public static void OnRegEvent(UIControlPanelAdvancedMinerEntry __instance)
		{
			try
			{
				ItemFilterShortcuts.AttachMinerEntry(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("attach miner right-click filter failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnUnregEvent")]
		public static void OnUnregEvent(UIControlPanelAdvancedMinerEntry __instance)
		{
			ItemFilterShortcuts.Detach((UIControlPanelObjectEntry)(object)__instance);
		}
	}
	public static class Lang
	{
		public static bool? LanguageOverride;

		public static bool Chinese
		{
			get
			{
				if (LanguageOverride.HasValue)
				{
					return LanguageOverride.Value;
				}
				try
				{
					return Localization.isZHCN;
				}
				catch (Exception)
				{
					return true;
				}
			}
		}

		public static string T(string zh, string en)
		{
			if (!Chinese)
			{
				return en;
			}
			return zh;
		}
	}
	internal static class NativeUi
	{
		public static Font DinFont()
		{
			UIControlPanelWindow val = CurrentWindow();
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.FONT_DIN;
		}

		public static UIControlPanelWindow CurrentWindow()
		{
			UIGame val = (((Object)(object)UIRoot.instance != (Object)null) ? UIRoot.instance.uiGame : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.controlPanelWindow;
		}

		public static UIButton MakeSmallTextButton(string label, Vector2 size, int fontSize, string name)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			UIGame val = (((Object)(object)UIRoot.instance != (Object)null) ? UIRoot.instance.uiGame : null);
			UIButton val2 = (((Object)(object)val != (Object)null && (Object)(object)val.assemblerWindow != (Object)null) ? val.assemblerWindow.copyButton : null);
			if ((Object)(object)val2 == (Object)null)
			{
				CppLog.Warn("native button template (assemblerWindow.copyButton) is not available");
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject);
			((Object)obj).name = name;
			UIButton component = obj.GetComponent<UIButton>();
			Transform val3 = obj.transform.Find("Text");
			if ((Object)(object)val3 != (Object)null)
			{
				Localizer component2 = ((Component)val3).GetComponent<Localizer>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component2);
				}
				Text component3 = ((Component)val3).GetComponent<Text>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.text = label;
					component3.fontSize = fontSize;
					component3.supportRichText = true;
					component3.horizontalOverflow = (HorizontalWrapMode)1;
					component3.verticalOverflow = (VerticalWrapMode)1;
				}
			}
			if ((Object)(object)component != (Object)null)
			{
				component.tips.tipTitle = "";
				component.tips.tipText = "";
			}
			obj.SetActive(true);
			RectTransform val4 = (RectTransform)obj.transform;
			((Transform)val4).localScale = Vector3.one;
			val4.sizeDelta = size;
			return component;
		}

		public static int MeasureTipWidth(string text, int fontSize)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(text))
			{
				return 0;
			}
			Font val = null;
			try
			{
				UIControlPanelWindow val2 = CurrentWindow();
				if ((Object)(object)val2 != (Object)null)
				{
					val = val2.FONT_SAIRASB;
				}
			}
			catch (Exception)
			{
			}
			string[] array = text.Split('\n');
			float num = 0f;
			TextGenerator val3 = new TextGenerator();
			for (int i = 0; i < array.Length; i++)
			{
				float num2 = 0f;
				if ((Object)(object)val != (Object)null)
				{
					TextGenerationSettings val4 = new TextGenerationSettings
					{
						font = val,
						fontSize = fontSize,
						scaleFactor = 1f,
						lineSpacing = 1f,
						richText = false,
						horizontalOverflow = (HorizontalWrapMode)1,
						verticalOverflow = (VerticalWrapMode)1,
						textAnchor = (TextAnchor)0,
						generationExtents = new Vector2(0f, 0f)
					};
					num2 = val3.GetPreferredWidth(array[i], val4);
				}
				if (num2 <= 0f)
				{
					num2 = array[i].Length * fontSize;
				}
				if (num2 > num)
				{
					num = num2;
				}
			}
			return Mathf.CeilToInt(num * 1.15f) + 30;
		}

		public static void AnchorTopRight(RectTransform rt, float rightOffset, float topOffset, Vector2 size)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = new Vector2(1f, 1f);
			rt.anchorMax = new Vector2(1f, 1f);
			rt.pivot = new Vector2(1f, 0.5f);
			rt.anchoredPosition = new Vector2(rightOffset, topOffset);
			rt.sizeDelta = size;
		}

		public static Text TextOf(UIButton btn)
		{
			if ((Object)(object)btn == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)btn).transform.Find("Text");
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<Text>();
		}

		public static bool IsInputFocused(UIControlPanelWindow w)
		{
			EventSystem current = EventSystem.current;
			if ((Object)(object)current != (Object)null)
			{
				GameObject currentSelectedGameObject = current.currentSelectedGameObject;
				if ((Object)(object)currentSelectedGameObject != (Object)null)
				{
					InputField component = currentSelectedGameObject.GetComponent<InputField>();
					if ((Object)(object)component != (Object)null && component.isFocused)
					{
						return true;
					}
					UIInputField component2 = currentSelectedGameObject.GetComponent<UIInputField>();
					if ((Object)(object)component2 != (Object)null && (Object)(object)component2.inputField != (Object)null && component2.inputField.isFocused)
					{
						return true;
					}
				}
			}
			UIControlPanelFilterPanel val = (((Object)(object)w != (Object)null) ? w.filterPanel : null);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val.astroFilterBox != (Object)null && (Object)(object)val.astroFilterBox.searchInput != (Object)null && val.astroFilterBox.searchInput.isFocused)
				{
					return true;
				}
				if ((Object)(object)val.tagFilterInput != (Object)null && val.tagFilterInput.isFocused)
				{
					return true;
				}
				if ((Object)(object)val.searchFilterInput != (Object)null && val.searchFilterInput.isFocused)
				{
					return true;
				}
			}
			UIControlPanelStationInspector val2 = (UIControlPanelStationInspector)(((Object)(object)w != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.nameInput != (Object)null && val2.nameInput.isFocused)
			{
				return true;
			}
			return false;
		}

		public static bool MouseOverStorageSlot()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			EventSystem current = EventSystem.current;
			if ((Object)(object)current == (Object)null)
			{
				return false;
			}
			PointerEventData val = new PointerEventData(current);
			val.position = Vector2.op_Implicit(Input.mousePosition);
			List<RaycastResult> list = new List<RaycastResult>();
			current.RaycastAll(val, list);
			for (int i = 0; i < list.Count; i++)
			{
				RaycastResult val2 = list[i];
				GameObject gameObject = ((RaycastResult)(ref val2)).gameObject;
				if (!((Object)(object)gameObject == (Object)null))
				{
					if ((Object)(object)gameObject.GetComponentInParent<UIControlPanelStationStorage>() != (Object)null)
					{
						return true;
					}
					if ((Object)(object)gameObject.GetComponentInParent<UIStationStorage>() != (Object)null)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void EnableRichText(UIComboBox box)
		{
			if (!((Object)(object)box == (Object)null))
			{
				if ((Object)(object)box.mainLabel != (Object)null)
				{
					box.mainLabel.supportRichText = true;
				}
				if ((Object)(object)box.emptyText != (Object)null)
				{
					box.emptyText.supportRichText = true;
				}
				if ((Object)(object)((UIListable)box).entryPrefab != (Object)null && (Object)(object)((UIListable)box).entryPrefab.text != (Object)null)
				{
					((UIListable)box).entryPrefab.text.supportRichText = true;
				}
			}
		}
	}
	[BepInPlugin("com.dsp.controlpanelplus", "ControlPanelPlus", "1.0.0")]
	public class ControlPanelPlusPlugin : BaseUnityPlugin
	{
		private HotkeyDriver _driver;

		public static ControlPanelPlusPlugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		internal static Harmony Harmony { get; private set; }

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			CppLog.Verbose = false;
			Cfg.Bind(((BaseUnityPlugin)this).Config);
			Harmony = new Harmony("com.dsp.controlpanelplus");
			Harmony.PatchAll(typeof(ControlPanelPlusPlugin).Assembly);
			_driver = ((Component)this).gameObject.AddComponent<HotkeyDriver>();
			CppLog.Info("ControlPanelPlus 1.0.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Harmony = null;
		}
	}
	public static class PluginPresence
	{
		public const string CheatEnablerGuid = "org.soardev.cheatenabler";

		public const string UiTweaksGuid = "starfi5h.plugin.UITweaks";

		private static bool? _cheatEnabler;

		private static bool? _uiTweaks;

		public static bool? CheatEnablerPresenceOverride;

		public static bool? UiTweaksPresenceOverride;

		public static bool CheatEnablerInstalled
		{
			get
			{
				if (CheatEnablerPresenceOverride.HasValue)
				{
					return CheatEnablerPresenceOverride.Value;
				}
				if (!_cheatEnabler.HasValue)
				{
					_cheatEnabler = Has("org.soardev.cheatenabler");
				}
				return _cheatEnabler.Value;
			}
		}

		public static bool UiTweaksInstalled
		{
			get
			{
				if (UiTweaksPresenceOverride.HasValue)
				{
					return UiTweaksPresenceOverride.Value;
				}
				if (!_uiTweaks.HasValue)
				{
					_uiTweaks = Has("starfi5h.plugin.UITweaks");
				}
				return _uiTweaks.Value;
			}
		}

		private static bool Has(string guid)
		{
			try
			{
				return Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey(guid);
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
	public static class RemoteItemAccess
	{
		private static int _scope;

		public static bool FeatureEnabled
		{
			get
			{
				if (Cfg.Enabled.Value && Cfg.AllowRemoteItemTransfer.Value)
				{
					return !PluginPresence.CheatEnablerInstalled;
				}
				return false;
			}
		}

		public static bool ForceLocal => _scope > 0;

		public static void BeginScope()
		{
			if (FeatureEnabled)
			{
				_scope++;
			}
		}

		public static void EndScope()
		{
			if (_scope > 0)
			{
				_scope--;
			}
		}

		public static void ResetScope()
		{
			_scope = 0;
		}
	}
	[HarmonyPatch(typeof(UIControlPanelStationStorage), "OnItemIconMouseDown")]
	internal static class StationStorageMouseDownScopePatch
	{
		[HarmonyPrefix]
		public static void Prefix()
		{
			RemoteItemAccess.BeginScope();
		}

		[HarmonyFinalizer]
		public static void Finalizer()
		{
			RemoteItemAccess.EndScope();
		}
	}
	[HarmonyPatch(typeof(UIControlPanelStationStorage), "OnTakeBackButtonClick")]
	internal static class StationStorageTakeBackScopePatch
	{
		[HarmonyPrefix]
		public static void Prefix()
		{
			RemoteItemAccess.BeginScope();
		}

		[HarmonyFinalizer]
		public static void Finalizer()
		{
			RemoteItemAccess.EndScope();
		}
	}
	[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), "OnProductIconClick")]
	internal static class VeinCollectorProductScopePatch
	{
		[HarmonyPrefix]
		public static void Prefix()
		{
			RemoteItemAccess.BeginScope();
		}

		[HarmonyFinalizer]
		public static void Finalizer()
		{
			RemoteItemAccess.EndScope();
		}
	}
	[HarmonyPatch(typeof(UIControlPanelStationStorage), "OnTakeBackButtonClick")]
	internal static class StationStorageRemoteClearDestroyPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UIControlPanelStationStorage __instance)
		{
			if (!Cfg.DestroyReplacedItems.Value)
			{
				return true;
			}
			if (!Cfg.Enabled.Value || !Cfg.AllowRemoteItemTransfer.Value)
			{
				return true;
			}
			if (PluginPresence.CheatEnablerInstalled)
			{
				return true;
			}
			if ((Object)(object)__instance == (Object)null || !__instance.isStationDataValid)
			{
				return true;
			}
			if (__instance.index < 0 || __instance.index >= __instance.station.storage.Length)
			{
				return true;
			}
			PlanetData localPlanet = GameMain.localPlanet;
			if (localPlanet != null && __instance.factory != null && __instance.factory.planet.id == localPlanet.id)
			{
				return true;
			}
			if (__instance.station.storage[__instance.index].count <= 0)
			{
				return true;
			}
			try
			{
				__instance.factory.transport.SetStationStorage(__instance.station.id, __instance.index, 0, 0, (ELogisticStorage)0, (ELogisticStorage)0, (Player)null);
				CppLog.Debug("remote clear destroyed the items on purpose");
			}
			catch (Exception ex)
			{
				CppLog.Error("remote clear destroy failed: " + ex);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(UIControlPanelStationStorage), "get_isLocal")]
	internal static class StationStorageIsLocalPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref bool __result)
		{
			if (RemoteItemAccess.ForceLocal)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), "get_isLocal")]
	internal static class VeinCollectorIsLocalPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref bool __result)
		{
			if (RemoteItemAccess.ForceLocal)
			{
				__result = true;
			}
		}
	}
	public static class StarmapLocate
	{
		public const string ButtonName = "cpt-locate-btn";

		public static void GetTooltip(out string title, out string text)
		{
			title = Lang.T("定位", "Locate");
			text = (Lang.Chinese ? "左键:打开星图并保留总控面板\n右键:打开星图并关闭总控面板\nShift+右键:关闭总控面板并点亮导航线" : "Left click: open the star map and keep the panel\nRight click: open the star map and close the panel\nShift+right click: close the panel and point the navigation line");
		}

		public static void EnsureButton(UIControlPanelPlanetEntry entry)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)entry == (Object)null || (Object)(object)entry.navigationButton == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)entry.navigationButton).transform.parent;
			if (!((Object)(object)parent == (Object)null) && !((Object)(object)parent.Find("cpt-locate-btn") != (Object)null))
			{
				float num = (Lang.Chinese ? 36f : 52f);
				UIButton val = NativeUi.MakeSmallTextButton(Lang.T("定位", "Locate"), new Vector2(num, 22f), 12, "cpt-locate-btn");
				if (!((Object)(object)val == (Object)null))
				{
					RectTransform val2 = (RectTransform)((Component)entry.navigationButton).transform;
					RectTransform val3 = (RectTransform)((Component)val).transform;
					((Transform)val3).SetParent(parent, false);
					val3.anchorMin = new Vector2(0f, 0.5f);
					val3.anchorMax = new Vector2(0f, 0.5f);
					val3.pivot = new Vector2(1f, 0.5f);
					val3.anchoredPosition = new Vector2(val2.anchoredPosition.x - 6f, 0f);
					val3.sizeDelta = new Vector2(num, 22f);
					((Transform)val3).localScale = Vector3.one;
					GetTooltip(out var title, out var text);
					val.tips.tipTitle = title;
					val.tips.tipText = text;
					val.tips.corner = 3;
					val.tips.offset = new Vector2(18f, -20f);
					val.tips.delay = 0.7f;
					val.tips.width = NativeUi.MeasureTipWidth(text, 16);
					LocateButtonHandler locateButtonHandler = ((Component)val).gameObject.AddComponent<LocateButtonHandler>();
					locateButtonHandler.entry = entry;
					val.onClick += locateButtonHandler.OnButtonClick;
					val.onRightClick += locateButtonHandler.OnButtonRightClick;
					CppLog.Debug("locate button injected into planet entry banner");
				}
			}
		}

		public static void RefreshVisibility(UIControlPanelPlanetEntry entry)
		{
			if ((Object)(object)entry == (Object)null)
			{
				return;
			}
			Transform val = (((Object)(object)entry.navigationButton != (Object)null) ? ((Component)entry.navigationButton).transform.parent : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform val2 = val.Find("cpt-locate-btn");
			if (!((Object)(object)val2 == (Object)null))
			{
				bool flag = Cfg.EnableStarmapButton.Value && ((UIControlPanelObjectEntry)entry).isTargetDataValid;
				if (((Component)val2).gameObject.activeSelf != flag)
				{
					((Component)val2).gameObject.SetActive(flag);
				}
			}
		}

		public static void Locate(UIControlPanelPlanetEntry entry, bool closePanel, bool linkNavigation)
		{
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)entry == (Object)null || !((UIControlPanelObjectEntry)entry).isTargetDataValid || !Cfg.Enabled.Value || !Cfg.EnableStarmapButton.Value)
			{
				return;
			}
			PlanetData planet = entry.planet;
			try
			{
				UIGame uiGame = UIRoot.instance.uiGame;
				UIStarmap starmap = uiGame.starmap;
				if ((Object)(object)starmap == (Object)null)
				{
					return;
				}
				Player mainPlayer = GameMain.mainPlayer;
				mainPlayer.combatState = false;
				uiGame.ShutPlayerInventory();
				if (closePanel)
				{
					uiGame.ShutAllFunctionWindow();
				}
				uiGame.ShutTechTree();
				uiGame.ShutDashboard();
				uiGame.ShutDysonEditorImmediately();
				uiGame.CloseEnemyBriefInfo();
				if ((Object)(object)uiGame.dashboard != (Object)null && ((ManualBehaviour)uiGame.dashboard).active)
				{
					CppLog.Warn("dashboard is still active after ShutDashboard; forcing it closed");
					try
					{
						((ManualBehaviour)uiGame.dashboard)._Close();
					}
					catch (Exception ex)
					{
						CppLog.Error("forced dashboard close failed: " + ex);
					}
				}
				if (!((ManualBehaviour)starmap).active)
				{
					uiGame.BeforeEnterFullScreenUI();
					starmap.FadeIn();
				}
				starmap.SetViewStar(planet.star, false);
				starmap.focusPlanet = null;
				starmap.focusStar = null;
				starmap.focusHive = null;
				starmap.focusEnemyId = 0;
				double num = (double)planet.realRadius * 0.00025 * 6.0;
				starmap.screenCameraController.SetViewTarget(planet, (StarData)null, (EnemyDFHiveSystem)null, (Player)null, VectorLF3.zero, num, num, true, false);
				if (linkNavigation && mainPlayer.navigation != null)
				{
					mainPlayer.navigation.indicatorAstroId = planet.astroId;
				}
				UIStarmapPlanet val = FindPlanetUi(starmap, planet);
				if ((Object)(object)val != (Object)null)
				{
					starmap.focusPlanet = val;
					starmap.focusStar = null;
					starmap.focusHive = null;
					starmap.focusEnemyId = 0;
					starmap.OnFocusTargetChange();
				}
				CppLog.Debug($"locate planet {planet.displayName} (astroId={planet.astroId}) selected={(Object)(object)val != (Object)null}");
			}
			catch (Exception ex2)
			{
				CppLog.Error("starmap locate failed: " + ex2);
			}
		}

		private static UIStarmapPlanet FindPlanetUi(UIStarmap starmap, PlanetData planet)
		{
			if (starmap.planetUIs == null)
			{
				return null;
			}
			for (int i = 0; i < starmap.planetUIs.Length; i++)
			{
				UIStarmapPlanet val = starmap.planetUIs[i];
				if ((Object)(object)val != (Object)null && val.planet == planet)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal class LocateButtonHandler : MonoBehaviour
	{
		public UIControlPanelPlanetEntry entry;

		public void OnButtonClick(int obj)
		{
			StarmapLocate.Locate(entry, closePanel: false, linkNavigation: false);
		}

		public void OnButtonRightClick(int obj)
		{
			bool linkNavigation = VFInput.shift || Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			StarmapLocate.Locate(entry, closePanel: true, linkNavigation);
		}
	}
	[HarmonyPatch(typeof(UIControlPanelPlanetEntry))]
	internal static class PlanetEntryPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("_OnRegEvent")]
		public static void OnRegEvent(UIControlPanelPlanetEntry __instance)
		{
			if (!Cfg.Enabled.Value || !Cfg.EnableStarmapButton.Value)
			{
				return;
			}
			try
			{
				StarmapLocate.EnsureButton(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("planet entry button injection failed: " + ex);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnUpdate")]
		public static void OnUpdate(UIControlPanelPlanetEntry __instance)
		{
			if (!Cfg.Enabled.Value)
			{
				return;
			}
			try
			{
				StarmapLocate.RefreshVisibility(__instance);
			}
			catch (Exception ex)
			{
				CppLog.Error("planet entry button refresh failed: " + ex);
			}
		}
	}
	public sealed class SlotSnapshot
	{
		public int itemId;

		public int max;

		public ELogisticStorage localLogic;

		public ELogisticStorage remoteLogic;
	}
	public sealed class StationSnapshot
	{
		public bool isStellar;

		public bool isCollector;

		public bool isVeinCollector;

		public int planetId;

		public string name = "";

		public SlotSnapshot[] slots;

		public bool droneAutoReplenish;

		public bool shipAutoReplenish;

		public long workEnergyPerTick;

		public double tripRangeDrones;

		public double tripRangeShips;

		public double warpEnableDist;

		public int deliveryDrones;

		public int deliveryShips;

		public int pilerCount;

		public bool includeOrbitCollector;

		public bool warperNecessary;

		public byte[] priorityIndex;

		public byte[] priorityLockTick;

		public ERemoteRoutePriority routePriority;

		public long remoteGroupMask;

		public int[] p2pPartners;

		public bool IsMiner
		{
			get
			{
				if (!isCollector)
				{
					return isVeinCollector;
				}
				return true;
			}
		}

		public string Summary()
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			if (slots != null)
			{
				for (int i = 0; i < slots.Length; i++)
				{
					if (slots[i].itemId > 0)
					{
						num++;
					}
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(isCollector ? Lang.T("轨道采集器", "Orbital Collector") : (isVeinCollector ? Lang.T("大型采矿机", "Vein Collector") : (isStellar ? Lang.T("星际物流站", "Interstellar Station") : Lang.T("行星内物流站", "Planetary Station"))));
			stringBuilder.Append(Lang.T(" 槽位=", " slots=")).Append(num).Append(Lang.T(" 名称=\"", " name=\""))
				.Append(name)
				.Append('"')
				.Append(Lang.T(" 航路优先级=", " routePriority="))
				.Append(routePriority)
				.Append(Lang.T(" 分组=", " group="))
				.Append(remoteGroupMask);
			if (p2pPartners != null && p2pPartners.Length != 0)
			{
				stringBuilder.Append(Lang.T(" P2P伙伴=", " p2pPartners=")).Append(p2pPartners.Length);
			}
			return stringBuilder.ToString();
		}
	}
	internal sealed class PasteResult
	{
		public int slotsApplied;

		public int slotsSkipped;

		public int slotsConflict;

		public int slotsLost;

		public bool settings;

		public bool priority;

		public int routesAdded;

		public string skippedReason = "";
	}
	public static class StationCopyPaste
	{
		private static StationSnapshot _clipboard;

		private static readonly HashSet<long> Multi = new HashSet<long>();

		private static string _filterSignature;

		public static bool HasClipboard => _clipboard != null;

		public static StationSnapshot Clipboard => _clipboard;

		public static int MultiCount => Multi.Count;

		public static void ClearClipboard()
		{
			_clipboard = null;
		}

		public static bool ToggleMultiSelect(ControlPanelTarget target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			if (target.astroId == 0 || target.objId == 0)
			{
				return false;
			}
			StationComponent val = ResolveStation(target.astroId, target.objId);
			if (val == null || val.id <= 0)
			{
				return false;
			}
			long item = Key(target.astroId, target.objId);
			if (!Multi.Remove(item))
			{
				Multi.Add(item);
				return true;
			}
			return true;
		}

		private static long Key(int astroId, int objId)
		{
			return ((long)astroId << 32) | (uint)objId;
		}

		private static int KeyAstro(long key)
		{
			return (int)(key >> 32);
		}

		private static int KeyObj(long key)
		{
			return (int)(key & 0xFFFFFFFFu);
		}

		public static bool IsMultiSelected(ControlPanelTarget target)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (Multi.Count == 0 || target.astroId == 0 || target.objId == 0)
			{
				return false;
			}
			return Multi.Contains(Key(target.astroId, target.objId));
		}

		private static void Tip(string message)
		{
			UIRealtimeTip.Popup(message, false, 0);
		}

		public static void OnWindowOpened()
		{
			Multi.Clear();
			_filterSignature = null;
		}

		public static void OnWindowClosed()
		{
			Multi.Clear();
			_filterSignature = null;
		}

		public static void OnFilterResultsDetermined(UIControlPanelWindow w)
		{
			string text = FilterSignature(w);
			if (text != _filterSignature)
			{
				if (_filterSignature != null && Multi.Count > 0)
				{
					CppLog.Debug("filter changed, multi-select cleared");
				}
				_filterSignature = text;
				Multi.Clear();
			}
		}

		private static string FilterSignature(UIControlPanelWindow w)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected I4, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected I4, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			ControlPanelFilter filter = w.filter;
			StringBuilder stringBuilder = new StringBuilder(64);
			stringBuilder.Append((int)filter.typeFilter).Append('|').Append(filter.astroFilter)
				.Append('|')
				.Append((int)filter.sortMethod)
				.Append('|')
				.Append(filter.stateFilter)
				.Append('|')
				.Append(filter.tagFilter ?? "")
				.Append('|')
				.Append(filter.searchFilter ?? "");
			if (filter.itemsFilter != null)
			{
				for (int i = 0; i < filter.itemsFilter.Length; i++)
				{
					stringBuilder.Append(filter.itemsFilter[i]).Append(',');
				}
			}
			return stringBuilder.ToString();
		}

		public static bool ToggleMultiSelect(UIControlPanelObjectEntry entry)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might