Decompiled source of Planetary P2P Pairing v0.3.3

BepInEx/plugins/PlanetaryP2PPairing/PlanetaryP2PPairing.dll

Decompiled 12 hours ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace LocalPriorityPairing;

internal enum DispatchReason
{
	Local,
	LocalPointToPoint,
	Remote,
	RemotePointToPoint,
	PlanetRoute,
	StarRoute,
	Group,
	RemoteFallback
}
internal struct DispatchRecord
{
	internal long tick;

	internal int sourcePlanetId;

	internal int sourceStationId;

	internal int demandPlanetId;

	internal int demandStationId;

	internal int itemId;

	internal int itemCount;

	internal bool vessel;

	internal DispatchReason reason;
}
internal static class DispatchLog
{
	private const int Capacity = 512;

	private static readonly DispatchRecord[] records = new DispatchRecord[512];

	private static int next;

	private static int count;

	internal static void Clear()
	{
		next = 0;
		count = 0;
	}

	internal static void CaptureLocal(PlanetFactory factory, StationComponent dispatcher, StationComponent[] stationPool, int firstNewDrone)
	{
		//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_003e: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		if (factory == null || dispatcher == null || stationPool == null || firstNewDrone < 0)
		{
			return;
		}
		int num = dispatcher.workDroneCount;
		if (num > dispatcher.workDroneDatas.Length)
		{
			num = dispatcher.workDroneDatas.Length;
		}
		for (int i = firstNewDrone; i < num; i++)
		{
			DroneData val = dispatcher.workDroneDatas[i];
			StationComponent val2 = StationAt(stationPool, val.endId);
			if (val2 != null && val.itemId > 0)
			{
				LocalLogisticOrder val3 = dispatcher.workDroneOrders[i];
				bool num2 = val.itemCount > 0;
				StationComponent val4 = (num2 ? dispatcher : val2);
				StationComponent val5 = (num2 ? val2 : dispatcher);
				int itemCount = ((val.itemCount > 0) ? val.itemCount : Math.Max(Math.Abs(val3.thisOrdered), Math.Abs(val3.otherOrdered)));
				Add(new DispatchRecord
				{
					tick = GameMain.gameTick,
					sourcePlanetId = factory.planetId,
					sourceStationId = val4.id,
					demandPlanetId = factory.planetId,
					demandStationId = val5.id,
					itemId = val.itemId,
					itemCount = itemCount,
					vessel = false,
					reason = (LocalPairStore.Contains(factory.planetId, val4.id, val5.id) ? DispatchReason.LocalPointToPoint : DispatchReason.Local)
				});
			}
		}
	}

	internal static void CaptureRemote(StationComponent dispatcher, StationComponent[] stationPool, int firstNewShip, int priorityIndex)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		if (dispatcher == null || stationPool == null || firstNewShip < 0)
		{
			return;
		}
		int num = dispatcher.workShipCount;
		if (num > dispatcher.workShipDatas.Length)
		{
			num = dispatcher.workShipDatas.Length;
		}
		for (int i = firstNewShip; i < num; i++)
		{
			ShipData val = dispatcher.workShipDatas[i];
			StationComponent val2 = StationAt(stationPool, val.otherGId);
			if (val2 != null && val.itemId > 0)
			{
				RemoteLogisticOrder val3 = dispatcher.workShipOrders[i];
				bool num2 = val.itemCount > 0;
				StationComponent val4 = (num2 ? dispatcher : val2);
				StationComponent val5 = (num2 ? val2 : dispatcher);
				int itemCount = ((val.itemCount > 0) ? val.itemCount : Math.Max(Math.Abs(val3.thisOrdered), Math.Abs(val3.otherOrdered)));
				Add(new DispatchRecord
				{
					tick = GameMain.gameTick,
					sourcePlanetId = val4.planetId,
					sourceStationId = val4.id,
					demandPlanetId = val5.planetId,
					demandStationId = val5.id,
					itemId = val.itemId,
					itemCount = itemCount,
					vessel = true,
					reason = RemoteReason(priorityIndex)
				});
			}
		}
	}

	internal static void AppendForStation(StringBuilder builder, int planetId, int stationId, int maximum)
	{
		int num = 0;
		for (int i = 0; i < count; i++)
		{
			if (num >= maximum)
			{
				break;
			}
			int num2 = next - 1 - i;
			if (num2 < 0)
			{
				num2 += 512;
			}
			DispatchRecord record = records[num2];
			if (Involves(record, planetId, stationId))
			{
				builder.Append(FormatTime(record.tick)).Append("  ");
				builder.Append(record.vessel ? "Vessel" : "Drone ").Append("  ");
				builder.Append(ReasonLabel(record.reason)).Append("  ");
				builder.Append(StationName(record.sourcePlanetId, record.sourceStationId));
				builder.Append("  ->  ");
				builder.Append(StationName(record.demandPlanetId, record.demandStationId));
				builder.Append("  |  ");
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(record.itemId);
				builder.Append((val == null) ? record.itemId.ToString() : ((Proto)val).name);
				builder.Append(" x").Append(record.itemCount).AppendLine();
				num++;
			}
		}
		if (num == 0)
		{
			builder.Append("No dispatches recorded for this station yet.");
		}
	}

	private static void Add(DispatchRecord record)
	{
		records[next] = record;
		next = (next + 1) % 512;
		if (count < 512)
		{
			count++;
		}
	}

	private static bool Involves(DispatchRecord record, int planetId, int stationId)
	{
		if (record.sourcePlanetId != planetId || record.sourceStationId != stationId)
		{
			if (record.demandPlanetId == planetId)
			{
				return record.demandStationId == stationId;
			}
			return false;
		}
		return true;
	}

	private static StationComponent StationAt(StationComponent[] pool, int id)
	{
		if (id <= 0 || id >= pool.Length)
		{
			return null;
		}
		StationComponent val = pool[id];
		if (val == null || val.id <= 0)
		{
			return null;
		}
		return val;
	}

	private static DispatchReason RemoteReason(int priorityIndex)
	{
		return priorityIndex switch
		{
			1 => DispatchReason.RemotePointToPoint, 
			2 => DispatchReason.PlanetRoute, 
			3 => DispatchReason.StarRoute, 
			4 => DispatchReason.Group, 
			5 => DispatchReason.RemoteFallback, 
			_ => DispatchReason.Remote, 
		};
	}

	private static string ReasonLabel(DispatchReason reason)
	{
		return reason switch
		{
			DispatchReason.LocalPointToPoint => "Local P2P", 
			DispatchReason.RemotePointToPoint => "Remote P2P", 
			DispatchReason.PlanetRoute => "Planet route", 
			DispatchReason.StarRoute => "Star route", 
			DispatchReason.Group => "Group", 
			DispatchReason.RemoteFallback => "Remote fallback", 
			DispatchReason.Remote => "Remote", 
			_ => "Local", 
		};
	}

	private static string StationName(int planetId, int stationId)
	{
		GameData data = GameMain.data;
		PlanetFactory val = ((data == null || data.galaxy == null) ? null : data.galaxy.PlanetById(planetId))?.factory;
		if (val != null && stationId > 0 && stationId < val.transport.stationCursor)
		{
			StationComponent val2 = val.transport.stationPool[stationId];
			if (val2 != null && val2.id == stationId)
			{
				string text = val.ReadExtraInfoOnEntity(val2.entityId);
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
				return (val2.isStellar ? "ILS " : "PLS ") + planetId + "-" + stationId;
			}
		}
		return "Station " + planetId + "-" + stationId;
	}

	private static string FormatTime(long tick)
	{
		long num = tick / 60;
		long num2 = num / 3600;
		num %= 3600;
		long num3 = num / 60;
		num %= 60;
		return num2.ToString("00") + ":" + num3.ToString("00") + ":" + num.ToString("00");
	}
}
internal sealed class DispatchLogPanel : MonoBehaviour
{
	private UIStationWindow window;

