Decompiled source of Stellogistics v2.0.1

Stellogistics.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Stellogistics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Shows combined Interplanetary Logistics (ILS) imports and exports per planet and star system on the Starmap.")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyInformationalVersion("2.0.1+6c5172b636f7a533ad8af5edcb994e655db816c8")]
[assembly: AssemblyProduct("Stellogistics")]
[assembly: AssemblyTitle("Stellogistics")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.1.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 Stellogistics
{
	public static class LogisticsAggregator
	{
		private struct SupplyAvailability
		{
			public int HealthySupplierPlanetCount;

			public int SingleSupplierPlanetId;

			public int SingleSupplierStarId;

			public bool MultipleStarSystems;
		}

		private const double OneLightYearMeters = 2390000.0;

		private const int WarperItemId = 1210;

		public static LogisticsSummary AggregatePlanet(PlanetData planet, StellogisticsConfig config)
		{
			int galaxySeed = ((GameMain.galaxy != null) ? GameMain.galaxy.seed : 0);
			int num = ((planet != null) ? planet.astroId : 0);
			EItemCategoryFilter filterForAstro = config.GetFilterForAstro(galaxySeed, num);
			LogisticsSummary logisticsSummary = new LogisticsSummary
			{
				IsStarSystem = false,
				TargetAstroId = num,
				GalaxySeed = galaxySeed,
				ActiveCategoryFilter = filterForAstro,
				TargetName = ((planet != null) ? planet.displayName : "Unknown Planet")
			};
			if (planet == null || GameMain.data == null)
			{
				return logisticsSummary;
			}
			Dictionary<int, CombinedLogisticsItem> exportsByItem = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, CombinedLogisticsItem> importsByItem = new Dictionary<int, CombinedLogisticsItem>();
			StationComponent[] gStationPool = GameMain.data.galacticTransport?.stationPool;
			int starId = ((planet.star != null) ? planet.star.id : (planet.id / 100));
			AggregatePlanetStations(planet, starId, config.IncludeOrbitalCollectors.Value, EStarFilterMode.AllRemoteSlots, gStationPool, exportsByItem, importsByItem, null, null, ref logisticsSummary.TotalIlsCount, ref logisticsSummary.TotalCollectorCount, ref logisticsSummary.TotalWarperCount, ref logisticsSummary.TotalIdleShips, ref logisticsSummary.TotalWorkShips);
			logisticsSummary.ColonizedPlanetCount = (logisticsSummary.HasAnyStations ? 1 : 0);
			LinkHubItems(exportsByItem, importsByItem);
			FinalizeSummary(logisticsSummary, exportsByItem, importsByItem, config, planet.id, 0);
			string arg = ((logisticsSummary.TotalCollectorCount > 0) ? $", {logisticsSummary.TotalCollectorCount} OC" : "");
			logisticsSummary.TargetSubtitle = $"Planet • {logisticsSummary.TotalIlsCount} ILS{arg}";
			return logisticsSummary;
		}

		public static LogisticsSummary AggregateStar(StarData star, StellogisticsConfig config)
		{
			int galaxySeed = ((GameMain.galaxy != null) ? GameMain.galaxy.seed : 0);
			int num = ((star != null) ? star.astroId : 0);
			EItemCategoryFilter filterForAstro = config.GetFilterForAstro(galaxySeed, num);
			LogisticsSummary logisticsSummary = new LogisticsSummary
			{
				IsStarSystem = true,
				TargetAstroId = num,
				GalaxySeed = galaxySeed,
				ActiveCategoryFilter = filterForAstro,
				TargetName = ((star != null) ? (star.displayName + " System") : "Unknown System")
			};
			if (star == null || star.planets == null || GameMain.data == null)
			{
				return logisticsSummary;
			}
			Dictionary<int, CombinedLogisticsItem> exportsByItem = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, CombinedLogisticsItem> importsByItem = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, HashSet<int>> exportPlanetsByItem = new Dictionary<int, HashSet<int>>();
			Dictionary<int, HashSet<int>> importPlanetsByItem = new Dictionary<int, HashSet<int>>();
			StationComponent[] gStationPool = GameMain.data.galacticTransport?.stationPool;
			EStarFilterMode value = config.StarSystemFilterMode.Value;
			bool value2 = config.IncludeOrbitalCollectors.Value;
			for (int i = 0; i < star.planets.Length; i++)
			{
				PlanetData val = star.planets[i];
				if (val != null)
				{
					int totalIlsCount = logisticsSummary.TotalIlsCount;
					int totalCollectorCount = logisticsSummary.TotalCollectorCount;
					AggregatePlanetStations(val, star.id, value2, value, gStationPool, exportsByItem, importsByItem, exportPlanetsByItem, importPlanetsByItem, ref logisticsSummary.TotalIlsCount, ref logisticsSummary.TotalCollectorCount, ref logisticsSummary.TotalWarperCount, ref logisticsSummary.TotalIdleShips, ref logisticsSummary.TotalWorkShips);
					if (logisticsSummary.TotalIlsCount > totalIlsCount || logisticsSummary.TotalCollectorCount > totalCollectorCount)
					{
						logisticsSummary.ColonizedPlanetCount++;
					}
				}
			}
			switch (value)
			{
			case EStarFilterMode.InterstellarSmart:
				ApplyInterstellarSmartFilter(exportsByItem, importsByItem);
				break;
			case EStarFilterMode.NetOutIntraSystem:
				ApplyNetOutIntraSystemFilter(exportsByItem, importsByItem);
				break;
			}
			LinkHubItems(exportsByItem, importsByItem);
			FinalizeSummary(logisticsSummary, exportsByItem, importsByItem, config, 0, star.id);
			string text = value switch
			{
				EStarFilterMode.InterstellarSmart => "Interstellar", 
				EStarFilterMode.NetOutIntraSystem => "Netted", 
				_ => "All Remote", 
			};
			string text2 = ((logisticsSummary.TotalCollectorCount > 0) ? $" +{logisticsSummary.TotalCollectorCount} OC" : "");
			logisticsSummary.TargetSubtitle = $"{text} • {logisticsSummary.ColonizedPlanetCount}/{star.planets.Length} Planets • {logisticsSummary.TotalIlsCount} ILS{text2}";
			return logisticsSummary;
		}

		private static void AggregatePlanetStations(PlanetData planet, int starId, bool includeCollectors, EStarFilterMode filterMode, StationComponent[] gStationPool, Dictionary<int, CombinedLogisticsItem> exportsByItem, Dictionary<int, CombinedLogisticsItem> importsByItem, Dictionary<int, HashSet<int>> exportPlanetsByItem, Dictionary<int, HashSet<int>> importPlanetsByItem, ref int totalIlsCount, ref int totalCollectorCount, ref int totalWarperCount, ref int totalIdleShips, ref int totalWorkShips)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Invalid comparison between Unknown and I4
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Invalid comparison between Unknown and I4
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Invalid comparison between Unknown and I4
			StationComponent[] array = planet.factory?.transport?.stationPool;
			int num = ((planet.factory?.transport != null) ? planet.factory.transport.stationCursor : 0);
			if (array == null || num <= 0)
			{
				return;
			}
			for (int i = 1; i < num; i++)
			{
				StationComponent val = array[i];
				if (val == null || val.id != i || !val.isStellar)
				{
					continue;
				}
				if (val.isCollector)
				{
					if (!includeCollectors)
					{
						continue;
					}
					totalCollectorCount++;
				}
				else
				{
					totalIlsCount++;
					totalWarperCount += val.warperCount;
					totalIdleShips += val.idleShipCount;
					totalWorkShips += val.workShipCount;
				}
				StationStore[] storage = val.storage;
				if (storage == null)
				{
					continue;
				}
				bool flag = val.isCollector || val.tripRangeShips >= 2390000.0;
				bool flag2 = !val.isCollector && val.idleShipCount + val.workShipCount > 0 && flag && (!val.warperNecessary || val.warperCount > 0 || val.warperFree || HasWarperSlot(storage));
				for (int j = 0; j < storage.Length; j++)
				{
					StationStore val2 = storage[j];
					if (val2.itemId <= 0 || (int)val2.remoteLogic == 0)
					{
						continue;
					}
					bool hasExternalPair = false;
					bool hasInternalPair = false;
					if (filterMode == EStarFilterMode.InterstellarSmart && gStationPool != null)
					{
						InspectSlotRemotePairs(val, j, starId, gStationPool, out hasExternalPair, out hasInternalPair);
						if ((hasInternalPair && !hasExternalPair && !flag2) || ((int)val2.remoteLogic == 2 && !flag && !hasExternalPair))
						{
							continue;
						}
					}
					if ((int)val2.remoteLogic == 1)
					{
						AccumulateSlot(exportsByItem, exportPlanetsByItem, planet.id, val2, val.isCollector, hasExternalPair, flag2);
					}
					else if ((int)val2.remoteLogic == 2)
					{
						AccumulateSlot(importsByItem, importPlanetsByItem, planet.id, val2, val.isCollector, hasExternalPair, flag2);
					}
				}
			}
		}

		private static bool HasWarperSlot(StationStore[] storage)
		{
			for (int i = 0; i < storage.Length; i++)
			{
				if (storage[i].itemId == 1210 && storage[i].count > 0)
				{
					return true;
				}
			}
			return false;
		}

		private static void InspectSlotRemotePairs(StationComponent station, int slotIndex, int starId, StationComponent[] gStationPool, out bool hasExternalPair, out bool hasInternalPair)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0046: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			hasExternalPair = false;
			hasInternalPair = false;
			SupplyDemandPair[] remotePairs = station.remotePairs;
			if (remotePairs == null)
			{
				return;
			}
			int num = Math.Min(station.remotePairTotalCount, remotePairs.Length);
			int gid = station.gid;
			for (int i = 0; i < num; i++)
			{
				SupplyDemandPair val = remotePairs[i];
				int num2 = -1;
				if (val.supplyId == gid && val.supplyIndex == slotIndex)
				{
					num2 = val.demandId;
				}
				else if (val.demandId == gid && val.demandIndex == slotIndex)
				{
					num2 = val.supplyId;
				}
				if (num2 <= 0 || num2 >= gStationPool.Length)
				{
					continue;
				}
				StationComponent val2 = gStationPool[num2];
				if (val2 != null && val2.gid == num2)
				{
					if (val2.planetId / 100 != starId)
					{
						hasExternalPair = true;
					}
					else
					{
						hasInternalPair = true;
					}
				}
			}
		}

		private static void AccumulateSlot(Dictionary<int, CombinedLogisticsItem> dict, Dictionary<int, HashSet<int>> planetsByItem, int planetId, StationStore store, bool isCollector, bool hasExternalPair, bool hasWarpCapableStation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_0031: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (!dict.TryGetValue(store.itemId, out var value))
			{
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items)?.Select(store.itemId);
				value = new CombinedLogisticsItem
				{
					ItemId = store.itemId,
					ItemName = ((val != null) ? ((Proto)val).name : $"Item #{store.itemId}"),
					Icon = ((val != null) ? val.iconSprite : null),
					Category = CombinedLogisticsItem.ClassifyItem(val),
					Logic = store.remoteLogic,
					PlanetCount = 1
				};
				dict[store.itemId] = value;
			}
			value.StoredCount += store.count;
			value.MaxCount += store.max;
			value.InTransitOrder += store.remoteOrder;
			value.SlotCount++;
			if (isCollector)
			{
				value.CollectorSlotCount++;
			}
			if (hasExternalPair)
			{
				value.HasExternalStarPair = true;
			}
			if (hasWarpCapableStation)
			{
				value.HasWarpCapableStation = true;
			}
			if (planetsByItem != null)
			{
				if (!planetsByItem.TryGetValue(store.itemId, out var value2))
				{
					value2 = new HashSet<int>();
					planetsByItem[store.itemId] = value2;
				}
				value2.Add(planetId);
				value.PlanetCount = value2.Count;
			}
		}

		private static void ApplyInterstellarSmartFilter(Dictionary<int, CombinedLogisticsItem> exportsByItem, Dictionary<int, CombinedLogisticsItem> importsByItem)
		{
			List<int> list = new List<int>();
			foreach (int key2 in exportsByItem.Keys)
			{
				if (importsByItem.ContainsKey(key2))
				{
					list.Add(key2);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				int key = list[i];
				CombinedLogisticsItem combinedLogisticsItem = exportsByItem[key];
				CombinedLogisticsItem combinedLogisticsItem2 = importsByItem[key];
				if (combinedLogisticsItem.HasExternalStarPair && !combinedLogisticsItem2.HasExternalStarPair)
				{
					importsByItem.Remove(key);
				}
				else if (combinedLogisticsItem2.HasExternalStarPair && !combinedLogisticsItem.HasExternalStarPair)
				{
					exportsByItem.Remove(key);
				}
				else if (!combinedLogisticsItem.HasExternalStarPair && !combinedLogisticsItem2.HasExternalStarPair)
				{
					exportsByItem.Remove(key);
					importsByItem.Remove(key);
				}
			}
		}

		private static void ApplyNetOutIntraSystemFilter(Dictionary<int, CombinedLogisticsItem> exportsByItem, Dictionary<int, CombinedLogisticsItem> importsByItem)
		{
			List<int> list = new List<int>();
			foreach (int key2 in exportsByItem.Keys)
			{
				if (importsByItem.ContainsKey(key2))
				{
					list.Add(key2);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				int key = list[i];
				CombinedLogisticsItem combinedLogisticsItem = exportsByItem[key];
				CombinedLogisticsItem combinedLogisticsItem2 = importsByItem[key];
				int num = combinedLogisticsItem.SlotCount - combinedLogisticsItem.CollectorSlotCount;
				if (num <= combinedLogisticsItem2.SlotCount && combinedLogisticsItem.CollectorSlotCount == 0)
				{
					exportsByItem.Remove(key);
					if (combinedLogisticsItem2.SlotCount <= num)
					{
						importsByItem.Remove(key);
					}
				}
				else
				{
					importsByItem.Remove(key);
				}
			}
		}

		private static void LinkHubItems(Dictionary<int, CombinedLogisticsItem> exportsByItem, Dictionary<int, CombinedLogisticsItem> importsByItem)
		{
			foreach (KeyValuePair<int, CombinedLogisticsItem> item in exportsByItem)
			{
				if (importsByItem.TryGetValue(item.Key, out var value))
				{
					CombinedLogisticsItem value2 = item.Value;
					value2.IsHub = true;
					value2.HubCounterpartStored = value.StoredCount;
					value2.HubCounterpartMax = value.MaxCount;
					value2.HubCounterpartSlots = value.SlotCount;
					value.IsHub = true;
					value.HubCounterpartStored = value2.StoredCount;
					value.HubCounterpartMax = value2.MaxCount;
					value.HubCounterpartSlots = value2.SlotCount;
				}
			}
		}

		private static void RecordPlanetSupplyAvailability(Dictionary<int, SupplyAvailability> supplyByItem, int planetId, int starId, CombinedLogisticsItem expItem, CombinedLogisticsItem impItemOnSamePlanet, int critPct, int warnPct)
		{
			if (expItem == null || expItem.StoredCount <= 0)
			{
				return;
			}
			EHealthStatus healthStatus = expItem.GetHealthStatus(critPct, warnPct);
			if (impItemOnSamePlanet != null && impItemOnSamePlanet.GetHealthStatus(critPct, warnPct) != EHealthStatus.Healthy && impItemOnSamePlanet.MaxCount > expItem.MaxCount)
			{
				return;
			}
			long num = expItem.StoredCount + expItem.InTransitOrder;
			if (healthStatus != EHealthStatus.Healthy && num < 400)
			{
				return;
			}
			if (!supplyByItem.TryGetValue(expItem.ItemId, out var value))
			{
				value.HealthySupplierPlanetCount = 1;
				value.SingleSupplierPlanetId = planetId;
				value.SingleSupplierStarId = starId;
				value.MultipleStarSystems = false;
			}
			else
			{
				if (value.HealthySupplierPlanetCount == 1 && value.SingleSupplierPlanetId != planetId)
				{
					value.HealthySupplierPlanetCount = 2;
				}
				else if (value.HealthySupplierPlanetCount > 1)
				{
					value.HealthySupplierPlanetCount++;
				}
				if (value.SingleSupplierStarId != starId)
				{
					value.MultipleStarSystems = true;
				}
			}
			supplyByItem[expItem.ItemId] = value;
		}

		private static bool HasExternalSupply(Dictionary<int, SupplyAvailability> supplyByItem, int itemId, int targetPlanetId, int targetStarId)
		{
			if (!supplyByItem.TryGetValue(itemId, out var value) || value.HealthySupplierPlanetCount <= 0)
			{
				return false;
			}
			if (targetPlanetId > 0)
			{
				if (value.HealthySupplierPlanetCount < 2)
				{
					return value.SingleSupplierPlanetId != targetPlanetId;
				}
				return true;
			}
			if (targetStarId > 0)
			{
				if (!value.MultipleStarSystems && value.SingleSupplierStarId == targetStarId)
				{
					return value.HealthySupplierPlanetCount >= 2;
				}
				return true;
			}
			return true;
		}

		private static void CollectGalaxySupplyAvailability(StellogisticsConfig config, int galaxySeed, int critPct, int warnPct, Dictionary<int, SupplyAvailability> outSupplyByItem)
		{
			outSupplyByItem.Clear();
			if (GameMain.galaxy?.stars == null || GameMain.data == null)
			{
				return;
			}
			bool value = config.IncludeOrbitalCollectors.Value;
			Dictionary<int, CombinedLogisticsItem> dictionary = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, CombinedLogisticsItem> dictionary2 = new Dictionary<int, CombinedLogisticsItem>();
			StarData[] stars = GameMain.galaxy.stars;
			foreach (StarData val in stars)
			{
				if (val == null || val.planets == null)
				{
					continue;
				}
				for (int j = 0; j < val.planets.Length; j++)
				{
					PlanetData val2 = val.planets[j];
					StationComponent[] obj = val2?.factory?.transport?.stationPool;
					int num = ((val2?.factory?.transport != null) ? val2.factory.transport.stationCursor : 0);
					if (obj == null || num <= 0 || config.IsPlanetOrStarIgnored(galaxySeed, val2))
					{
						continue;
					}
					dictionary.Clear();
					dictionary2.Clear();
					int totalIlsCount = 0;
					int totalCollectorCount = 0;
					int totalWarperCount = 0;
					int totalIdleShips = 0;
					int totalWorkShips = 0;
					AggregatePlanetStations(val2, val.id, value, EStarFilterMode.AllRemoteSlots, null, dictionary, dictionary2, null, null, ref totalIlsCount, ref totalCollectorCount, ref totalWarperCount, ref totalIdleShips, ref totalWorkShips);
					foreach (CombinedLogisticsItem value3 in dictionary.Values)
					{
						dictionary2.TryGetValue(value3.ItemId, out var value2);
						RecordPlanetSupplyAvailability(outSupplyByItem, val2.id, val.id, value3, value2, critPct, warnPct);
					}
				}
			}
		}

		private static void EvaluateImportBottleneck(CombinedLogisticsItem impItem, EHealthStatus status, Dictionary<int, SupplyAvailability> supplyByItem, int planetId, int starId)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (impItem != null && (int)impItem.Logic == 2 && impItem.MaxCount > 0 && status != EHealthStatus.Healthy && impItem.FillRatio + impItem.InboundTransitRatio < 0.85f && HasExternalSupply(supplyByItem, impItem.ItemId, planetId, starId))
			{
				impItem.HasLogisticsBottleneck = true;
			}
		}

		private static void FinalizeSummary(LogisticsSummary summary, Dictionary<int, CombinedLogisticsItem> exportsByItem, Dictionary<int, CombinedLogisticsItem> importsByItem, StellogisticsConfig config, int targetPlanetId, int targetStarId)
		{
			int value = config.CriticalThresholdPercent.Value;
			int value2 = config.WarningThresholdPercent.Value;
			int num = Mathf.Clamp(config.ExcludeFullThresholdPercent.Value, 40, 100);
			ESortOrder sortOrder = config.SortOrder.Value;
			bool exclude100PercentForAstro = config.GetExclude100PercentForAstro(summary.GalaxySeed, summary.TargetAstroId);
			Dictionary<int, SupplyAvailability> dictionary = null;
			foreach (CombinedLogisticsItem value3 in exportsByItem.Values)
			{
				bool flag = value3.DisplayPercent >= num;
				if (!config.IsItemVisibleForAstro(summary.GalaxySeed, summary.TargetAstroId, value3.ItemId, value3.Category) || (exclude100PercentForAstro && flag))
				{
					summary.FilteredOutItemCount++;
					continue;
				}
				summary.Exports.Add(value3);
				switch (value3.GetHealthStatus(value, value2))
				{
				case EHealthStatus.Critical:
					summary.CriticalExportCount++;
					break;
				case EHealthStatus.Warning:
					summary.WarningExportCount++;
					break;
				}
			}
			foreach (CombinedLogisticsItem value4 in importsByItem.Values)
			{
				bool flag2 = value4.DisplayPercent >= num;
				if (!config.IsItemVisibleForAstro(summary.GalaxySeed, summary.TargetAstroId, value4.ItemId, value4.Category) || (exclude100PercentForAstro && flag2))
				{
					summary.FilteredOutItemCount++;
					continue;
				}
				summary.Imports.Add(value4);
				EHealthStatus healthStatus = value4.GetHealthStatus(value, value2);
				switch (healthStatus)
				{
				case EHealthStatus.Critical:
					summary.CriticalImportCount++;
					break;
				case EHealthStatus.Warning:
					summary.WarningImportCount++;
					break;
				}
				if (healthStatus != EHealthStatus.Healthy && value4.FillRatio + value4.InboundTransitRatio < 0.85f)
				{
					if (dictionary == null)
					{
						dictionary = new Dictionary<int, SupplyAvailability>();
						CollectGalaxySupplyAvailability(config, summary.GalaxySeed, value, value2, dictionary);
					}
					EvaluateImportBottleneck(value4, healthStatus, dictionary, targetPlanetId, targetStarId);
				}
			}
			Comparison<CombinedLogisticsItem> comparison = delegate(CombinedLogisticsItem a, CombinedLogisticsItem b)
			{
				if (sortOrder == ESortOrder.ShortageFirst)
				{
					int num2 = a.DisplayPercent.CompareTo(b.DisplayPercent);
					if (num2 != 0)
					{
						return num2;
					}
					int num3 = a.FillRatio.CompareTo(b.FillRatio);
					if (num3 != 0)
					{
						return num3;
					}
					int num4 = b.MaxCount.CompareTo(a.MaxCount);
					if (num4 != 0)
					{
						return num4;
					}
				}
				else if (sortOrder == ESortOrder.StoredAmountDesc)
				{
					int num5 = b.DisplayPercent.CompareTo(a.DisplayPercent);
					if (num5 != 0)
					{
						return num5;
					}
					int num6 = b.FillRatio.CompareTo(a.FillRatio);
					if (num6 != 0)
					{
						return num6;
					}
					int num7 = b.StoredCount.CompareTo(a.StoredCount);
					if (num7 != 0)
					{
						return num7;
					}
				}
				return a.ItemId.CompareTo(b.ItemId);
			};
			summary.Exports.Sort(comparison);
			summary.Imports.Sort(comparison);
		}

		public static void CollectStoredItemIds(HashSet<int> result)
		{
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			result.Clear();
			GameData data = GameMain.data;
			if (data == null || data.factories == null)
			{
				return;
			}
			int num = Math.Min(data.factoryCount, data.factories.Length);
			for (int i = 0; i < num; i++)
			{
				PlanetFactory val = data.factories[i];
				if (val == null)
				{
					continue;
				}
				PlanetTransport transport = val.transport;
				if (transport != null)
				{
					StationComponent[] stationPool = transport.stationPool;
					if (stationPool != null)
					{
						int num2 = Math.Min(transport.stationCursor, stationPool.Length);
						for (int j = 1; j < num2; j++)
						{
							StationComponent val2 = stationPool[j];
							if (val2 == null || val2.id != j || val2.storage == null)
							{
								continue;
							}
							for (int k = 0; k < val2.storage.Length; k++)
							{
								int itemId = val2.storage[k].itemId;
								if (itemId > 0)
								{
									result.Add(itemId);
								}
							}
						}
					}
					DispenserComponent[] dispenserPool = transport.dispenserPool;
					if (dispenserPool != null)
					{
						int num3 = Math.Min(transport.dispenserCursor, dispenserPool.Length);
						for (int l = 1; l < num3; l++)
						{
							DispenserComponent val3 = dispenserPool[l];
							if (val3 != null && val3.id == l && val3.filter > 0)
							{
								result.Add(val3.filter);
							}
						}
					}
				}
				FactoryStorage factoryStorage = val.factoryStorage;
				if (factoryStorage == null)
				{
					continue;
				}
				StorageComponent[] storagePool = factoryStorage.storagePool;
				if (storagePool != null)
				{
					int num4 = Math.Min(factoryStorage.storageCursor, storagePool.Length);
					for (int m = 1; m < num4; m++)
					{
						StorageComponent val4 = storagePool[m];
						if (val4 == null || val4.id != m || val4.grids == null)
						{
							continue;
						}
						for (int n = 0; n < val4.grids.Length; n++)
						{
							int itemId2 = val4.grids[n].itemId;
							if (itemId2 > 0)
							{
								result.Add(itemId2);
							}
							int filter = val4.grids[n].filter;
							if (filter > 0)
							{
								result.Add(filter);
							}
						}
					}
				}
				TankComponent[] tankPool = factoryStorage.tankPool;
				if (tankPool == null)
				{
					continue;
				}
				int num5 = Math.Min(factoryStorage.tankCursor, tankPool.Length);
				for (int num6 = 1; num6 < num5; num6++)
				{
					TankComponent val5 = tankPool[num6];
					if (val5.id == num6 && val5.fluidId > 0)
					{
						result.Add(val5.fluidId);
					}
				}
			}
		}

		public static GalaxyItemSearchSummary SearchGalaxyForItem(int itemId, StellogisticsConfig config)
		{
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Invalid comparison between Unknown and I4
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Invalid comparison between Unknown and I4
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items)?.Select(itemId);
			GalaxyItemSearchSummary galaxyItemSearchSummary = new GalaxyItemSearchSummary
			{
				ItemId = itemId,
				ItemName = ((val != null) ? ((Proto)val).name : $"Item #{itemId}"),
				Icon = ((val != null) ? val.iconSprite : null)
			};
			if (itemId <= 0 || GameMain.galaxy == null || GameMain.galaxy.stars == null || GameMain.data == null)
			{
				return galaxyItemSearchSummary;
			}
			int seed = GameMain.galaxy.seed;
			bool value = config.IncludeOrbitalCollectors.Value;
			int value2 = config.CriticalThresholdPercent.Value;
			int value3 = config.WarningThresholdPercent.Value;
			int num = Mathf.Clamp(config.ExcludeFullThresholdPercent.Value, 40, 100);
			bool exclude100PercentForAstro = config.GetExclude100PercentForAstro(seed, 0);
			ESortOrder sortOrder = config.SortOrder.Value;
			StarData[] stars = GameMain.galaxy.stars;
			foreach (StarData val2 in stars)
			{
				if (val2 == null || val2.planets == null)
				{
					continue;
				}
				for (int j = 0; j < val2.planets.Length; j++)
				{
					PlanetData val3 = val2.planets[j];
					StationComponent[] array = val3?.factory?.transport?.stationPool;
					int num2 = ((val3?.factory?.transport != null) ? val3.factory.transport.stationCursor : 0);
					if (array == null || num2 <= 0)
					{
						continue;
					}
					CombinedLogisticsItem combinedLogisticsItem = null;
					CombinedLogisticsItem combinedLogisticsItem2 = null;
					for (int k = 1; k < num2; k++)
					{
						StationComponent val4 = array[k];
						if (val4 == null || val4.id != k || !val4.isStellar || val4.storage == null || (val4.isCollector && !value))
						{
							continue;
						}
						StationStore[] storage = val4.storage;
						foreach (StationStore val5 in storage)
						{
							if (val5.itemId != itemId || (int)val5.remoteLogic == 0)
							{
								continue;
							}
							if ((int)val5.remoteLogic == 1)
							{
								if (combinedLogisticsItem == null)
								{
									combinedLogisticsItem = new CombinedLogisticsItem
									{
										ItemId = itemId,
										ItemName = galaxyItemSearchSummary.ItemName,
										Icon = galaxyItemSearchSummary.Icon,
										Category = CombinedLogisticsItem.ClassifyItem(val),
										Logic = (ELogisticStorage)1,
										PlanetCount = 1
									};
								}
								combinedLogisticsItem.StoredCount += val5.count;
								combinedLogisticsItem.MaxCount += val5.max;
								combinedLogisticsItem.InTransitOrder += val5.remoteOrder;
								combinedLogisticsItem.SlotCount++;
								if (val4.isCollector)
								{
									combinedLogisticsItem.CollectorSlotCount++;
								}
							}
							else if ((int)val5.remoteLogic == 2)
							{
								if (combinedLogisticsItem2 == null)
								{
									combinedLogisticsItem2 = new CombinedLogisticsItem
									{
										ItemId = itemId,
										ItemName = galaxyItemSearchSummary.ItemName,
										Icon = galaxyItemSearchSummary.Icon,
										Category = CombinedLogisticsItem.ClassifyItem(val),
										Logic = (ELogisticStorage)2,
										PlanetCount = 1
									};
								}
								combinedLogisticsItem2.StoredCount += val5.count;
								combinedLogisticsItem2.MaxCount += val5.max;
								combinedLogisticsItem2.InTransitOrder += val5.remoteOrder;
								combinedLogisticsItem2.SlotCount++;
								if (val4.isCollector)
								{
									combinedLogisticsItem2.CollectorSlotCount++;
								}
							}
						}
					}
					if (combinedLogisticsItem != null && combinedLogisticsItem2 != null)
					{
						combinedLogisticsItem.IsHub = true;
						combinedLogisticsItem.HubCounterpartStored = combinedLogisticsItem2.StoredCount;
						combinedLogisticsItem.HubCounterpartMax = combinedLogisticsItem2.MaxCount;
						combinedLogisticsItem.HubCounterpartSlots = combinedLogisticsItem2.SlotCount;
						combinedLogisticsItem2.IsHub = true;
						combinedLogisticsItem2.HubCounterpartStored = combinedLogisticsItem.StoredCount;
						combinedLogisticsItem2.HubCounterpartMax = combinedLogisticsItem.MaxCount;
						combinedLogisticsItem2.HubCounterpartSlots = combinedLogisticsItem.SlotCount;
					}
					bool flag = combinedLogisticsItem != null && (!exclude100PercentForAstro || combinedLogisticsItem.DisplayPercent < num);
					bool flag2 = combinedLogisticsItem2 != null && (!exclude100PercentForAstro || combinedLogisticsItem2.DisplayPercent < num);
					if ((flag || flag2) && config.IsPlanetOrStarIgnored(seed, val3))
					{
						galaxyItemSearchSummary.IgnoredPlanetMatchCount++;
						continue;
					}
					if (flag)
					{
						galaxyItemSearchSummary.ExportingPlanets.Add(new PlanetItemLocationEntry
						{
							Planet = val3,
							Star = val2,
							PlanetId = val3.id,
							PlanetAstroId = val3.astroId,
							PlanetName = val3.displayName,
							StarName = val2.displayName,
							Item = combinedLogisticsItem
						});
						switch (combinedLogisticsItem.GetHealthStatus(value2, value3))
						{
						case EHealthStatus.Critical:
							galaxyItemSearchSummary.CriticalExportPlanetCount++;
							break;
						case EHealthStatus.Warning:
							galaxyItemSearchSummary.WarningExportPlanetCount++;
							break;
						}
					}
					if (flag2)
					{
						galaxyItemSearchSummary.ImportingPlanets.Add(new PlanetItemLocationEntry
						{
							Planet = val3,
							Star = val2,
							PlanetId = val3.id,
							PlanetAstroId = val3.astroId,
							PlanetName = val3.displayName,
							StarName = val2.displayName,
							Item = combinedLogisticsItem2
						});
						switch (combinedLogisticsItem2.GetHealthStatus(value2, value3))
						{
						case EHealthStatus.Critical:
							galaxyItemSearchSummary.CriticalImportPlanetCount++;
							break;
						case EHealthStatus.Warning:
							galaxyItemSearchSummary.WarningImportPlanetCount++;
							break;
						}
					}
				}
			}
			Comparison<PlanetItemLocationEntry> comparison = delegate(PlanetItemLocationEntry a, PlanetItemLocationEntry b)
			{
				if (sortOrder == ESortOrder.ShortageFirst)
				{
					int num3 = a.Item.DisplayPercent.CompareTo(b.Item.DisplayPercent);
					if (num3 != 0)
					{
						return num3;
					}
					int num4 = a.Item.FillRatio.CompareTo(b.Item.FillRatio);
					if (num4 != 0)
					{
						return num4;
					}
					int num5 = b.Item.MaxCount.CompareTo(a.Item.MaxCount);
					if (num5 != 0)
					{
						return num5;
					}
				}
				else if (sortOrder == ESortOrder.StoredAmountDesc)
				{
					int num6 = b.Item.DisplayPercent.CompareTo(a.Item.DisplayPercent);
					if (num6 != 0)
					{
						return num6;
					}
					int num7 = b.Item.FillRatio.CompareTo(a.Item.FillRatio);
					if (num7 != 0)
					{
						return num7;
					}
					int num8 = b.Item.StoredCount.CompareTo(a.Item.StoredCount);
					if (num8 != 0)
					{
						return num8;
					}
				}
				return a.PlanetId.CompareTo(b.PlanetId);
			};
			galaxyItemSearchSummary.ExportingPlanets.Sort(comparison);
			galaxyItemSearchSummary.ImportingPlanets.Sort(comparison);
			return galaxyItemSearchSummary;
		}

		public static GalaxyItemSearchSummary ScanGalaxyBottlenecks(StellogisticsConfig config)
		{
			return ScanGalaxyFinder(config, onlyBottlenecks: true);
		}

		public static GalaxyItemSearchSummary ScanGalaxyFinder(StellogisticsConfig config, bool onlyBottlenecks)
		{
			int galaxySeed = ((GameMain.galaxy != null) ? GameMain.galaxy.seed : 0);
			HashSet<int> hashSet = new HashSet<int>();
			CollectStoredItemIds(hashSet);
			int num = 0;
			int num2 = -1;
			ItemProto val = null;
			foreach (int item in hashSet)
			{
				ItemProto val2 = ((ProtoSet<ItemProto>)(object)LDB.items)?.Select(item);
				if (val2 == null || ((Proto)val2).ID <= 0 || val2.GridIndex <= 0)
				{
					continue;
				}
				EItemCategoryFilter itemCategory = CombinedLogisticsItem.ClassifyItem(val2);
				if (config.IsItemVisibleForAstro(galaxySeed, 0, item, itemCategory))
				{
					num++;
					if (num == 1)
					{
						num2 = item;
						val = val2;
					}
					else
					{
						num2 = -1;
						val = null;
					}
				}
			}
			string itemName = ((num == 0) ? "No Items Checked" : ((num2 > 0) ? ((val != null) ? ((Proto)val).name : $"Item #{num2}") : ((!onlyBottlenecks) ? ((num < hashSet.Count) ? $"{num} Items" : "All Items") : ((num < hashSet.Count) ? $"Bottlenecks ({num} Items)" : "Bottlenecks"))));
			GalaxyItemSearchSummary galaxyItemSearchSummary = new GalaxyItemSearchSummary
			{
				IsBottleneckScan = (num2 <= 0),
				CheckedItemCount = num,
				ItemId = num2,
				ItemName = itemName,
				Icon = ((val != null) ? val.iconSprite : null)
			};
			if (num == 0 || GameMain.galaxy == null || GameMain.galaxy.stars == null || GameMain.data == null)
			{
				return galaxyItemSearchSummary;
			}
			bool value = config.IncludeOrbitalCollectors.Value;
			int value2 = config.CriticalThresholdPercent.Value;
			int value3 = config.WarningThresholdPercent.Value;
			int num3 = Mathf.Clamp(config.ExcludeFullThresholdPercent.Value, 40, 100);
			bool exclude100PercentForAstro = config.GetExclude100PercentForAstro(galaxySeed, 0);
			ESortOrder sortOrder = config.SortOrder.Value;
			Dictionary<int, CombinedLogisticsItem> dictionary = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, CombinedLogisticsItem> dictionary2 = new Dictionary<int, CombinedLogisticsItem>();
			Dictionary<int, SupplyAvailability> supplyByItem = new Dictionary<int, SupplyAvailability>();
			StarData[] stars = GameMain.galaxy.stars;
			foreach (StarData val3 in stars)
			{
				if (val3 == null || val3.planets == null)
				{
					continue;
				}
				for (int j = 0; j < val3.planets.Length; j++)
				{
					PlanetData val4 = val3.planets[j];
					StationComponent[] obj = val4?.factory?.transport?.stationPool;
					int num4 = ((val4?.factory?.transport != null) ? val4.factory.transport.stationCursor : 0);
					if (obj == null || num4 <= 0)
					{
						continue;
					}
					dictionary.Clear();
					dictionary2.Clear();
					int totalIlsCount = 0;
					int totalCollectorCount = 0;
					int totalWarperCount = 0;
					int totalIdleShips = 0;
					int totalWorkShips = 0;
					AggregatePlanetStations(val4, val3.id, value, EStarFilterMode.AllRemoteSlots, null, dictionary, dictionary2, null, null, ref totalIlsCount, ref totalCollectorCount, ref totalWarperCount, ref totalIdleShips, ref totalWorkShips);
					LinkHubItems(dictionary, dictionary2);
					bool flag = config.IsPlanetOrStarIgnored(galaxySeed, val4);
					bool flag2 = false;
					foreach (CombinedLogisticsItem value5 in dictionary.Values)
					{
						if (!flag)
						{
							dictionary2.TryGetValue(value5.ItemId, out var value4);
							RecordPlanetSupplyAvailability(supplyByItem, val4.id, val3.id, value5, value4, value2, value3);
						}
						if (!config.IsItemVisibleForAstro(galaxySeed, 0, value5.ItemId, value5.Category))
						{
							continue;
						}
						EHealthStatus healthStatus = value5.GetHealthStatus(value2, value3);
						if (onlyBottlenecks)
						{
							if (healthStatus == EHealthStatus.Healthy)
							{
								continue;
							}
						}
						else if (exclude100PercentForAstro && value5.DisplayPercent >= num3)
						{
							continue;
						}
						if (flag)
						{
							flag2 = true;
							continue;
						}
						galaxyItemSearchSummary.ExportingPlanets.Add(new PlanetItemLocationEntry
						{
							Planet = val4,
							Star = val3,
							PlanetId = val4.id,
							PlanetAstroId = val4.astroId,
							PlanetName = val4.displayName,
							StarName = val3.displayName,
							Item = value5
						});
						switch (healthStatus)
						{
						case EHealthStatus.Critical:
							galaxyItemSearchSummary.CriticalExportPlanetCount++;
							break;
						case EHealthStatus.Warning:
							galaxyItemSearchSummary.WarningExportPlanetCount++;
							break;
						}
					}
					foreach (CombinedLogisticsItem value6 in dictionary2.Values)
					{
						if (!config.IsItemVisibleForAstro(galaxySeed, 0, value6.ItemId, value6.Category))
						{
							continue;
						}
						EHealthStatus healthStatus2 = value6.GetHealthStatus(value2, value3);
						if (onlyBottlenecks)
						{
							if (healthStatus2 == EHealthStatus.Healthy)
							{
								continue;
							}
						}
						else if (exclude100PercentForAstro && value6.DisplayPercent >= num3)
						{
							continue;
						}
						if (flag)
						{
							flag2 = true;
							continue;
						}
						galaxyItemSearchSummary.ImportingPlanets.Add(new PlanetItemLocationEntry
						{
							Planet = val4,
							Star = val3,
							PlanetId = val4.id,
							PlanetAstroId = val4.astroId,
							PlanetName = val4.displayName,
							StarName = val3.displayName,
							Item = value6
						});
						switch (healthStatus2)
						{
						case EHealthStatus.Critical:
							galaxyItemSearchSummary.CriticalImportPlanetCount++;
							break;
						case EHealthStatus.Warning:
							galaxyItemSearchSummary.WarningImportPlanetCount++;
							break;
						}
					}
					if (flag2)
					{
						galaxyItemSearchSummary.IgnoredPlanetMatchCount++;
					}
				}
			}
			for (int k = 0; k < galaxyItemSearchSummary.ImportingPlanets.Count; k++)
			{
				PlanetItemLocationEntry planetItemLocationEntry = galaxyItemSearchSummary.ImportingPlanets[k];
				EHealthStatus healthStatus3 = planetItemLocationEntry.Item.GetHealthStatus(value2, value3);
				int starId = ((planetItemLocationEntry.Star != null) ? planetItemLocationEntry.Star.id : (planetItemLocationEntry.PlanetId / 100));
				EvaluateImportBottleneck(planetItemLocationEntry.Item, healthStatus3, supplyByItem, planetItemLocationEntry.PlanetId, starId);
			}
			Comparison<PlanetItemLocationEntry> comparison = delegate(PlanetItemLocationEntry a, PlanetItemLocationEntry b)
			{
				if (sortOrder == ESortOrder.ShortageFirst)
				{
					int num5 = a.Item.DisplayPercent.CompareTo(b.Item.DisplayPercent);
					if (num5 != 0)
					{
						return num5;
					}
					int num6 = a.Item.FillRatio.CompareTo(b.Item.FillRatio);
					if (num6 != 0)
					{
						return num6;
					}
					int num7 = b.Item.MaxCount.CompareTo(a.Item.MaxCount);
					if (num7 != 0)
					{
						return num7;
					}
				}
				else if (sortOrder == ESortOrder.StoredAmountDesc)
				{
					int num8 = b.Item.DisplayPercent.CompareTo(a.Item.DisplayPercent);
					if (num8 != 0)
					{
						return num8;
					}
					int num9 = b.Item.FillRatio.CompareTo(a.Item.FillRatio);
					if (num9 != 0)
					{
						return num9;
					}
					int num10 = b.Item.StoredCount.CompareTo(a.Item.StoredCount);
					if (num10 != 0)
					{
						return num10;
					}
				}
				int num11 = a.Item.ItemId.CompareTo(b.Item.ItemId);
				return (num11 != 0) ? num11 : a.PlanetId.CompareTo(b.PlanetId);
			};
			galaxyItemSearchSummary.ExportingPlanets.Sort(comparison);
			galaxyItemSearchSummary.ImportingPlanets.Sort(comparison);
			return galaxyItemSearchSummary;
		}

		public static void CollectLogisticsPlanetsAndStars(StellogisticsConfig config, List<PlanetLogisticsFilterEntry> outEntries)
		{
			outEntries.Clear();
			if (GameMain.galaxy == null || GameMain.galaxy.stars == null)
			{
				return;
			}
			int seed = GameMain.galaxy.seed;
			bool value = config.IncludeOrbitalCollectors.Value;
			List<PlanetLogisticsFilterEntry> list = new List<PlanetLogisticsFilterEntry>();
			StarData[] stars = GameMain.galaxy.stars;
			foreach (StarData val in stars)
			{
				if (val == null || val.planets == null)
				{
					continue;
				}
				list.Clear();
				int num = 0;
				int num2 = 0;
				for (int j = 0; j < val.planets.Length; j++)
				{
					PlanetData val2 = val.planets[j];
					if (val2 == null)
					{
						continue;
					}
					int num3 = 0;
					int num4 = 0;
					StationComponent[] array = val2.factory?.transport?.stationPool;
					int num5 = ((val2.factory?.transport != null) ? val2.factory.transport.stationCursor : 0);
					if (array != null && num5 > 0)
					{
						for (int k = 1; k < num5; k++)
						{
							StationComponent val3 = array[k];
							if (val3 == null || val3.id != k || !val3.isStellar)
							{
								continue;
							}
							if (val3.isCollector)
							{
								if (value)
								{
									num4++;
								}
							}
							else
							{
								num3++;
							}
						}
					}
					bool flag = config.IsAstroIgnored(seed, val2.astroId);
					if (num3 > 0 || num4 > 0 || flag)
					{
						num += num3;
						num2 += num4;
						string metaInfo = ((num3 > 0 && num4 > 0) ? $"{num3} ILS +{num4} OC" : ((num4 > 0) ? $"{num4} OC" : ((num3 <= 0) ? "0 ILS (Ignored)" : $"{num3} ILS")));
						list.Add(new PlanetLogisticsFilterEntry
						{
							IsStarSystem = false,
							AstroId = val2.astroId,
							ParentStarAstroId = val.astroId,
							Star = val,
							Planet = val2,
							DisplayName = val2.displayName,
							MetaInfo = metaInfo,
							IlsCount = num3,
							CollectorCount = num4
						});
					}
				}
				bool flag2 = config.IsAstroIgnored(seed, val.astroId);
				if (list.Count > 0 || flag2)
				{
					string metaInfo2 = ((num2 > 0) ? $"System • {list.Count} Planets • {num} ILS +{num2} OC" : $"System • {list.Count} Planets • {num} ILS");
					outEntries.Add(new PlanetLogisticsFilterEntry
					{
						IsStarSystem = true,
						AstroId = val.astroId,
						ParentStarAstroId = val.astroId,
						Star = val,
						Planet = null,
						DisplayName = "★ " + val.displayName,
						MetaInfo = metaInfo2,
						IlsCount = num,
						CollectorCount = num2
					});
					for (int l = 0; l < list.Count; l++)
					{
						outEntries.Add(list[l]);
					}
				}
			}
		}
	}
	public enum EHealthStatus
	{
		Critical,
		Warning,
		Healthy
	}
	public class CombinedLogisticsItem
	{
		public int ItemId;

		public string ItemName;

		public Sprite Icon;

		public EItemCategoryFilter Category;

		public ELogisticStorage Logic;

		public long StoredCount;

		public long MaxCount;

		public long InTransitOrder;

		public int SlotCount;

		public int CollectorSlotCount;

		public int PlanetCount;

		public bool HasExternalStarPair;

		public bool HasWarpCapableStation;

		public bool IsHub;

		public long HubCounterpartStored;

		public long HubCounterpartMax;

		public int HubCounterpartSlots;

		public bool HasLogisticsBottleneck;

		public float FillRatio
		{
			get
			{
				if (MaxCount <= 0)
				{
					if (StoredCount <= 0)
					{
						return 0f;
					}
					return 1f;
				}
				return Mathf.Clamp01((float)StoredCount / (float)MaxCount);
			}
		}

		public float InboundTransitRatio
		{
			get
			{
				if (MaxCount <= 0 || InTransitOrder <= 0)
				{
					return 0f;
				}
				float num = Mathf.Clamp01(1f - FillRatio);
				return Mathf.Clamp((float)InTransitOrder / (float)MaxCount, 0f, num);
			}
		}

		public int DisplayPercent
		{
			get
			{
				if (MaxCount <= 0)
				{
					if (StoredCount <= 0)
					{
						return 0;
					}
					return 100;
				}
				if (StoredCount <= 0)
				{
					return 0;
				}
				if (StoredCount >= MaxCount)
				{
					return 100;
				}
				return Mathf.Clamp(Mathf.RoundToInt((float)StoredCount / (float)MaxCount * 100f), 1, 99);
			}
		}

		public EHealthStatus GetHealthStatus(int criticalThresholdPct, int warningThresholdPct)
		{
			if (MaxCount <= 0)
			{
				if (StoredCount <= 0)
				{
					return EHealthStatus.Critical;
				}
				return EHealthStatus.Healthy;
			}
			int displayPercent = DisplayPercent;
			if (StoredCount <= 0 || displayPercent <= criticalThresholdPct)
			{
				return EHealthStatus.Critical;
			}
			if (displayPercent <= warningThresholdPct)
			{
				return EHealthStatus.Warning;
			}
			return EHealthStatus.Healthy;
		}

		public static EItemCategoryFilter ClassifyItem(ItemProto proto)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0069: Expected I4, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Invalid comparison between Unknown and I4
			if (proto == null)
			{
				return EItemCategoryFilter.Materials;
			}
			if ((int)proto.Type == 11)
			{
				return EItemCategoryFilter.Matrices;
			}
			if (proto.CanBuild || (int)proto.Type == 5 || (int)proto.Type == 6 || (int)proto.Type == 7 || (int)proto.Type == 8 || (int)proto.Type == 9)
			{
				return EItemCategoryFilter.Buildings;
			}
			EItemType type = proto.Type;
			switch (type - 1)
			{
			default:
				if ((int)type == 10)
				{
					return EItemCategoryFilter.Materials;
				}
				return EItemCategoryFilter.Materials;
			case 0:
				return EItemCategoryFilter.RawResources;
			case 1:
				return EItemCategoryFilter.Materials;
			case 2:
				return EItemCategoryFilter.Components;
			case 3:
				return EItemCategoryFilter.ConsumablesAndPods;
			}
		}

		public static string FormatAmount(long amount)
		{
			long num = Math.Abs(amount);
			string arg = ((amount < 0) ? "-" : "");
			if (num >= 1000000)
			{
				return $"{arg}{(double)num / 1000000.0:0.#}M";
			}
			if (num >= 10000)
			{
				return $"{arg}{(double)num / 1000.0:0.#}k";
			}
			if (num >= 1000)
			{
				return $"{arg}{(double)num / 1000.0:0.0}k";
			}
			return $"{arg}{num}";
		}
	}
	public class LogisticsSummary
	{
		public string TargetName = "";

		public string TargetSubtitle = "";

		public bool IsStarSystem;

		public int TargetAstroId;

		public int GalaxySeed;

		public EItemCategoryFilter ActiveCategoryFilter = EItemCategoryFilter.All;

		public int FilteredOutItemCount;

		public int TotalIlsCount;

		public int TotalCollectorCount;

		public int TotalWarperCount;

		public int TotalIdleShips;

		public int TotalWorkShips;

		public int ColonizedPlanetCount;

		public List<CombinedLogisticsItem> Exports = new List<CombinedLogisticsItem>();

		public List<CombinedLogisticsItem> Imports = new List<CombinedLogisticsItem>();

		public int CriticalExportCount;

		public int WarningExportCount;

		public int CriticalImportCount;

		public int WarningImportCount;

		public bool HasAnyStations
		{
			get
			{
				if (TotalIlsCount <= 0)
				{
					return TotalCollectorCount > 0;
				}
				return true;
			}
		}

		public bool HasAnySlots
		{
			get
			{
				if (Exports.Count <= 0)
				{
					return Imports.Count > 0;
				}
				return true;
			}
		}
	}
	public class PlanetItemLocationEntry
	{
		public PlanetData Planet;

		public StarData Star;

		public int PlanetId;

		public int PlanetAstroId;

		public string PlanetName = "";

		public string StarName = "";

		public CombinedLogisticsItem Item;
	}
	public class GalaxyItemSearchSummary
	{
		public bool IsBottleneckScan;

		public int CheckedItemCount;

		public int ItemId;

		public string ItemName = "";

		public Sprite Icon;

		public List<PlanetItemLocationEntry> ExportingPlanets = new List<PlanetItemLocationEntry>();

		public List<PlanetItemLocationEntry> ImportingPlanets = new List<PlanetItemLocationEntry>();

		public int CriticalExportPlanetCount;

		public int WarningExportPlanetCount;

		public int CriticalImportPlanetCount;

		public int WarningImportPlanetCount;

		public int IgnoredPlanetMatchCount;

		public bool HasAnyLocations
		{
			get
			{
				if (ExportingPlanets.Count <= 0)
				{
					return ImportingPlanets.Count > 0;
				}
				return true;
			}
		}
	}
	public class PlanetLogisticsFilterEntry
	{
		public bool IsStarSystem;

		public int AstroId;

		public int ParentStarAstroId;

		public StarData Star;

		public PlanetData Planet;

		public string DisplayName = "";

		public string MetaInfo = "";

		public int IlsCount;

		public int CollectorCount;
	}
	public static class StarmapPatches
	{
		private static UIStarmapLogisticsPanel _panelInstance;

		private static bool _zoomBlockedThisFrame;

		private static double _savedDistWanted;

		private static float _savedFovWanted;

		public static bool IsPointerOverPanel()
		{
			if ((Object)(object)_panelInstance != (Object)null)
			{
				return _panelInstance.IsPointerOverUI();
			}
			return false;
		}

		public static UIStarmapLogisticsPanel EnsurePanel(UIStarmap starmap)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_panelInstance != (Object)null)
			{
				return _panelInstance;
			}
			UIGame val = UIRoot.instance?.uiGame;
			if ((Object)(object)val == (Object)null || (Object)(object)starmap == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)starmap).transform;
			GameObject val2 = new GameObject("Stellogistics_StarmapPanel", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(transform, false);
			val2.SetActive(false);
			_panelInstance = val2.AddComponent<UIStarmapLogisticsPanel>();
			_panelInstance.Initialize(val, StellogisticsPlugin.ModConfig);
			ManualLogSource log = StellogisticsPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"Initialized Stellogistics Starmap sidebar panel.");
			}
			return _panelInstance;
		}

		public static void DestroyPanel()
		{
			if ((Object)(object)_panelInstance != (Object)null)
			{
				if ((Object)(object)((Component)_panelInstance).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)_panelInstance).gameObject);
				}
				_panelInstance = null;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIStarmap), "_OnOpen")]
		public static void UIStarmap_OnOpen_Postfix(UIStarmap __instance)
		{
			UIStarmapLogisticsPanel uIStarmapLogisticsPanel = EnsurePanel(__instance);
			if ((Object)(object)uIStarmapLogisticsPanel != (Object)null)
			{
				uIStarmapLogisticsPanel.RequestImmediateRefresh();
				uIStarmapLogisticsPanel.OnStarmapUpdate(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIStarmap), "_OnUpdate")]
		public static void UIStarmap_OnUpdate_Postfix(UIStarmap __instance)
		{
			UIStarmapLogisticsPanel uIStarmapLogisticsPanel = EnsurePanel(__instance);
			if ((Object)(object)uIStarmapLogisticsPanel != (Object)null)
			{
				uIStarmapLogisticsPanel.OnStarmapUpdate(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIStarmap), "_OnClose")]
		public static void UIStarmap_OnClose_Postfix()
		{
			if ((Object)(object)_panelInstance != (Object)null && ((Component)_panelInstance).gameObject.activeSelf)
			{
				((Component)_panelInstance).gameObject.SetActive(false);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIStarmap), "_OnDestroy")]
		public static void UIStarmap_OnDestroy_Postfix()
		{
			DestroyPanel();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIPlanetDetail), "OnPlanetDataSet")]
		public static void UIPlanetDetail_OnPlanetDataSet_Postfix()
		{
			if ((Object)(object)_panelInstance != (Object)null)
			{
				_panelInstance.RequestImmediateRefresh();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")]
		public static void UIStarDetail_OnStarDataSet_Postfix()
		{
			if ((Object)(object)_panelInstance != (Object)null)
			{
				_panelInstance.RequestImmediateRefresh();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(VFInput), "UpdateGameStates")]
		public static void VFInput_UpdateGameStates_Postfix()
		{
			if (IsPointerOverPanel())
			{
				VFInput.inScrollView = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void VFInput_CameraZoomIn_Postfix(ref float __result)
		{
			if (IsPointerOverPanel())
			{
				__result = 0f;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static void VFInput_CameraZoomOut_Postfix(ref float __result)
		{
			if (IsPointerOverPanel())
			{
				__result = 0f;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(StarmapCamera), "CameraControl")]
		public static void StarmapCamera_CameraControl_Prefix(StarmapCamera __instance)
		{
			if (IsPointerOverPanel())
			{
				VFInput.inScrollView = true;
				_zoomBlockedThisFrame = true;
				_savedDistWanted = __instance.distWanted;
				_savedFovWanted = __instance.fovWanted;
			}
			else
			{
				_zoomBlockedThisFrame = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StarmapCamera), "CameraControl")]
		public static void StarmapCamera_CameraControl_Postfix(StarmapCamera __instance)
		{
			if (_zoomBlockedThisFrame)
			{
				__instance.distWanted = _savedDistWanted;
				__instance.fovWanted = _savedFovWanted;
			}
		}
	}
	public enum EStarFilterMode
	{
		InterstellarSmart,
		NetOutIntraSystem,
		AllRemoteSlots
	}
	public enum ESortOrder
	{
		ShortageFirst,
		ItemId,
		StoredAmountDesc
	}
	[Flags]
	public enum EItemCategoryFilter
	{
		None = 0,
		RawResources = 1,
		Materials = 2,
		Components = 4,
		Buildings = 8,
		ConsumablesAndPods = 0x10,
		Matrices = 0x20,
		All = 0x3F,
		Exclude100Percent = 0x40
	}
	public class StellogisticsConfig
	{
		private readonly ConfigFile _configFile;

		public const float DefaultPosX = 82f;

		public const float DefaultPosY = -470f;

		public const float DefaultWidth = 310f;

		public const float DefaultMaxHeight = 460f;

		private readonly Dictionary<string, EItemCategoryFilter> _astroFilterCache = new Dictionary<string, EItemCategoryFilter>();

		private readonly Dictionary<string, HashSet<int>> _astroItemOverridesCache = new Dictionary<string, HashSet<int>>();

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

		private const string GlobalFilterKey = "global";

		public ConfigEntry<bool> EnableMod { get; }

		public ConfigEntry<bool> IncludeOrbitalCollectors { get; }

		public ConfigEntry<EStarFilterMode> StarSystemFilterMode { get; }

		public ConfigEntry<ESortOrder> SortOrder { get; }

		public ConfigEntry<bool> ShowOnHover { get; }

		public ConfigEntry<bool> ShowInTransitBar { get; }

		public ConfigEntry<int> CriticalThresholdPercent { get; }

		public ConfigEntry<int> WarningThresholdPercent { get; }

		public ConfigEntry<int> ExcludeFullThresholdPercent { get; }

		public ConfigEntry<float> PanelWidth { get; }

		public ConfigEntry<float> PanelMaxHeight { get; }

		public ConfigEntry<bool> UseCustomPosition { get; }

		public ConfigEntry<float> CustomPanelPosX { get; }

		public ConfigEntry<float> CustomPanelPosY { get; }

		public ConfigEntry<EItemCategoryFilter> DefaultCategoryFilter { get; }

		public ConfigEntry<string> SavedAstroFilters { get; }

		public ConfigEntry<string> SavedAstroItemOverrides { get; }

		public ConfigEntry<string> SavedIgnoredAstros { get; }

		public StellogisticsConfig(ConfigFile config)
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			_configFile = config;
			EnableMod = config.Bind<bool>("General", "EnableMod", true, "Enable the Stellogistics import/export panel on the Starmap.");
			IncludeOrbitalCollectors = config.Bind<bool>("Logistics", "IncludeOrbitalCollectors", true, "Include Gas Giant Orbital Collectors (Hydrogen, Deuterium, Fire Ice) in Exports.");
			StarSystemFilterMode = config.Bind<EStarFilterMode>("Logistics", "StarSystemFilterMode", EStarFilterMode.InterstellarSmart, "How to filter intra-system trade when viewing an entire Star System:\nInterstellarSmart: Excludes slots restricted to intra-system range (<1 LY) and internal supply+demand pairs that have no external star routes.\nNetOutIntraSystem: Nets total Supply against total Demand within the same star system.\nAllRemoteSlots: Shows all Remote Supply and Remote Demand slots in the star system.");
			SortOrder = config.Bind<ESortOrder>("Display", "SortOrder", ESortOrder.ShortageFirst, "How combined items are sorted in the Exports and Imports lists:\nShortageFirst: Items running empty (Exports) or starved (Imports) appear at the top.\nItemId: Sorted by DSP item ID.\nStoredAmountDesc: Sorted by highest stored amount first.");
			ShowOnHover = config.Bind<bool>("Display", "ShowOnHover", true, "Show logistics when hovering a planet or star in the Starmap even if not clicked/selected.");
			ShowInTransitBar = config.Bind<bool>("Display", "ShowInTransitBar", true, "Show a hatched bar extension on item rows indicating inbound (+ in-transit) cargo on the way.");
			CriticalThresholdPercent = config.Bind<int>("Thresholds", "CriticalThresholdPercent", 15, new ConfigDescription("Storage fullness percentage at or below which an item is highlighted Red (Critical / Empty).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			WarningThresholdPercent = config.Bind<int>("Thresholds", "WarningThresholdPercent", 40, new ConfigDescription("Storage fullness percentage at or below which an item is highlighted Orange (Low / Depleting).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 85), Array.Empty<object>()));
			ExcludeFullThresholdPercent = config.Bind<int>("Thresholds", "ExcludeFullThresholdPercent", 90, new ConfigDescription("Storage fullness percentage at or above which an item is excluded when the Exclude Full filter is enabled (90 = excludes 90%–100% including freshly tapped storages; 100 = only 100%; 41 = excludes all green >40% entries).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(40, 100), Array.Empty<object>()));
			PanelWidth = config.Bind<float>("UI", "PanelWidth", 310f, new ConfigDescription("Width of the Stellogistics panel in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(240f, 700f), Array.Empty<object>()));
			PanelMaxHeight = config.Bind<float>("UI", "PanelMaxHeight", 460f, new ConfigDescription("Maximum height of the scrollable list area in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(56f, 950f), Array.Empty<object>()));
			UseCustomPosition = config.Bind<bool>("UI", "UseCustomPosition", false, "True when the user has dragged the Stellogistics panel to a custom screen position.");
			CustomPanelPosX = config.Bind<float>("UI", "CustomPanelPosX", 82f, "Saved X anchoredPosition (from top-left) of the Stellogistics panel.");
			CustomPanelPosY = config.Bind<float>("UI", "CustomPanelPosY", -470f, "Saved Y anchoredPosition (from top-left) of the Stellogistics panel.");
			DefaultCategoryFilter = config.Bind<EItemCategoryFilter>("Filters", "DefaultCategoryFilter", EItemCategoryFilter.All, "Default item category filter for planets and star systems that do not have a custom per-body filter saved.");
			SavedAstroFilters = config.Bind<string>("Filters", "SavedAstroFilters", "", "Serialized per-star and per-planet item category filters (format: seed_astroId:mask,...).");
			SavedAstroItemOverrides = config.Bind<string>("Filters", "SavedAstroItemOverrides", "", "Serialized per-star and per-planet individual item filter overrides (format: seed_astroId:id1|id2,...).");
			SavedIgnoredAstros = config.Bind<string>("Filters", "SavedIgnoredAstros", "", "Serialized per-galaxy ignored planet and star system astroIds for the Finder (format: seed:astroId1|astroId2,...).");
			ParseSavedAstroFilters();
			ParseSavedAstroItemOverrides();
			ParseSavedIgnoredAstros();
		}

		private static string MakeAstroKey(int galaxySeed, int astroId)
		{
			return "global";
		}

		private void ParseSavedAstroFilters()
		{
			_astroFilterCache.Clear();
			string value = SavedAstroFilters.Value;
			if (string.IsNullOrEmpty(value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 2 && int.TryParse(array2[1], out var result))
				{
					_astroFilterCache[array2[0].Trim()] = (EItemCategoryFilter)(result & 0x7F);
				}
			}
		}

		private void FlushSavedAstroFilters()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, EItemCategoryFilter> item in _astroFilterCache)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append(item.Key).Append(':').Append((int)item.Value);
			}
			SavedAstroFilters.Value = stringBuilder.ToString();
			_configFile.Save();
		}

		private void ParseSavedAstroItemOverrides()
		{
			_astroItemOverridesCache.Clear();
			string value = SavedAstroItemOverrides.Value;
			if (string.IsNullOrEmpty(value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length != 2)
				{
					continue;
				}
				string key = array2[0].Trim();
				string[] array3 = array2[1].Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
				HashSet<int> hashSet = new HashSet<int>();
				for (int j = 0; j < array3.Length; j++)
				{
					if (int.TryParse(array3[j], out var result) && result > 0)
					{
						hashSet.Add(result);
					}
				}
				if (hashSet.Count > 0)
				{
					_astroItemOverridesCache[key] = hashSet;
				}
			}
		}

		private void FlushSavedAstroItemOverrides()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, HashSet<int>> item in _astroItemOverridesCache)
			{
				if (item.Value == null || item.Value.Count == 0)
				{
					continue;
				}
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append(item.Key).Append(':');
				bool flag = true;
				foreach (int item2 in item.Value)
				{
					if (!flag)
					{
						stringBuilder.Append('|');
					}
					stringBuilder.Append(item2);
					flag = false;
				}
			}
			SavedAstroItemOverrides.Value = stringBuilder.ToString();
			_configFile.Save();
		}

		public EItemCategoryFilter GetFilterForAstro(int galaxySeed, int astroId)
		{
			if (_astroFilterCache.TryGetValue("global", out var value))
			{
				return value;
			}
			return DefaultCategoryFilter.Value;
		}

		public bool GetExclude100PercentForAstro(int galaxySeed, int astroId)
		{
			return (GetFilterForAstro(galaxySeed, astroId) & EItemCategoryFilter.Exclude100Percent) != 0;
		}

		public void ToggleExclude100PercentForAstro(int galaxySeed, int astroId)
		{
			EItemCategoryFilter filterForAstro = GetFilterForAstro(galaxySeed, astroId);
			EItemCategoryFilter value = (((filterForAstro & EItemCategoryFilter.Exclude100Percent) != EItemCategoryFilter.None) ? (filterForAstro & ~EItemCategoryFilter.Exclude100Percent) : (filterForAstro | EItemCategoryFilter.Exclude100Percent));
			_astroFilterCache["global"] = value;
			DefaultCategoryFilter.Value = value;
			FlushSavedAstroFilters();
		}

		public bool HasCustomFilterForAstro(int galaxySeed, int astroId)
		{
			bool num = GetFilterForAstro(galaxySeed, astroId) != EItemCategoryFilter.All;
			HashSet<int> value;
			bool flag = _astroItemOverridesCache.TryGetValue("global", out value) && value.Count > 0;
			return num || flag;
		}

		private HashSet<int> GetOrInitHiddenItemsSet(int galaxySeed, int astroId)
		{
			if (!_astroItemOverridesCache.TryGetValue("global", out var value))
			{
				value = new HashSet<int>();
				EItemCategoryFilter eItemCategoryFilter = GetFilterForAstro(galaxySeed, astroId) & EItemCategoryFilter.All;
				if (eItemCategoryFilter != EItemCategoryFilter.All && (Object)(object)LDB.items != (Object)null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null)
				{
					ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
					foreach (ItemProto val in dataArray)
					{
						if (val != null && ((Proto)val).ID > 0)
						{
							EItemCategoryFilter eItemCategoryFilter2 = CombinedLogisticsItem.ClassifyItem(val);
							if ((eItemCategoryFilter & eItemCategoryFilter2) == 0)
							{
								value.Add(((Proto)val).ID);
							}
						}
					}
				}
				_astroItemOverridesCache["global"] = value;
			}
			return value;
		}

		public void SetFilterForAstro(int galaxySeed, int astroId, EItemCategoryFilter mask, EItemCategoryFilter? toggledCategories = null)
		{
			HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
			EItemCategoryFilter eItemCategoryFilter = GetFilterForAstro(galaxySeed, astroId) & EItemCategoryFilter.Exclude100Percent;
			EItemCategoryFilter eItemCategoryFilter2 = (mask & EItemCategoryFilter.All) | eItemCategoryFilter;
			_astroFilterCache["global"] = eItemCategoryFilter2;
			DefaultCategoryFilter.Value = eItemCategoryFilter2;
			if (toggledCategories.HasValue && (Object)(object)LDB.items != (Object)null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null)
			{
				EItemCategoryFilter value = toggledCategories.Value;
				ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
				foreach (ItemProto val in dataArray)
				{
					if (val == null || ((Proto)val).ID <= 0)
					{
						continue;
					}
					EItemCategoryFilter eItemCategoryFilter3 = CombinedLogisticsItem.ClassifyItem(val);
					if ((value & eItemCategoryFilter3) != EItemCategoryFilter.None)
					{
						if ((eItemCategoryFilter2 & eItemCategoryFilter3) != EItemCategoryFilter.None)
						{
							orInitHiddenItemsSet.Remove(((Proto)val).ID);
						}
						else
						{
							orInitHiddenItemsSet.Add(((Proto)val).ID);
						}
					}
				}
			}
			FlushSavedAstroItemOverrides();
			FlushSavedAstroFilters();
		}

		public void SetCustomItemsAllVisible(int galaxySeed, int astroId, bool visible)
		{
			HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
			if (visible)
			{
				orInitHiddenItemsSet.Clear();
			}
			else if ((Object)(object)LDB.items != (Object)null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null)
			{
				ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
				foreach (ItemProto val in dataArray)
				{
					if (val != null && ((Proto)val).ID > 0)
					{
						orInitHiddenItemsSet.Add(((Proto)val).ID);
					}
				}
			}
			FlushSavedAstroItemOverrides();
		}

		public void CopyHiddenItemsSnapshot(int galaxySeed, int astroId, HashSet<int> destination)
		{
			if (destination != null)
			{
				destination.Clear();
				HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
				destination.UnionWith(orInitHiddenItemsSet);
			}
		}

		public void RestoreHiddenItemsSnapshot(int galaxySeed, int astroId, HashSet<int> snapshot)
		{
			if (snapshot != null)
			{
				HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
				orInitHiddenItemsSet.Clear();
				orInitHiddenItemsSet.UnionWith(snapshot);
				FlushSavedAstroItemOverrides();
			}
		}

		public void SetCustomSingleItemOnly(int galaxySeed, int astroId, int itemId)
		{
			if (itemId <= 0)
			{
				return;
			}
			HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
			orInitHiddenItemsSet.Clear();
			if ((Object)(object)LDB.items != (Object)null && ((ProtoSet<ItemProto>)(object)LDB.items).dataArray != null)
			{
				ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
				foreach (ItemProto val in dataArray)
				{
					if (val != null && ((Proto)val).ID > 0 && ((Proto)val).ID != itemId)
					{
						orInitHiddenItemsSet.Add(((Proto)val).ID);
					}
				}
			}
			FlushSavedAstroItemOverrides();
		}

		public void ResetFilterForAstro(int galaxySeed, int astroId)
		{
			DefaultCategoryFilter.Value = EItemCategoryFilter.All;
			_astroFilterCache.Clear();
			_astroItemOverridesCache.Clear();
			FlushSavedAstroFilters();
			FlushSavedAstroItemOverrides();
		}

		public bool IsItemVisibleForAstro(int galaxySeed, int astroId, int itemId, EItemCategoryFilter itemCategory)
		{
			if (_astroItemOverridesCache.TryGetValue("global", out var value))
			{
				return !value.Contains(itemId);
			}
			return (GetFilterForAstro(galaxySeed, astroId) & itemCategory) != 0;
		}

		public void ToggleItemOverrideForAstro(int galaxySeed, int astroId, int itemId)
		{
			if (itemId > 0)
			{
				HashSet<int> orInitHiddenItemsSet = GetOrInitHiddenItemsSet(galaxySeed, astroId);
				if (!orInitHiddenItemsSet.Remove(itemId))
				{
					orInitHiddenItemsSet.Add(itemId);
				}
				FlushSavedAstroItemOverrides();
			}
		}

		private void ParseSavedIgnoredAstros()
		{
			_ignoredAstrosBySeed.Clear();
			string value = SavedIgnoredAstros.Value;
			if (string.IsNullOrEmpty(value))
			{
				return;
			}
			string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length != 2 || !int.TryParse(array2[0].Trim(), out var result))
				{
					continue;
				}
				string[] array3 = array2[1].Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
				HashSet<int> hashSet = new HashSet<int>();
				for (int j = 0; j < array3.Length; j++)
				{
					if (int.TryParse(array3[j], out var result2) && result2 > 0)
					{
						hashSet.Add(result2);
					}
				}
				if (hashSet.Count > 0)
				{
					_ignoredAstrosBySeed[result] = hashSet;
				}
			}
		}

		private void FlushSavedIgnoredAstros()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<int, HashSet<int>> item in _ignoredAstrosBySeed)
			{
				if (item.Value == null || item.Value.Count == 0)
				{
					continue;
				}
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(',');
				}
				stringBuilder.Append(item.Key).Append(':');
				bool flag = true;
				foreach (int item2 in item.Value)
				{
					if (!flag)
					{
						stringBuilder.Append('|');
					}
					stringBuilder.Append(item2);
					flag = false;
				}
			}
			SavedIgnoredAstros.Value = stringBuilder.ToString();
			_configFile.Save();
		}

		public bool IsAstroIgnored(int galaxySeed, int astroId)
		{
			if (astroId <= 0)
			{
				return false;
			}
			if (_ignoredAstrosBySeed.TryGetValue(galaxySeed, out var value))
			{
				return value.Contains(astroId);
			}
			return false;
		}

		public bool IsPlanetOrStarIgnored(int galaxySeed, PlanetData planet)
		{
			if (planet == null)
			{
				return false;
			}
			if (IsAstroIgnored(galaxySeed, planet.astroId))
			{
				return true;
			}
			if (planet.star != null && IsAstroIgnored(galaxySeed, planet.star.astroId))
			{
				return true;
			}
			return false;
		}

		public void ToggleAstroIgnored(int galaxySeed, int astroId)
		{
			if (astroId > 0)
			{
				if (!_ignoredAstrosBySeed.TryGetValue(galaxySeed, out var value))
				{
					value = new HashSet<int>();
					_ignoredAstrosBySeed[galaxySeed] = value;
				}
				if (!value.Remove(astroId))
				{
					value.Add(astroId);
				}
				FlushSavedIgnoredAstros();
			}
		}

		public void SetAstroIgnored(int galaxySeed, int astroId, bool ignored)
		{
			if (astroId <= 0)
			{
				return;
			}
			if (!_ignoredAstrosBySeed.TryGetValue(galaxySeed, out var value))
			{
				if (!ignored)
				{
					return;
				}
				value = new HashSet<int>();
				_ignoredAstrosBySeed[galaxySeed] = value;
			}
			if (ignored ? value.Add(astroId) : value.Remove(astroId))
			{
				FlushSavedIgnoredAstros();
			}
		}

		public void ClearAllIgnoredAstros(int galaxySeed)
		{
			if (_ignoredAstrosBySeed.Remove(galaxySeed))
			{
				FlushSavedIgnoredAstros();
			}
		}

		public int GetIgnoredAstroCount(int galaxySeed)
		{
			if (!_ignoredAstrosBySeed.TryGetValue(galaxySeed, out var value))
			{
				return 0;
			}
			return value.Count;
		}

		public void SaveCustomPanelPosition(float x, float y)
		{
			UseCustomPosition.Value = true;
			CustomPanelPosX.Value = x;
			CustomPanelPosY.Value = y;
			_configFile.Save();
		}

		public void SavePanelSize(float width, float maxHeight)
		{
			PanelWidth.Value = width;
			PanelMaxHeight.Value = maxHeight;
			_configFile.Save();
		}

		public void ResetPanelLayout()
		{
			UseCustomPosition.Value = false;
			CustomPanelPosX.Value = 82f;
			CustomPanelPosY.Value = -470f;
			PanelWidth.Value = 310f;
			PanelMaxHeight.Value = 460f;
			_configFile.Save();
		}
	}
	[BepInPlugin("com.stellogistics.dsp", "Stellogistics", "2.0.1")]
	[BepInProcess("DSPGAME.exe")]
	public class StellogisticsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.stellogistics.dsp";

		public const string PluginName = "Stellogistics";

		public const string PluginVersion = "2.0.1";

		private Harmony _harmony;

		public static ManualLogSource Log { get; private set; }

		public static StellogisticsConfig ModConfig { get; private set; }

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig = new StellogisticsConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.stellogistics.dsp");
			_harmony.PatchAll(typeof(StarmapPatches));
			Log.LogInfo((object)"Stellogistics v2.0.1 loaded.");
		}

		private void OnDestroy()
		{
			StarmapPatches.DestroyPanel();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public class PointerHoverTracker : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public bool IsHovered { get; private set; }

		public void OnPointerEnter(PointerEventData eventData)
		{
			IsHovered = true;
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			IsHovered = false;
		}

		private void OnDisable()
		{
			IsHovered = false;
		}
	}
	public class ItemCellHoverHandler : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public Action OnHoverEnter;

		public Action OnHoverExit;

		public void OnPointerEnter(PointerEventData eventData)
		{
			OnHoverEnter?.Invoke();
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			OnHoverExit?.Invoke();
		}
	}
	public class PanelDragHandler : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		public RectTransform TargetRect;

		public Action OnDragStarted;

		public Action<Vector2> OnDragFinished;

		private Canvas _canvas;

		public void OnBeginDrag(PointerEventData eventData)
		{
			if (!((Object)(object)TargetRect == (Object)null))
			{
				if ((Object)(object)_canvas == (Object)null)
				{
					_canvas = ((Component)TargetRect).GetComponentInParent<Canvas>();
				}
				OnDragStarted?.Invoke();
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)TargetRect == (Object)null))
			{
				float num = (((Object)(object)_canvas != (Object)null && _canvas.scaleFactor > 0.01f) ? _canvas.scaleFactor : 1f);
				RectTransform targetRect = TargetRect;
				targetRect.anchoredPosition += eventData.delta / num;
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)TargetRect != (Object)null)
			{
				OnDragFinished?.Invoke(TargetRect.anchoredPosition);
			}
		}
	}
	public class PanelResizeHandler : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		public RectTransform TargetRect;

		public Action OnResizeStarted;

		public Action<float, float> OnResizing;

		public Action<float, float> OnResizeFinished;

		private Vector2 _grabOffset;

		private float _lastWidth = 310f;

		private float _lastTotalHeight = 300f;

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)TargetRect == (Object)null))
			{
				Vector2 val = default(Vector2);
				Rect rect;
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(TargetRect, eventData.position, eventData.pressEventCamera, ref val))
				{
					rect = TargetRect.rect;
					float width = ((Rect)(ref rect)).width;
					rect = TargetRect.rect;
					float height = ((Rect)(ref rect)).height;
					_grabOffset = new Vector2(width - val.x, height - (0f - val.y));
				}
				else
				{
					_grabOffset = Vector2.zero;
				}
				rect = TargetRect.rect;
				_lastWidth = ((Rect)(ref rect)).width;
				rect = TargetRect.rect;
				_lastTotalHeight = ((Rect)(ref rect)).height;
				OnResizeStarted?.Invoke();
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			if (!((Object)(object)TargetRect == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle(TargetRect, eventData.position, eventData.pressEventCamera, ref val))
			{
				float num = val.x + _grabOffset.x;
				float num2 = 0f - val.y + _grabOffset.y;
				_lastWidth = Mathf.Clamp(num, 240f, 700f);
				_lastTotalHeight = Mathf.Clamp(num2, 10f, 1020f);
				OnResizing?.Invoke(_lastWidth, _lastTotalHeight);
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			OnResizeFinished?.Invoke(_lastWidth, _lastTotalHeight);
		}
	}
	public class UIStarmapLogisticsPanel : MonoBehaviour
	{
		private class ItemRowView
		{
			public GameObject RootGo;

			public RectTransform RootRect;

			public Image BgImage;

			public Button RowButton;

			public Action OnRowClick;

			public GameObject MuteBtnGo;

			public Action OnMuteClick;

			public RectTransform FillBarRect;

			public Image FillBarImage;

			public float FillRatioCached;

			public RectTransform TransitBarRect;

			public Image TransitBarImage;

			public float TransitRatioCached;

			public Image StatusStripeImage;

			public Image IconImage;

			public Text NameText;

			public Text MetaText;

			public Text AmountText;

			public Text SubStatusText;
		}

		private class PlanetFilterRowView
		{
			public GameObject RootGo;

			public RectTransform RootRect;

			public Image BgImage;

			public Button Btn;

			public Image CheckBoxBg;

			public Text CheckMarkText;

			public Text NameText;

			public Text MetaText;

			public Action OnClick;
		}

		private class GeneralToggleRow
		{
			public Func<bool> Getter;

			public Action Toggler;

			public Button Btn;

			public Image CheckBoxBg;

			public Text CheckMarkText;

			public Text LabelText;
		}

		private class FilterToggleRow
		{
			public EItemCategoryFilter Category;

			public Button Btn;

			public Image CheckBoxBg;

			public Text CheckMarkText;

			public Text LabelText;
		}

		private class CustomPickerCell
		{
			public int ItemId;

			public string ItemName;

			public EItemCategoryFilter Category;

			public int TabIndex;

			public GameObject CellGo;

			public Image BgImage;

			public Image IconImage;
		}

		private StellogisticsConfig _config;

		private UIGame _uiGame;

		private Font _gameFont;

		private RectTransform _panelRect;

		private RectTransform _headerRect;

		private Image _panelBg;

		private PointerHoverTracker _panelHoverTracker;

		private PointerHoverTracker _optionsHoverTracker;

		private PointerHoverTracker _generalOptionsHoverTracker;

		private PointerHoverTracker _customPickerHoverTracker;

		private Sprite _hatchedTransitSprite;

		private Button _panelCollapseBtn;

		private Text _panelCollapseBtnText;

		private Text _titleText;

		private Text _subtitleText;

		private Text _fleetInfoText;

		private Button _filterModeBtn;

		private Text _filterModeBtnText;

		private Button _finderModeBtn;

		private Text _finderModeBtnText;

		private Button _sortModeBtn;

		private Text _sortModeBtnText;

		private Button _optionsBtn;

		private Text _optionsBtnText;

		private Button _generalOptionsBtn;

		private Text _generalOptionsBtnText;

		private RectTransform _scrollViewportRect;

		private RectTransform _scrollContentRect;

		private ScrollRect _scrollRect;

		private GameObject _scrollbarGo;

		private Scrollbar _verticalScrollbar;

		private GameObject _resizeGripGo;

		private GameObject _emptyStateGo;

		private Text _emptyStateText;

		private GameObject _exportsHeaderGo;

		private RectTransform _exportsHeaderRect;

		private Text _exportsHeaderText;

		private Text _exportsAlertText;

		private GameObject _importsHeaderGo;

		private RectTransform _importsHeaderRect;

		private Text _importsHeaderText;

		private Text _importsAlertText;

		private GameObject _optionsMenuGo;

		private RectTransform _optionsMenuRect;

		private Text _optionsTargetLabel;

		private Text _excludeRowLabelText;

		private Text _excludeThresholdBtnText;

		private GeneralToggleRow _ignoreTargetToggleRow;

		private readonly List<FilterToggleRow> _filterToggles = new List<FilterToggleRow>();

		private GameObject _generalOptionsMenuGo;

		private RectTransform _generalOptionsMenuRect;

		private readonly List<GeneralToggleRow> _generalOptionToggles = new List<GeneralToggleRow>();

		private GameObject _customPickerGo;

		private RectTransform _customPickerRect;

		private GameObject _customPickerGridGo;

		private GameObject _customPickerPlanetsScrollGo;

		private RectTransform _customPickerPlanetsContentRect;

		private GameObject _customPickerPlanetsEmptyGo;

		private Text _customPickerTitleText;

		private Text _customPickerHoveredLabel;

		private Image _customTabItemsBg;

		private Image _customTabBuildingsBg;

		private Image _customTabPlanetsBg;

		private Text _customTabPlanetsText;

		private Button _pickerCheckAllBtn;

		private Button _pickerUncheckAllBtn;

		private Button _pickerBottlenecksBtn;

		private Text _pickerBottlenecksTxt;

		private Button _pickerShowAllPlanetsBtn;

		private int _customPickerActiveTab = 1;

		private bool _customPickerOpen;

		private readonly List<CustomPickerCell> _customPickerCells = new List<CustomPickerCell>();

		private readonly List<PlanetFilterRowView> _planetFilterRowPool = new List<PlanetFilterRowView>();

		private readonly List<PlanetLogisticsFilterEntry> _planetFilterEntries = new List<PlanetLogisticsFilterEntry>();

		private readonly HashSet<int> _storedItemsSet = new HashSet<int>();

		private readonly HashSet<int> _savedFinderHiddenSnapshot = new HashSet<int>();

		private bool _hasSavedFinderSnapshot;

		private bool _savedFinderOnlyBottlenecks = true;

		private int _lastFinderCheckedCount;

		private bool _finderOnlyBottlenecks = true;

		private readonly List<ItemRowView> _rowPool = new List<ItemRowView>();

		private UIStarmap _currentStarmap;

		private bool _finderModeActive;

		private int _lastTargetAstroId = -1;

		private int _lastGalaxySeed;

		private string _lastTargetDisplayName = "";

		private PlanetData _lastResolvedPlanet;

		private StarData _lastResolvedStar;

		private float _nextRefreshTime;

		private bool _forceRefresh = true;

		private float _activeContentHeight = 160f;

		private bool _panelCollapsed;

		private bool _exportsCollapsed;

		private bool _importsCollapsed;

		private bool _optionsMenuOpen;

		private bool _generalOptionsMenuOpen;

		private bool _isResizing;

		private static readonly Color PanelBgColor = new Color(0.055f, 0.085f, 0.13f, 0.94f);

		private static readonly Color HeaderBgColor = new Color(0.09f, 0.145f, 0.22f, 0.98f);

		private static readonly Color SectionHeaderBgColor = new Color(0.12f, 0.19f, 0.28f, 0.95f);

		private static readonly Color SectionHeaderHoverColor = new Color(0.17f, 0.27f, 0.39f, 0.98f);

		private static readonly Color RowEvenBgColor = new Color(0.08f, 0.12f, 0.18f, 0.78f);

		private static readonly Color RowOddBgColor = new Color(0.065f, 0.1f, 0.15f, 0.78f);

		private static readonly Color CriticalColor = new Color(1f, 0.34f, 0.34f, 1f);

		private static readonly Color CriticalFillColor = new Color(0.85f, 0.18f, 0.18f, 0.24f);

		private static readonly Color CriticalTransitColor = new Color(1f, 0.42f, 0.42f, 0.38f);

		private static readonly Color WarningColor = new Color(1f, 0.7f, 0.24f, 1f);

		private static readonly Color WarningFillColor = new Color(0.85f, 0.52f, 0.12f, 0.22f);

		private static readonly Color WarningTransitColor = new Color(1f, 0.72f, 0.28f, 0.36f);

		private static readonly Color HealthyColor = new Color(0.3f, 0.9f, 0.58f, 1f);

		private static readonly Color HealthyFillColor = new Color(0.18f, 0.68f, 0.42f, 0.18f);

		private static readonly Color HealthyTransitColor = new Color(0.32f, 0.92f, 0.62f, 0.34f);

		private const float HeaderHeight = 74f;

		private const float StackedHeaderHeight = 96f;

		private const float StackedWidthPlanet = 305f;

		private const float StackedWidthFiveBtns = 355f;

		private const float CollapsedTabWidth = 148f;

		private const float CollapsedTabHeight = 32f;

		private const float SectionHeaderHeight = 26f;

		private const float RowHeight = 38f;

		private const float RowSpacing = 2f;

		private const float MinScrollHeight = 56f;

		private const float ScrollbarWidth = 7f;

		public void Initialize(UIGame uiGame, StellogisticsConfig config)
		{
			_uiGame = uiGame;
			_config = config;
			if ((Object)(object)_uiGame.planetDetail != (Object)null && (Object)(object)_uiGame.planetDetail.typeText != (Object)null)
			{
				_gameFont = _uiGame.planetDetail.typeText.font;
			}
			else if ((Object)(object)_uiGame.starmap != (Object)null && (Object)(object)_uiGame.starmap.cursorViewText != (Object)null)
			{
				_gameFont = _uiGame.starmap.cursorViewText.font;
			}
			if ((Object)(object)_gameFont == (Object)null)
			{
				_gameFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			BuildUI();
			BuildOptionsMenu();
			BuildGeneralOptionsMenu();
			BuildCustomItemPicker();
		}

		private Sprite GetOrCreateHatchedTransitSprite()
		{
			//IL_001b: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_00af: 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_0070: 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)
			if ((Object)(object)_hatchedTransitSprite != (Object)null)
			{
				return _hatchedTransitSprite;
			}
			Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[256];
			for (int i = 0; i < 16; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					float num = ((((j + i) & 7) < 4) ? 1f : 0.22f);
					array[i * 16 + j] = new Color(1f, 1f, 1f, num);
				}
			}
			val.SetPixels(array);
			val.Apply();
			_hatchedTransitSprite = Sprite.Create(val, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f), 100f);
			return _hatchedTransitSprite;
		}

		public bool IsPointerOverUI()
		{
			if (!((Component)this).gameObject.activeInHierarchy)
			{
				return false;
			}
			if ((Object)(object)_panelHoverTracker != (Object)null && _panelHoverTracker.IsHovered)
			{
				return true;
			}
			if (_optionsMenuOpen && (Object)(object)_optionsHoverTracker != (Object)null && _optionsHoverTracker.IsHovered)
			{
				return true;
			}
			if (_generalOptionsMenuOpen && (Object)(object)_generalOptionsHoverTracker != (Object)null && _generalOptionsHoverTracker.IsHovered)
			{
				return true;
			}
			if (_customPickerOpen && (Object)(object)_customPickerHoverTracker != (Object)null && _customPickerHoverTracker.IsHovered)
			{
				return true;
			}
			return false;
		}

		private void BuildUI()
		{
			//IL_0040: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Expected O, but got Unknown
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: 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_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Expected O, but got Unknown
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Expected O, but got Unknown
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Expected O, but got Unknown
			//IL_053b: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0582: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Expected O, but got Unknown
			//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Expected O, but got Unknown
			//IL_0619: Unknown result type (might be due to invalid IL or missing references)
			//IL_063d: Unknown result type (might be due to invalid IL or missing references)
			//IL_065c: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Unknown result type (might be due to invalid IL or missing references)
			//IL_069a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_070c: Unknown result type (might be due to invalid IL or missing references)
			//IL_072b: Unknown result type (might be due to invalid IL or missing references)
			//IL_074a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0769: Unknown result type (might be due to invalid IL or missing references)
			//IL_0788: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d7: Expected O, but got Unknown
			//IL_0805: Unknown result type (might be due to invalid IL or missing references)
			//IL_081f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0839: Unknown result type (might be due to invalid IL or missing references)
			//IL_0853: Unknown result type (might be due to invalid IL or missing references)
			//IL_086d: Unknown result type (might be due to invalid IL or miss