	private GameObject panel;

	private RectTransform panelRect;

	private GameObject buttonObject;

	private RectTransform buttonRect;

	private RectTransform controlButtonRect;

	private Text buttonText;

	private Text content;

	private readonly StringBuilder builder = new StringBuilder(4096);

	private int lastRefreshFrame = -100;

	internal void Initialize(UIStationWindow owner)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Expected O, but got Unknown
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		window = owner;
		Font font = owner.titleText.font;
		controlButtonRect = owner.controlPanelBtnRt;
		buttonObject = CreateBox("Dispatch Log Button", ((Transform)controlButtonRect).parent, new Color(0.08f, 0.18f, 0.25f, 0.96f));
		buttonRect = (RectTransform)buttonObject.transform;
		PositionButton();
		Button obj = buttonObject.AddComponent<Button>();
		((Selectable)obj).targetGraphic = (Graphic)(object)buttonObject.GetComponent<Image>();
		((UnityEvent)obj.onClick).AddListener(new UnityAction(Toggle));
		buttonText = CreateText("Label", (Transform)(object)buttonRect, font, 14, (TextAnchor)4);
		buttonText.text = "Dispatch Log";
		panel = CreateBox("Dispatch Log Panel", (Transform)(object)owner.windowTrans, new Color(0.025f, 0.055f, 0.075f, 0.97f));
		panelRect = (RectTransform)panel.transform;
		PositionPanel();
		Text obj2 = CreateText("Header", (Transform)(object)panelRect, font, 16, (TextAnchor)0);
		RectTransform rectTransform = ((Graphic)obj2).rectTransform;
		rectTransform.anchorMin = new Vector2(0f, 1f);
		rectTransform.anchorMax = new Vector2(1f, 1f);
		rectTransform.pivot = new Vector2(0.5f, 1f);
		rectTransform.offsetMin = new Vector2(14f, -34f);
		rectTransform.offsetMax = new Vector2(-14f, -7f);
		obj2.text = "Dispatch history (newest first)";
		content = CreateText("Content", (Transform)(object)panelRect, font, 13, (TextAnchor)0);
		RectTransform rectTransform2 = ((Graphic)content).rectTransform;
		rectTransform2.anchorMin = Vector2.zero;
		rectTransform2.anchorMax = Vector2.one;
		rectTransform2.offsetMin = new Vector2(14f, 12f);
		rectTransform2.offsetMax = new Vector2(-14f, -40f);
		content.horizontalOverflow = (HorizontalWrapMode)0;
		content.verticalOverflow = (VerticalWrapMode)0;
		panel.SetActive(false);
	}

	internal void RefreshPanel()
	{
		if (!((Object)(object)window == (Object)null) && !((Object)(object)buttonObject == (Object)null))
		{
			PositionButton();
			PositionPanel();
			StationComponent val = CurrentStation();
			bool flag = val != null && !val.isCollector && !val.isVeinCollector;
			buttonObject.SetActive(flag);
			if (!flag)
			{
				panel.SetActive(false);
			}
			else if (panel.activeSelf && Time.frameCount - lastRefreshFrame >= 20)
			{
				lastRefreshFrame = Time.frameCount;
				builder.Length = 0;
				DispatchLog.AppendForStation(builder, val.planetId, val.id, 18);
				content.text = builder.ToString();
			}
		}
	}

	internal void HidePanel()
	{
		if ((Object)(object)panel != (Object)null)
		{
			panel.SetActive(false);
		}
		if ((Object)(object)buttonText != (Object)null)
		{
			buttonText.text = "Dispatch Log";
		}
	}

	private void Toggle()
	{
		bool flag = !panel.activeSelf;
		panel.SetActive(flag);
		panel.transform.SetAsLastSibling();
		buttonObject.transform.SetAsLastSibling();
		buttonText.text = (flag ? "Close Log" : "Dispatch Log");
		lastRefreshFrame = -100;
		RefreshPanel();
	}

	private void PositionButton()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		buttonRect.anchorMin = controlButtonRect.anchorMin;
		buttonRect.anchorMax = controlButtonRect.anchorMax;
		buttonRect.pivot = controlButtonRect.pivot;
		RectTransform obj = buttonRect;
		float x = controlButtonRect.anchoredPosition.x;
		Rect rect = controlButtonRect.rect;
		obj.anchoredPosition = new Vector2(x + ((Rect)(ref rect)).width + 8f, controlButtonRect.anchoredPosition.y);
		RectTransform obj2 = buttonRect;
		rect = controlButtonRect.rect;
		obj2.sizeDelta = new Vector2(116f, ((Rect)(ref rect)).height);
	}

	private void PositionPanel()
	{
		//IL_0010: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		panelRect.anchorMin = new Vector2(1f, 0f);
		panelRect.anchorMax = new Vector2(1f, 1f);
		panelRect.pivot = new Vector2(0f, 0.5f);
		panelRect.anchoredPosition = new Vector2(12f, 0f);
		RectTransform obj = panelRect;
		Rect rect = window.windowTrans.rect;
		obj.sizeDelta = new Vector2(Mathf.Max(520f, ((Rect)(ref rect)).width), -24f);
	}

	private StationComponent CurrentStation()
	{
		int stationId = window.stationId;
		PlanetTransport transport = window.transport;
		if (transport == null || stationId <= 0 || stationId >= transport.stationCursor)
		{
			return null;
		}
		StationComponent val = transport.stationPool[stationId];
		if (val == null || val.id != stationId)
		{
			return null;
		}
		return val;
	}

	private static GameObject CreateBox(string name, Transform parent, Color color)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val.transform.SetParent(parent, false);
		((Graphic)val.GetComponent<Image>()).color = color;
		return val;
	}

	private static Text CreateText(string name, Transform parent, Font font, int fontSize, TextAnchor alignment)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(Text)
		});
		val.transform.SetParent(parent, false);
		RectTransform val2 = (RectTransform)val.transform;
		val2.anchorMin = Vector2.zero;
		val2.anchorMax = Vector2.one;
		val2.offsetMin = Vector2.zero;
		val2.offsetMax = Vector2.zero;
		Text component = val.GetComponent<Text>();
		component.font = font;
		component.fontSize = fontSize;
		component.alignment = alignment;
		((Graphic)component).color = Color.white;
		((Graphic)component).raycastTarget = false;
		return component;
	}
}
[HarmonyPatch(typeof(StationComponent), "DetermineDispatch")]
internal static class RemoteDispatchLogPatch
{
	private static void Prefix(StationComponent __instance, out int __state)
	{
		__state = __instance.workShipCount;
	}

	private static void Postfix(StationComponent __instance, StationComponent[] gStationPool, int priorityIndex, int __state)
	{
		if (__instance.workShipCount > __state)
		{
			DispatchLog.CaptureRemote(__instance, gStationPool, __state, priorityIndex);
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "_OnCreate")]
internal static class DispatchLogWindowCreatePatch
{
	private static void Postfix(UIStationWindow __instance)
	{
		if ((Object)(object)((Component)__instance).GetComponent<DispatchLogPanel>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<DispatchLogPanel>().Initialize(__instance);
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "_OnUpdate")]
internal static class DispatchLogWindowUpdatePatch
{
	private static void Postfix(UIStationWindow __instance)
	{
		DispatchLogPanel component = ((Component)__instance).GetComponent<DispatchLogPanel>();
		if ((Object)(object)component != (Object)null)
		{
			component.RefreshPanel();
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "_OnClose")]
internal static class DispatchLogWindowClosePatch
{
	private static void Postfix(UIStationWindow __instance)
	{
		DispatchLogPanel component = ((Component)__instance).GetComponent<DispatchLogPanel>();
		if ((Object)(object)component != (Object)null)
		{
			component.HidePanel();
		}
	}
}
internal struct LocalPairViewState
{
	internal bool changed;

	internal SupplyDemandPair[] pairs;

	internal int count;

	internal int workDroneCount;
}
[HarmonyPatch(typeof(PlanetTransport), "RefreshStationTraffic")]
internal static class RefreshStationTrafficPatch
{
	private static void Postfix(PlanetTransport __instance)
	{
		StationComponent[] stationPool = __instance.stationPool;
		for (int i = 1; i < __instance.stationCursor; i++)
		{
			StationComponent val = stationPool[i];
			if (val != null && val.id == i)
			{
				LocalPairStore.SortPriorityPairs(__instance.planet.id, val);
			}
		}
	}
}
[HarmonyPatch(typeof(StationComponent), "InternalTickLocal")]
internal static class InternalTickLocalPatch
{
	private static void Prefix(StationComponent __instance, PlanetFactory factory, int droneCarries, StationComponent[] stationPool, out LocalPairViewState __state)
	{
		__state = default(LocalPairViewState);
		__state.workDroneCount = __instance.workDroneCount;
		LocalPairStore.BeginPriorityDispatch(factory.planetId, __instance);
		if (LocalPairStore.TryBuildPriorityView(factory.planetId, __instance, stationPool, droneCarries, out var pairs, out var count))
		{
			__state.changed = true;
			__state.pairs = __instance.localPairs;
			__state.count = __instance.localPairCount;
			__instance.localPairs = pairs;
			__instance.localPairCount = count;
			__instance.localPairProcess = ((count > 0) ? (__instance.localPairProcess % count) : 0);
		}
	}

	private static Exception Finalizer(StationComponent __instance, PlanetFactory factory, StationComponent[] stationPool, LocalPairViewState __state, Exception __exception)
	{
		if (__exception == null && __instance.workDroneCount > __state.workDroneCount)
		{
			DispatchLog.CaptureLocal(factory, __instance, stationPool, __state.workDroneCount);
		}
		if (__state.changed)
		{
			int localPairProcess = __instance.localPairProcess;
			__instance.localPairs = __state.pairs;
			__instance.localPairCount = __state.count;
			__instance.localPairProcess = ((__state.count > 0) ? (localPairProcess % __state.count) : 0);
		}
		return __exception;
	}
}
[HarmonyPatch(typeof(PlanetTransport), "RemoveStationComponent")]
internal static class RemoveStationComponentPatch
{
	private static void Prefix(PlanetTransport __instance, int id)
	{
		LocalPairStore.RemoveStation(__instance.planet.id, id);
	}
}
internal static class LocalPairStore
{
	private const int SaveVersion = 1;

	private static readonly Dictionary<int, HashSet<long>> pairsByPlanet = new Dictionary<int, HashSet<long>>();

	private static readonly Dictionary<long, int> priorityPairCounts = new Dictionary<long, int>();

	private static readonly ConcurrentDictionary<long, SupplyDemandPair[]> filteredPairBuffers = new ConcurrentDictionary<long, SupplyDemandPair[]>();

	private static ManualLogSource logger;

	internal static void SetLogger(ManualLogSource source)
	{
		logger = source;
	}

	internal static void Add(int planetId, int stationA, int stationB)
	{
		if (ValidEndpoints(planetId, stationA, stationB))
		{
			if (!pairsByPlanet.TryGetValue(planetId, out var value))
			{
				value = new HashSet<long>();
				pairsByPlanet.Add(planetId, value);
			}
			if (value.Add(PairKey(stationA, stationB)))
			{
				RefreshPlanet(planetId);
			}
		}
	}

	internal static void Remove(int planetId, int stationA, int stationB)
	{
		if (pairsByPlanet.TryGetValue(planetId, out var value) && value.Remove(PairKey(stationA, stationB)))
		{
			if (value.Count == 0)
			{
				pairsByPlanet.Remove(planetId);
			}
			RefreshPlanet(planetId);
		}
	}

	internal static void RemoveStation(int planetId, int stationId)
	{
		if (!pairsByPlanet.TryGetValue(planetId, out var value))
		{
			return;
		}
		bool flag = false;
		List<long> list = null;
		foreach (long item in value)
		{
			if (First(item) == stationId || Second(item) == stationId)
			{
				if (list == null)
				{
					list = new List<long>();
				}
				list.Add(item);
			}
		}
		if (list != null)
		{
			for (int i = 0; i < list.Count; i++)
			{
				flag |= value.Remove(list[i]);
			}
		}
		if (value.Count == 0)
		{
			pairsByPlanet.Remove(planetId);
		}
		if (flag)
		{
			RefreshPlanet(planetId);
		}
	}

	internal static IEnumerable<int> Partners(int planetId, int stationId)
	{
		if (!pairsByPlanet.TryGetValue(planetId, out var value))
		{
			yield break;
		}
		foreach (long item in value)
		{
			if (First(item) == stationId)
			{
				yield return Second(item);
			}
			else if (Second(item) == stationId)
			{
				yield return First(item);
			}
		}
	}

	internal static int PartnerCount(int planetId, int stationId)
	{
		int num = 0;
		foreach (int item in Partners(planetId, stationId))
		{
			_ = item;
			num++;
		}
		return num;
	}

	internal static bool Contains(int planetId, int stationA, int stationB)
	{
		return IsPriorityPair(planetId, stationA, stationB);
	}

	internal static void SortPriorityPairs(int planetId, StationComponent station)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		if (station.localPairCount <= 0 || station.localPairs == null)
		{
			priorityPairCounts.Remove(StationKey(planetId, station.id));
			return;
		}
		int localPairCount = station.localPairCount;
		SupplyDemandPair[] array = (SupplyDemandPair[])(object)new SupplyDemandPair[localPairCount];
		int num = 0;
		for (int i = 0; i < localPairCount; i++)
		{
			SupplyDemandPair val = station.localPairs[i];
			if (IsPriorityPair(planetId, val.supplyId, val.demandId))
			{
				array[num++] = val;
			}
		}
		if (num == 0)
		{
			priorityPairCounts.Remove(StationKey(planetId, station.id));
			return;
		}
		int num2 = num;
		for (int j = 0; j < localPairCount; j++)
		{
			SupplyDemandPair val2 = station.localPairs[j];
			if (!IsPriorityPair(planetId, val2.supplyId, val2.demandId))
			{
				array[num2++] = val2;
			}
		}
		Array.Copy(array, station.localPairs, localPairCount);
		station.localPairProcess = 0;
		long key = StationKey(planetId, station.id);
		priorityPairCounts[key] = num;
	}

	internal static void BeginPriorityDispatch(int planetId, StationComponent station)
	{
		long key = StationKey(planetId, station.id);
		if (priorityPairCounts.TryGetValue(key, out var value) && value > 0)
		{
			station.localPairProcess %= value;
		}
	}

	internal static bool TryBuildPriorityView(int planetId, StationComponent station, StationComponent[] stationPool, int droneCarries, out SupplyDemandPair[] pairs, out int count)
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		pairs = null;
		count = 0;
		if (station.localPairs == null || station.localPairCount <= 0 || !pairsByPlanet.TryGetValue(planetId, out var value) || value.Count == 0)
		{
			return false;
		}
		long key = StationKey(planetId, station.id);
		if (!filteredPairBuffers.TryGetValue(key, out var value2) || value2.Length < station.localPairCount)
		{
			value2 = (SupplyDemandPair[])(object)new SupplyDemandPair[station.localPairCount];
			filteredPairBuffers[key] = value2;
		}
		int num = 0;
		for (int i = 0; i < station.localPairCount; i++)
		{
			SupplyDemandPair val = station.localPairs[i];
			if (value.Contains(PairKey(val.supplyId, val.demandId)) || !HasUsablePriorityAlternative(value, val, stationPool, droneCarries))
			{
				value2[num++] = val;
			}
		}
		if (num == station.localPairCount)
		{
			return false;
		}
		pairs = value2;
		count = num;
		return true;
	}

	internal static bool TryRefreshAllPlanets()
	{
		GameData data = GameMain.data;
		if (data == null || data.galaxy == null || data.factories == null || data.factoryCount <= 0)
		{
			return false;
		}
		for (int i = 0; i < data.factoryCount; i++)
		{
			PlanetFactory val = data.factories[i];
			if (val != null)
			{
				val.transport.RefreshStationTraffic(0);
			}
		}
		return true;
	}

	internal static void Clear()
	{
		pairsByPlanet.Clear();
		priorityPairCounts.Clear();
		filteredPairBuffers.Clear();
	}

	internal static void Export(BinaryWriter writer)
	{
		writer.Write(1);
		int num = 0;
		foreach (KeyValuePair<int, HashSet<long>> item in pairsByPlanet)
		{
			num += item.Value.Count;
		}
		writer.Write(num);
		foreach (KeyValuePair<int, HashSet<long>> item2 in pairsByPlanet)
		{
			foreach (long item3 in item2.Value)
			{
				writer.Write(item2.Key);
				writer.Write(First(item3));
				writer.Write(Second(item3));
			}
		}
	}

	internal static void Import(BinaryReader reader)
	{
		Clear();
		int num = reader.ReadInt32();
		if (num != 1)
		{
			logger.LogWarning((object)("Ignoring unsupported local priority pairing save data version " + num + "."));
			return;
		}
		int num2 = reader.ReadInt32();
		for (int i = 0; i < num2; i++)
		{
			int num3 = reader.ReadInt32();
			int stationA = reader.ReadInt32();
			int stationB = reader.ReadInt32();
			if (ValidEndpoints(num3, stationA, stationB))
			{
				if (!pairsByPlanet.TryGetValue(num3, out var value))
				{
					value = new HashSet<long>();
					pairsByPlanet.Add(num3, value);
				}
				value.Add(PairKey(stationA, stationB));
			}
		}
	}

	private static bool ValidEndpoints(int planetId, int stationA, int stationB)
	{
		if (planetId > 0 && stationA > 0 && stationB > 0)
		{
			return stationA != stationB;
		}
		return false;
	}

	private static bool IsPriorityPair(int planetId, int stationA, int stationB)
	{
		if (pairsByPlanet.TryGetValue(planetId, out var value))
		{
			return value.Contains(PairKey(stationA, stationB));
		}
		return false;
	}

	private static bool HasUsablePriorityAlternative(HashSet<long> configuredPairs, SupplyDemandPair ordinaryPair, StationComponent[] stationPool, int droneCarries)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		StationComponent val = StationAt(stationPool, ordinaryPair.supplyId);
		StationComponent val2 = StationAt(stationPool, ordinaryPair.demandId);
		if (val == null || val2 == null || ordinaryPair.supplyIndex < 0 || ordinaryPair.supplyIndex >= val.storage.Length || ordinaryPair.demandIndex < 0 || ordinaryPair.demandIndex >= val2.storage.Length)
		{
			return false;
		}
		int itemId = val.storage[ordinaryPair.supplyIndex].itemId;
		if (itemId <= 0 || val2.storage[ordinaryPair.demandIndex].itemId != itemId)
		{
			return false;
		}
		foreach (long configuredPair in configuredPairs)
		{
			int num = First(configuredPair);
			int num2 = Second(configuredPair);
			int num3 = ((num == val2.id) ? num2 : ((num2 == val2.id) ? num : 0));
			if (num3 != val.id)
			{
				StationComponent val3 = ((num3 > 0) ? StationAt(stationPool, num3) : null);
				if (val3 != null && CanSupplyItem(val3, val2, ordinaryPair.demandIndex, itemId, droneCarries))
				{
					return true;
				}
			}
		}
		foreach (long configuredPair2 in configuredPairs)
		{
			int num4 = First(configuredPair2);
			int num5 = Second(configuredPair2);
			int num6 = ((num4 == val.id) ? num5 : ((num5 == val.id) ? num4 : 0));
			if (num6 != val2.id)
			{
				StationComponent val4 = ((num6 > 0) ? StationAt(stationPool, num6) : null);
				if (val4 != null && CanReceiveItem(val, ordinaryPair.supplyIndex, val4, itemId, droneCarries))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool CanSupplyItem(StationComponent supply, StationComponent demand, int demandIndex, int itemId, int droneCarries)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//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_003d: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Invalid comparison between Unknown and I4
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		StationStore val = demand.storage[demandIndex];
		if ((int)val.localLogic != 2 || ((StationStore)(ref val)).localDemandCount <= 0 || ((StationStore)(ref val)).totalDemandCount <= 0)
		{
			return false;
		}
		for (int i = 0; i < supply.storage.Length; i++)
		{
			StationStore val2 = supply.storage[i];
			if (val2.itemId == itemId && (int)val2.localLogic == 1 && HasDispatchableSupply(val2, supply, demand, droneCarries))
			{
				return true;
			}
		}
		return false;
	}

	private static bool CanReceiveItem(StationComponent supply, int supplyIndex, StationComponent demand, int itemId, int droneCarries)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Invalid comparison between Unknown and I4
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		StationStore val = supply.storage[supplyIndex];
		if ((int)val.localLogic != 1)
		{
			return false;
		}
		for (int i = 0; i < demand.storage.Length; i++)
		{
			StationStore val2 = demand.storage[i];
			if (val2.itemId == itemId && (int)val2.localLogic == 2 && ((StationStore)(ref val2)).localDemandCount > 0 && ((StationStore)(ref val2)).totalDemandCount > 0 && HasDispatchableSupply(val, supply, demand, droneCarries))
			{
				return true;
			}
		}
		return false;
	}

	private static bool HasDispatchableSupply(StationStore supplyStore, StationComponent supply, StationComponent demand, int droneCarries)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (((StationStore)(ref supplyStore)).localSupplyCount <= 0 || ((StationStore)(ref supplyStore)).totalSupplyCount <= 0)
		{
			return false;
		}
		if (!CanEndpointDispatch(supply, supplyStore, supply, demand, droneCarries))
		{
			return CanEndpointDispatch(demand, supplyStore, supply, demand, droneCarries);
		}
		return true;
	}

	private static bool CanEndpointDispatch(StationComponent dispatcher, StationStore supplyStore, StationComponent supply, StationComponent demand, int droneCarries)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		if (dispatcher.idleDroneCount <= 0 || dispatcher.energy <= 800000 || !CanDispatchTrip(dispatcher, supply, demand))
		{
			return false;
		}
		int num = (droneCarries - 1) * dispatcher.deliveryDrones / 100;
		if (supplyStore.max <= num)
		{
			num = supplyStore.max - 1;
			if (num < 0)
			{
				num = 0;
			}
		}
		if (supplyStore.count > num && ((StationStore)(ref supplyStore)).localSupplyCount > num)
		{
			return ((StationStore)(ref supplyStore)).totalSupplyCount > num;
		}
		return false;
	}

	private static bool CanDispatchTrip(StationComponent dispatcher, StationComponent supply, StationComponent demand)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		Vector3 droneDock = supply.droneDock;
		Vector3 droneDock2 = demand.droneDock;
		double num = Math.Sqrt(droneDock.x * droneDock.x + droneDock.y * droneDock.y + droneDock.z * droneDock.z);
		double num2 = Math.Sqrt(droneDock2.x * droneDock2.x + droneDock2.y * droneDock2.y + droneDock2.z * droneDock2.z);
		if (num <= 0.0 || num2 <= 0.0)
		{
			return false;
		}
		double num3 = (double)(droneDock.x * droneDock2.x + droneDock.y * droneDock2.y + droneDock.z * droneDock2.z) / (num * num2);
		if (num3 < -1.0)
		{
			num3 = -1.0;
		}
		else if (num3 > 1.0)
		{
			num3 = 1.0;
		}
		if (num3 < dispatcher.tripRangeDrones - 1E-06)
		{
			return false;
		}
		double num4 = (num + num2) * 0.5 * Math.Acos(num3);
		return dispatcher.energy >= (long)(num4 * 20000.0 * 2.0 + 800000.0);
	}

	private static StationComponent StationAt(StationComponent[] stationPool, int stationId)
	{
		if (stationPool == null || stationId <= 0 || stationId >= stationPool.Length)
		{
			return null;
		}
		StationComponent val = stationPool[stationId];
		if (val == null || val.id != stationId)
		{
			return null;
		}
		return val;
	}

	private static long PairKey(int stationA, int stationB)
	{
		return PairingKey.Pair(stationA, stationB);
	}

	private static long StationKey(int planetId, int stationId)
	{
		return PairingKey.Station(planetId, stationId);
	}

	private static int First(long pair)
	{
		return (int)(pair >> 32);
	}

	private static int Second(long pair)
	{
		return (int)pair;
	}

	private static void RefreshPlanet(int planetId)
	{
		GameData data = GameMain.data;
		PlanetData val = ((data == null) ? null : data.galaxy.PlanetById(planetId));
		if (val != null && val.factory != null)
		{
			val.factory.transport.RefreshStationTraffic(0);
		}
	}
}
internal static class PairingKey
{
	internal static long Pair(int stationA, int stationB)
	{
		if (stationA > stationB)
		{
			int num = stationA;
			stationA = stationB;
			stationB = num;
		}
		return ((long)stationA << 32) | (uint)stationB;
	}

	internal static long Station(int planetId, int stationId)
	{
		return ((long)planetId << 32) | (uint)stationId;
	}
}
[BepInPlugin("samox.dsp.local-priority-pairing", "Planetary P2P Pairing", "0.3.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[ModSaveSettings]
public sealed class Plugin : BaseUnityPlugin, IModCanSave
{
	internal const string GUID = "samox.dsp.local-priority-pairing";

	internal const string NAME = "Planetary P2P Pairing";

	internal const string VERSION = "0.3.3";

	private Harmony harmony;

	private bool refreshPending;

	private void Awake()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		LocalPairStore.SetLogger(((BaseUnityPlugin)this).Logger);
		harmony = new Harmony("samox.dsp.local-priority-pairing");
		harmony.PatchAll(typeof(Plugin).Assembly);
	}

	private void Start()
	{
		DSPModSavePlugin.AddModSaveManually((BaseUnityPlugin)(object)this);
	}

	private void Update()
	{
		if (refreshPending && LocalPairStore.TryRefreshAllPlanets())
		{
			refreshPending = false;
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	public void Export(BinaryWriter writer)
	{
		LocalPairStore.Export(writer);
	}

	public void Import(BinaryReader reader)
	{
		DispatchLog.Clear();
		LocalPairStore.Import(reader);
		refreshPending = true;
	}

	public void IntoOtherSave()
	{
		refreshPending = false;
		DispatchLog.Clear();
		LocalPairStore.Clear();
	}
}
internal sealed class LocalPairStationIcon : MonoBehaviour
{
	internal Image image;
}
internal static class LocalPriorityUi
{
	private static readonly FieldInfo TabIndexField = AccessTools.Field(typeof(UIStationWindow), "tabIndex");

	private static readonly FieldInfo StationPairCountField = AccessTools.Field(typeof(UIStationWindow), "s2sCount");

	private static readonly FieldInfo EntriesField = AccessTools.Field(typeof(UIStationRoutePanel), "entries");

	private static readonly FieldInfo SearchEntriesField = AccessTools.Field(typeof(UIStationRoutePanel), "searchEntries");

	private static readonly FieldInfo ActiveEntryCountField = AccessTools.Field(typeof(UIStationRoutePanel), "activeEntryCount");

	private static readonly FieldInfo ActiveSearchEntryCountField = AccessTools.Field(typeof(UIStationRoutePanel), "activeSearchEntryCount");

	private static readonly FieldInfo AddGidsField = AccessTools.Field(typeof(UIStationRoutePanel), "addGids");

	private static readonly FieldInfo AddRouteModeField = AccessTools.Field(typeof(UIStationRoutePanel), "addRouteMode");

	internal static bool IsPriorityTab(UIStationWindow window)
	{
		return (int)TabIndexField.GetValue(window) == 1;
	}

	internal static int VanillaStationPairCount(UIStationWindow window)
	{
		return (int)StationPairCountField.GetValue(window);
	}

	internal static bool IsLocalRoutePanel(UIStationRoutePanel panel)
	{
		if (panel.station != null && panel.station.id > 0)
		{
			return !panel.station.isStellar;
		}
		return false;
	}

	internal static List<UIStationRouteEntry> Entries(UIStationRoutePanel panel)
	{
		return (List<UIStationRouteEntry>)EntriesField.GetValue(panel);
	}

	internal static List<UIStationRouteSearchEntry> SearchEntries(UIStationRoutePanel panel)
	{
		return (List<UIStationRouteSearchEntry>)SearchEntriesField.GetValue(panel);
	}

	internal static void SetActiveEntryCount(UIStationRoutePanel panel, int count)
	{
		ActiveEntryCountField.SetValue(panel, count);
	}

	internal static int ActiveEntryCount(UIStationRoutePanel panel)
	{
		return (int)ActiveEntryCountField.GetValue(panel);
	}

	internal static void SetActiveSearchEntryCount(UIStationRoutePanel panel, int count)
	{
		ActiveSearchEntryCountField.SetValue(panel, count);
	}

	internal static int ActiveSearchEntryCount(UIStationRoutePanel panel)
	{
		return (int)ActiveSearchEntryCountField.GetValue(panel);
	}

	internal static List<int> AddGids(UIStationRoutePanel panel)
	{
		return (List<int>)AddGidsField.GetValue(panel);
	}

	internal static void EndAddRouteMode(UIStationRoutePanel panel)
	{
		AddRouteModeField.SetValue(panel, false);
	}

	internal static PlanetFactory ResolveLocalFactory(UIStationRoutePanel panel)
	{
		StationComponent station = panel.station;
		GameData data = GameMain.data;
		if (station == null || data == null)
		{
			return null;
		}
		PlanetData val = ((station.planetId > 0) ? data.galaxy.PlanetById(station.planetId) : null);
		if (ContainsStation(val?.factory, station))
		{
			return val.factory;
		}
		PlanetData localPlanet = GameMain.localPlanet;
		if (ContainsStation(localPlanet?.factory, station))
		{
			station.planetId = localPlanet.id;
			return localPlanet.factory;
		}
		return null;
	}

	internal static bool IsLocalCandidate(StationComponent candidate, StationComponent source, int poolIndex)
	{
		if (candidate != null && candidate.id == poolIndex && candidate.id != source.id && !candidate.isCollector)
		{
			return !candidate.isVeinCollector;
		}
		return false;
	}

	private static bool ContainsStation(PlanetFactory factory, StationComponent station)
	{
		if (factory == null || factory.transport == null || station.id <= 0 || station.id >= factory.transport.stationCursor)
		{
			return false;
		}
		return factory.transport.stationPool[station.id] == station;
	}

	internal static StationComponent FindLocalStation(UIStationRoutePanel panel, int stationId)
	{
		PlanetFactory val = ResolveLocalFactory(panel);
		if (val == null)
		{
			return null;
		}
		PlanetTransport transport = val.transport;
		if (stationId <= 0 || stationId >= transport.stationCursor)
		{
			return null;
		}
		StationComponent val2 = transport.stationPool[stationId];
		if (val2 == null || val2.id != stationId)
		{
			return null;
		}
		val2.planetId = val.planetId;
		return val2;
	}

	internal static Sprite StationIcon(UIStationRoutePanel panel, StationComponent station)
	{
		PlanetFactory val = ResolveLocalFactory(panel);
		if (val == null || station == null || station.entityId <= 0 || station.entityId >= val.entityPool.Length)
		{
			return null;
		}
		ref EntityData reference = ref val.entityPool[station.entityId];
		if (reference.id != station.entityId)
		{
			return null;
		}
		ItemProto val2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)reference.protoId);
		if (val2 != null)
		{
			return val2.iconSprite;
		}
		return null;
	}
}
[HarmonyPatch(typeof(UIStationRoutePanel), "Refresh")]
internal static class LocalRoutePanelRefreshPatch
{
	private static bool Prefix(UIStationRoutePanel __instance)
	{
		if (__instance.station == null || __instance.station.isStellar)
		{
			return true;
		}
		if (LocalPriorityUi.ResolveLocalFactory(__instance) == null)
		{
			((ManualBehaviour)__instance)._Close();
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(UIStationWindow), "RefreshTabs")]
internal static class StationWindowRefreshTabsPatch
{
	private static void Postfix(UIStationWindow __instance, StationComponent station)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (station.isStellar || station.isCollector || station.isVeinCollector)
		{
			return;
		}
		((Component)__instance.prioritySettingTabBtn).gameObject.SetActive(true);
		__instance.controlPanelBtnRt.anchoredPosition = new Vector2(276f, __instance.controlPanelBtnRt.anchoredPosition.y);
		if (LocalPriorityUi.IsPriorityTab(__instance))
		{
			((Component)__instance.priorityGroup).gameObject.SetActive(true);
			((Component)__instance.a2aSettingBtn).gameObject.SetActive(false);
			((Component)__instance.a2aSettingRightBtn).gameObject.SetActive(false);
			((Component)__instance.groupSettingRightBtn).gameObject.SetActive(false);
			((Component)__instance.a2aMatchedCountText).gameObject.SetActive(false);
			((Component)__instance.groupMatchedCountText).gameObject.SetActive(false);
			((Component)__instance.behaviorComboBox).gameObject.SetActive(false);
			for (int i = 0; i < __instance.groupBtns.Length; i++)
			{
				((Component)__instance.groupBtns[i]).gameObject.SetActive(false);
			}
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "RefreshTrans")]
internal static class StationWindowRefreshTransPatch
{
	private static void Postfix(UIStationWindow __instance, StationComponent station)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if (!station.isStellar && !station.isCollector && !station.isVeinCollector && LocalPriorityUi.IsPriorityTab(__instance))
		{
			__instance.windowTrans.sizeDelta = new Vector2(__instance.windowTrans.sizeDelta.x, __instance.windowTrans.sizeDelta.y + 94f);
			__instance.panelDownTrans.anchoredPosition = new Vector2(__instance.panelDownTrans.anchoredPosition.x, __instance.panelDownTrans.anchoredPosition.y + 94f);
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "UpdatePriorityGroup")]
internal static class StationWindowUpdatePriorityGroupPatch
{
	private static void Postfix(UIStationWindow __instance, StationComponent station)
	{
		if (LocalPriorityUi.IsPriorityTab(__instance))
		{
			int num = LocalPairStore.PartnerCount(station.planetId, station.id);
			if (station.isStellar)
			{
				__instance.s2sMatchedCountText.text = (LocalPriorityUi.VanillaStationPairCount(__instance) + num).ToString();
				return;
			}
			__instance.s2sMatchedCountText.text = num.ToString();
			__instance.s2sSettingTipText.text = "Local priority pairing";
			((Selectable)__instance.s2sSettingBtn.button).interactable = !string.IsNullOrEmpty(__instance.factory.ReadExtraInfoOnEntity(station.entityId)) || num > 0;
			((Component)__instance.s2sSettingRightBtn).gameObject.SetActive(false);
		}
	}
}
[HarmonyPatch(typeof(UIStationWindow), "OnStation2StationSettingButtonClick")]
internal static class OpenLocalPriorityPanelPatch
{
	private static bool Prefix(UIStationWindow __instance)
	{
		PlanetTransport transport = __instance.transport;
		StationComponent val = ((transport == null || __instance.factory == null) ? null : transport.stationPool[GetStationId(__instance)]);
		if (val == null || val.isStellar)
		{
			return true;
		}
		if (string.IsNullOrEmpty(__instance.factory.ReadExtraInfoOnEntity(val.entityId)) && LocalPairStore.PartnerCount(val.planetId, val.id) == 0)
		{
			return false;
		}
		__instance.uiRoutePanel.station = val;
		LocalPriorityUi.ResolveLocalFactory(__instance.uiRoutePanel);
		((ManualBehaviour)__instance.uiRoutePanel)._Open();
		__instance.uiRoutePanel.routeMode = 0;
		return false;
	}

	private static int GetStationId(UIStationWindow window)
	{
		return (int)AccessTools.Field(typeof(UIStationWindow), "_stationId").GetValue(window);
	}
}
[HarmonyPatch(typeof(UIStationRoutePanel), "OnSearchNameInputChanged")]
internal static class LocalRoutePanelAutocompletePatch
{
	private static bool Prefix(UIStationRoutePanel __instance, string str)
	{
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		if (!LocalPriorityUi.IsLocalRoutePanel(__instance))
		{
			return true;
		}
		List<UIStationRouteSearchEntry> list = LocalPriorityUi.SearchEntries(__instance);
		int num = 0;
		if (!string.IsNullOrEmpty(str))
		{
			((Component)__instance.searchDropDownRt).gameObject.SetActive(true);
			Transform parent = ((Component)__instance.searchEntryPrefab).transform.parent;
			PlanetFactory val = LocalPriorityUi.ResolveLocalFactory(__instance);
			PlanetTransport val2 = val?.transport;
			if (val2 != null)
			{
				for (int i = 1; i < val2.stationCursor; i++)
				{
					StationComponent val3 = val2.stationPool[i];
					if (!LocalPriorityUi.IsLocalCandidate(val3, __instance.station, i))
					{
						continue;
					}
					string text = val.ReadExtraInfoOnEntity(val3.entityId);
					if (!string.IsNullOrEmpty(text) && text.IndexOf(str) >= 0 && !ContainsName(list, num, text))
					{
						if (list.Count <= num)
						{
							list.Add(null);
						}
						if ((Object)(object)list[num] == (Object)null)
						{
							list[num] = Object.Instantiate<UIStationRouteSearchEntry>(__instance.searchEntryPrefab, parent);
							((ManualBehaviour)list[num])._Create();
						}
						RectTransform rt = list[num].rt;
						float num2 = -num;
						Rect rect = __instance.searchEntryPrefab.rt.rect;
						rt.anchoredPosition = new Vector2(0f, num2 * ((Rect)(ref rect)).height);
						((ManualBehaviour)list[num])._Init((object)null);
						((ManualBehaviour)list[num])._Open();
						list[num].realName = text;
						list[num].SetName(str);
						num++;
					}
				}
			}
			for (int j = num; j < list.Count; j++)
			{
				if ((Object)(object)list[j] != (Object)null)
				{
					((ManualBehaviour)list[j])._Close();
				}
			}
		}
		else
		{
			((Component)__instance.searchDropDownRt).gameObject.SetActive(false);
			for (int k = 0; k < list.Count; k++)
			{
				if ((Object)(object)list[k] != (Object)null)
				{
					((ManualBehaviour)list[k])._Close();
				}
			}
		}
		LocalPriorityUi.SetActiveSearchEntryCount(__instance, num);
		return false;
	}

	private static void Postfix(UIStationRoutePanel __instance, string str)
	{
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.station == null || !__instance.station.isStellar || string.IsNullOrEmpty(str))
		{
			return;
		}
		List<UIStationRouteSearchEntry> list = LocalPriorityUi.SearchEntries(__instance);
		int num = LocalPriorityUi.ActiveSearchEntryCount(__instance);
		Transform parent = ((Component)__instance.searchEntryPrefab).transform.parent;
		PlanetFactory val = LocalPriorityUi.ResolveLocalFactory(__instance);
		PlanetTransport val2 = val?.transport;
		if (val2 != null)
		{
			for (int i = 1; i < val2.stationCursor; i++)
			{
				StationComponent val3 = val2.stationPool[i];
				if (!LocalPriorityUi.IsLocalCandidate(val3, __instance.station, i))
				{
					continue;
				}
				string text = val.ReadExtraInfoOnEntity(val3.entityId);
				if (!string.IsNullOrEmpty(text) && text.IndexOf(str) >= 0 && !ContainsName(list, num, text))
				{
					if (list.Count <= num)
					{
						list.Add(null);
					}
					if ((Object)(object)list[num] == (Object)null)
					{
						list[num] = Object.Instantiate<UIStationRouteSearchEntry>(__instance.searchEntryPrefab, parent);
						((ManualBehaviour)list[num])._Create();
					}
					RectTransform rt = list[num].rt;
					float num2 = -num;
					Rect rect = __instance.searchEntryPrefab.rt.rect;
					rt.anchoredPosition = new Vector2(0f, num2 * ((Rect)(ref rect)).height);
					((ManualBehaviour)list[num])._Init((object)null);
					((ManualBehaviour)list[num])._Open();
					list[num].realName = text;
					list[num].SetName(str);
					num++;
				}
			}
		}
		for (int j = num; j < list.Count; j++)
		{
			if ((Object)(object)list[j] != (Object)null)
			{
				((ManualBehaviour)list[j])._Close();
			}
		}
		LocalPriorityUi.SetActiveSearchEntryCount(__instance, num);
	}

	private static bool ContainsName(List<UIStationRouteSearchEntry> entries, int active, string name)
	{
		for (int i = 0; i < active; i++)
		{
			if ((Object)(object)entries[i] != (Object)null && entries[i].realName == name)
			{
				return true;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(UIStationRoutePanel), "RefreshEntries")]
internal static class LocalRoutePanelEntriesPatch
{
	private static bool Prefix(UIStationRoutePanel __instance)
	{
		if (!LocalPriorityUi.IsLocalRoutePanel(__instance))
		{
			return true;
		}
		List<UIStationRouteEntry> list = LocalPriorityUi.Entries(__instance);
		int num = 0;
		Transform parent = ((Component)__instance.entryPrefab).transform.parent;
		foreach (int item in LocalPairStore.Partners(__instance.station.planetId, __instance.station.id))
		{
			StationComponent val = LocalPriorityUi.FindLocalStation(__instance, item);
			if (val != null)
			{
				if (list.Count <= num)
				{
					list.Add(null);
				}
				if ((Object)(object)list[num] == (Object)null)
				{
					list[num] = Object.Instantiate<UIStationRouteEntry>(__instance.entryPrefab, parent);
					((ManualBehaviour)list[num])._Create();
				}
				((ManualBehaviour)list[num])._Init((object)GameMain.data);
				((ManualBehaviour)list[num])._Open();
				list[num].otherStation = val;
				list[num].distance = 0.0;
				num++;
			}
		}
		for (int i = num; i < list.Count; i++)
		{
			((ManualBehaviour)list[i])._Close();
		}
		LocalPriorityUi.SetActiveEntryCount(__instance, num);
		return false;
	}

	private static void Postfix(UIStationRoutePanel __instance)
	{
		if (__instance.station == null || !__instance.station.isStellar || __instance.routeMode != 0)
		{
			return;
		}
		List<UIStationRouteEntry> list = LocalPriorityUi.Entries(__instance);
		int num = LocalPriorityUi.ActiveEntryCount(__instance);
		Transform parent = ((Component)__instance.entryPrefab).transform.parent;
		foreach (int item in LocalPairStore.Partners(__instance.station.planetId, __instance.station.id))
		{
			StationComponent val = LocalPriorityUi.FindLocalStation(__instance, item);
			if (val != null)
			{
				if (list.Count <= num)
				{
					list.Add(null);
				}
				if ((Object)(object)list[num] == (Object)null)
				{
					list[num] = Object.Instantiate<UIStationRouteEntry>(__instance.entryPrefab, parent);
					((ManualBehaviour)list[num])._Create();
				}
				((ManualBehaviour)list[num])._Init((object)GameMain.data);
				((ManualBehaviour)list[num])._Open();
				list[num].otherStation = val;
				list[num].distance = 0.0;
				num++;
			}
		}
		for (int i = num; i < list.Count; i++)
		{
			((ManualBehaviour)list[i])._Close();
		}
		LocalPriorityUi.SetActiveEntryCount(__instance, num);
	}
}
[HarmonyPatch(typeof(UIStationRoutePanel), "RefreshSearchEntries")]
internal static class LocalRoutePanelSearchPatch
{
	private static bool Prefix(UIStationRoutePanel __instance)
	{
		if (!LocalPriorityUi.IsLocalRoutePanel(__instance))
		{
			return true;
		}
		List<int> list = LocalPriorityUi.AddGids(__instance);
		list.Clear();
		string text = __instance.searchNameInputField.text;
		if (!string.IsNullOrEmpty(text))
		{
			PlanetFactory val = LocalPriorityUi.ResolveLocalFactory(__instance);
			PlanetTransport val2 = val?.transport;
			if (val2 == null)
			{
				__instance.RefreshAddEntry();
				return false;
			}
			for (int i = 1; i < val2.stationCursor; i++)
			{
				StationComponent val3 = val2.stationPool[i];
				if (LocalPriorityUi.IsLocalCandidate(val3, __instance.station, i) && val.ReadExtraInfoOnEntity(val3.entityId) == text)
				{
					list.Add(val3.id);
				}
			}
		}
		__instance.RefreshAddEntry();
		return false;
	}

	private static void Postfix(UIStationRoutePanel __instance)
	{
		if (__instance.station == null || !__instance.station.isStellar)
		{
			return;
		}
		string text = __instance.searchNameInputField.text;
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		List<int> list = LocalPriorityUi.AddGids(__instance);
		PlanetFactory val = LocalPriorityUi.ResolveLocalFactory(__instance);
		PlanetTransport val2 = val?.transport;
		if (val2 != null)
		{
			for (int i = 1; i < val2.stationCursor; i++)
			{
				StationComponent val3 = val2.stationPool[i];
				if (LocalPriorityUi.IsLocalCandidate(val3, __instance.station, i) && val.ReadExtraInfoOnEntity(val3.entityId) == text)
				{
					list.Add(-val3.id);
				}
			}
		}
		__instance.RefreshAddEntry();
	}
}
[HarmonyPatch(typeof(UIStationRoutePanel), "OnAddRouteConfirmButtonClick")]
internal static class AddLocalRoutePatch
{
	private static bool Prefix(UIStationRoutePanel __instance)
	{
		List<int> list = LocalPriorityUi.AddGids(__instance);
		if (!LocalPriorityUi.IsLocalRoutePanel(__instance) && !ContainsLocalMatch(list))
		{
			return true;
		}
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i] < 0)
			{
				LocalPairStore.Add(__instance.station.planetId, __instance.station.id, -list[i]);
			}
			else if (__instance.station.isStellar)
			{
				GameMain.data.galacticTransport.AddStation2StationRoute(__instance.station.gid, list[i]);
			}
			else
			{
				LocalPairStore.Add(__instance.station.planetId, __instance.station.id, list[i]);
			}
		}
		LocalPriorityUi.EndAddRouteMode(__instance);
		__instance.RefreshEntries();
		return false;
	}

	private static bool ContainsLocalMatch(List<int> matches)
	{
		for (int i = 0; i < matches.Count; i++)
		{
			if (matches[i] < 0)
			{
				return true;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(UIStationRouteEntry), "OnDeleteButtonClick")]
internal static class DeleteLocalRoutePatch
{
	private static bool Prefix(UIStationRouteEntry __instance)
	{
		UIStationRoutePanel stationRoutePanel = __instance.stationRoutePanel;
		if ((Object)(object)stationRoutePanel == (Object)null || stationRoutePanel.station == null || __instance.otherStation == null)
		{
			return true;
		}
		if (__instance.otherStation.planetId == stationRoutePanel.station.planetId && LocalPairStore.Contains(stationRoutePanel.station.planetId, stationRoutePanel.station.id, __instance.otherStation.id))
		{
			LocalPairStore.Remove(stationRoutePanel.station.planetId, stationRoutePanel.station.id, __instance.otherStation.id);
			stationRoutePanel.RefreshEntries();
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(UIStationRouteEntry), "Refresh")]
internal static class LocalRouteEntryLabelPatch
{
	private static void Postfix(UIStationRouteEntry __instance)
	{
		UIStationRoutePanel stationRoutePanel = __instance.stationRoutePanel;
		bool num = (Object)(object)stationRoutePanel != (Object)null && stationRoutePanel.station != null && __instance.otherStation != null && __instance.otherStation.planetId == stationRoutePanel.station.planetId && LocalPairStore.Contains(stationRoutePanel.station.planetId, stationRoutePanel.station.id, __instance.otherStation.id);
		LocalPairStationIcon localPairStationIcon = ((Component)__instance).GetComponent<LocalPairStationIcon>();
		if (num)
		{
			__instance.distanceText.text = "Local priority";
			Sprite val = LocalPriorityUi.StationIcon(stationRoutePanel, __instance.otherStation);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)localPairStationIcon == (Object)null)
				{
					localPairStationIcon = CreateStationIcon(__instance);
				}
				localPairStationIcon.image.sprite = val;
				((Component)localPairStationIcon.image).gameObject.SetActive(true);
			}
			else if ((Object)(object)localPairStationIcon != (Object)null)
			{
				((Component)localPairStationIcon.image).gameObject.SetActive(false);
			}
		}
		else if ((Object)(object)localPairStationIcon != (Object)null)
		{
			((Component)localPairStationIcon.image).gameObject.SetActive(false);
		}
	}

	private static LocalPairStationIcon CreateStationIcon(UIStationRouteEntry entry)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		LocalPairStationIcon localPairStationIcon = ((Component)entry).gameObject.AddComponent<LocalPairStationIcon>();
		RectTransform rectTransform = ((Graphic)entry.nameText).rectTransform;
		rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x + 34f, rectTransform.anchoredPosition.y);
		rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x - 34f, rectTransform.sizeDelta.y);
		GameObject val = new GameObject("Local Priority Pair Station Icon", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		RectTransform val2 = (RectTransform)val.transform;
		((Transform)val2).SetParent((Transform)(object)rectTransform, false);
		val2.anchorMin = new Vector2(0f, 0.5f);
		val2.anchorMax = new Vector2(0f, 0.5f);
		val2.pivot = new Vector2(1f, 0.5f);
		val2.anchoredPosition = new Vector2(-6f, 0f);
		val2.sizeDelta = new Vector2(28f, 28f);
		localPairStationIcon.image = val.GetComponent<Image>();
		localPairStationIcon.image.preserveAspect = true;
		((Graphic)localPairStationIcon.image).raycastTarget = false;
		return localPairStationIcon;
	}
}