Decompiled source of LogisticsArchitect v0.1.7

LogisticsArchitect.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: InternalsVisibleTo("LogisticsArchitect.Tests")]
[assembly: AssemblyTitle("Logistics Architect")]
[assembly: AssemblyCompany("Loki Moon Labs")]
[assembly: AssemblyProduct("Logistics Architect")]
[assembly: AssemblyVersion("0.1.6.0")]
namespace LokiMoonLabs.LogisticsArchitect;

internal sealed class ApplyJob
{
	public readonly PlanetFactory Factory;

	public readonly PresetSnapshot Preset;

	public readonly ICarrierStock Inventory;

	public readonly ApplyResult Result = new ApplyResult();

	public int Cursor = 1;

	private readonly int singleId;

	private readonly object expected;

	private readonly int expectedEntity;

	public ApplyJob(PlanetFactory factory, PresetSnapshot preset, ICarrierStock inventory, int id = 0, object expected = null)
	{
		Factory = factory;
		Preset = preset;
		Inventory = inventory;
		singleId = id;
		this.expected = expected;
		StationComponent val = (StationComponent)((expected is StationComponent) ? expected : null);
		DispenserComponent val2 = (DispenserComponent)((expected is DispenserComponent) ? expected : null);
		BattleBaseComponent val3 = (BattleBaseComponent)((expected is BattleBaseComponent) ? expected : null);
		expectedEntity = val?.entityId ?? val2?.entityId ?? val3?.entityId ?? 0;
	}

	public bool Step()
	{
		if (Factory == null)
		{
			return true;
		}
		int num = ((singleId > 0) ? singleId : Cursor++);
		if (singleId > 0 && Cursor++ > 1)
		{
			return true;
		}
		if (Preset.Kind == Facility.Distributors)
		{
			PlanetTransport transport = Factory.transport;
			if (transport == null || transport.dispenserPool == null || num >= Math.Min(transport.dispenserCursor, transport.dispenserPool.Length))
			{
				return true;
			}
			DispenserComponent val = transport.dispenserPool[num];
			if (val != null && val.id == num && (expected == null || (object.ReferenceEquals(expected, val) && val.entityId == expectedEntity)))
			{
				StationService.Dispenser(Factory, val, Preset, Inventory, Result);
			}
		}
		else if (Preset.Kind == Facility.BattleBases)
		{
			DefenseSystem defenseSystem = Factory.defenseSystem;
			if (defenseSystem == null || defenseSystem.battleBases == null || defenseSystem.battleBases.buffer == null || num >= Math.Min(defenseSystem.battleBases.cursor, defenseSystem.battleBases.buffer.Length))
			{
				return true;
			}
			BattleBaseComponent val2 = defenseSystem.battleBases.buffer[num];
			if (val2 != null && val2.id == num && (expected == null || (object.ReferenceEquals(expected, val2) && val2.entityId == expectedEntity)))
			{
				StationService.BattleBase(Factory, val2, Preset, Result);
			}
		}
		else
		{
			PlanetTransport transport2 = Factory.transport;
			if (transport2 == null || transport2.stationPool == null || num >= Math.Min(transport2.stationCursor, transport2.stationPool.Length))
			{
				return true;
			}
			StationComponent val3 = transport2.stationPool[num];
			if (val3 != null && val3.id == num && StationService.Matches(val3, Preset.Kind) && (expected == null || (object.ReferenceEquals(expected, val3) && val3.entityId == expectedEntity)))
			{
				StationService.Station(Factory, val3, Preset, Inventory, Result);
			}
		}
		return singleId > 0;
	}
}
internal sealed class ApplyQueue
{
	private readonly Queue<ApplyJob> jobs = new Queue<ApplyJob>();

	private GameData data;

	public string Status = "Ready. Apply buttons affect matching facilities on the current planet.";

	public int Pending => jobs.Count;

	public int Revision { get; private set; }

	public void Enqueue(GameData game, ApplyJob job)
	{
		if (!object.ReferenceEquals(data, game))
		{
			jobs.Clear();
			data = game;
		}
		jobs.Enqueue(job);
		Status = "Applying settings…";
	}

	public void Clear()
	{
		jobs.Clear();
		Status = "No pending changes.";
	}

	public void Tick(GameData game)
	{
		if (!object.ReferenceEquals(data, game))
		{
			Clear();
			data = game;
			return;
		}
		long timestamp = Stopwatch.GetTimestamp();
		int num = 0;
		while (jobs.Count > 0 && num++ < 64 && ((num & 7) != 0 || Stopwatch.GetTimestamp() - timestamp <= Stopwatch.Frequency / 2000))
		{
			ApplyJob applyJob = jobs.Peek();
			try
			{
				int changed = applyJob.Result.Changed;
				bool flag = applyJob.Step();
				if (applyJob.Result.Changed != changed)
				{
					Revision++;
				}
				if (flag)
				{
					jobs.Dequeue();
					Status = applyJob.Result.Summary();
				}
			}
			catch (Exception ex)
			{
				jobs.Dequeue();
				Status = "Apply stopped for one job: " + ex.Message;
			}
		}
	}
}
internal sealed class ArchitectWindow : IDisposable
{
	private sealed class Editor
	{
		public string Value;

		public string Min;

		public string Max;

		public string Step;

		public Editor(Setting s)
		{
			Value = Number(s.Value.Value);
			Min = Number(s.Minimum.Value);
			Max = Number(s.Maximum.Value);
			Step = Number(s.Step.Value);
		}
	}

	private const float ApplyButtonWidth = 100f;

	private readonly Plugin plugin;

	private readonly Dictionary<Setting, Editor> editors = new Dictionary<Setting, Editor>();

	private Rect rect = new Rect(80f, 65f, 1000f, 720f);

	private Vector2 scroll;

	private bool ranges;

	private int blockedThrough = -1;

	private bool pointerHeld;

	private bool keyboardFocused;

	private GameObject shield;

	private RectTransform shieldRect;

	private Texture2D dark;

	private Texture2D button;

	private Texture2D field;

	private Texture2D accent;

	private Texture2D logo;

	private GUIStyle panelStyle;

	private GUIStyle buttonStyle;

	private GUIStyle fieldStyle;

	private GUIStyle headingStyle;

	private GUIStyle labelStyle;

	private GUIStyle sliderStyle;

	private GUIStyle thumbStyle;

	public bool Visible { get; private set; }

	private float Scale => Mathf.Clamp((float)Screen.height / 1080f, 0.65f, 1.4f);

	private bool ShieldActive
	{
		get
		{
			if (!Visible)
			{
				return Time.frameCount <= blockedThrough;
			}
			return true;
		}
	}

	public bool KeyboardBlocking
	{
		get
		{
			if (Visible)
			{
				return keyboardFocused;
			}
			return false;
		}
	}

	public bool Blocking
	{
		get
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!ShieldActive)
			{
				return false;
			}
			Vector3 mousePosition = Input.mousePosition;
			float scale = Scale;
			bool overWindow = ((Rect)(ref rect)).Contains(new Vector2(mousePosition.x / scale, ((float)Screen.height - mousePosition.y) / scale));
			return InputPolicy.Block(Visible, overWindow, pointerHeld, keyboardFocused, Time.frameCount <= blockedThrough);
		}
	}

	public ArchitectWindow(Plugin plugin)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		this.plugin = plugin;
		foreach (Preset preset in plugin.Settings.Presets)
		{
			foreach (Setting setting in preset.Settings)
			{
				editors.Add(setting, new Editor(setting));
			}
		}
	}

	public void Toggle()
	{
		if (Visible)
		{
			Close();
		}
		else
		{
			Visible = true;
		}
	}

	public void Close()
	{
		Visible = false;
		pointerHeld = (keyboardFocused = false);
		blockedThrough = Time.frameCount + 1;
		GUIUtility.keyboardControl = 0;
	}

	public void UpdateShield()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		if (ShieldActive && (Object)(object)shield == (Object)null)
		{
			shield = new GameObject("Logistics Architect modal input shield", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(GraphicRaycaster)
			});
			Object.DontDestroyOnLoad((Object)(object)shield);
			Canvas component = shield.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32760;
			GameObject val = new GameObject("Window-only raycast blocker", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(shield.transform, false);
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = Color.clear;
			((Graphic)component2).raycastTarget = true;
			shieldRect = val.GetComponent<RectTransform>();
			RectTransform obj = shieldRect;
			RectTransform obj2 = shieldRect;
			Vector2 val2 = (shieldRect.pivot = new Vector2(0f, 1f));
			Vector2 anchorMin = (obj2.anchorMax = val2);
			obj.anchorMin = anchorMin;
		}
		if ((Object)(object)shield != (Object)null && shield.activeSelf != ShieldActive)
		{
			shield.SetActive(ShieldActive);
		}
		if ((Object)(object)shieldRect != (Object)null)
		{
			float scale = Scale;
			shieldRect.anchoredPosition = new Vector2(((Rect)(ref rect)).x * scale, (0f - ((Rect)(ref rect)).y) * scale);
			shieldRect.sizeDelta = new Vector2(((Rect)(ref rect)).width * scale, ((Rect)(ref rect)).height * scale);
		}
	}

	private static string Number(double value)
	{
		return value.ToString("0.########", CultureInfo.InvariantCulture);
	}

	private static bool Parse(string text, out double value)
	{
		if (double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
		{
			return Setting.Finite(value);
		}
		return false;
	}

	private static Texture2D Solid(Color color)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Expected O, but got Unknown
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
		val.SetPixel(0, 0, color);
		val.Apply();
		return val;
	}

	private static void Background(GUIStyle style, Texture2D texture)
	{
		//IL_0088: 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_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_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		GUIStyleState normal = style.normal;
		GUIStyleState hover = style.hover;
		GUIStyleState active = style.active;
		Texture2D val = (style.focused.background = texture);
		Texture2D val3 = (active.background = val);
		Texture2D background = (hover.background = val3);
		normal.background = background;
		GUIStyleState onNormal = style.onNormal;
		GUIStyleState onHover = style.onHover;
		GUIStyleState onActive = style.onActive;
		Texture2D val6 = (style.onFocused.background = texture);
		Texture2D val8 = (onActive.background = val6);
		Texture2D background2 = (onHover.background = val8);
		onNormal.background = background2;
		GUIStyleState normal2 = style.normal;
		GUIStyleState hover2 = style.hover;
		GUIStyleState active2 = style.active;
		Color val11 = (style.focused.textColor = Color.white);
		Color val12 = (active2.textColor = val11);
		Color textColor = (hover2.textColor = val12);
		normal2.textColor = textColor;
		GUIStyleState onNormal2 = style.onNormal;
		GUIStyleState onHover2 = style.onHover;
		GUIStyleState onActive2 = style.onActive;
		Color val15 = (style.onFocused.textColor = Color.white);
		Color val16 = (onActive2.textColor = val15);
		Color textColor2 = (onHover2.textColor = val16);
		onNormal2.textColor = textColor2;
	}

	private void Styles()
	{
		//IL_001e: 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_0066: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Expected O, but got Unknown
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Expected O, but got Unknown
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Expected O, but got Unknown
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Expected O, but got Unknown
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Expected O, but got Unknown
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Expected O, but got Unknown
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Expected O, but got Unknown
		if (panelStyle == null)
		{
			dark = Solid(new Color(0.045f, 0.065f, 0.11f, 1f));
			button = Solid(new Color(0.13f, 0.18f, 0.27f, 1f));
			field = Solid(new Color(0.08f, 0.1f, 0.15f, 1f));
			accent = Solid(new Color(0.35f, 0.75f, 0.85f, 1f));
			panelStyle = new GUIStyle(GUI.skin.window);
			panelStyle.padding = new RectOffset(18, 18, 26, 16);
			Background(panelStyle, dark);
			buttonStyle = new GUIStyle(GUI.skin.button);
			buttonStyle.fontSize = 15;
			buttonStyle.padding = new RectOffset(8, 8, 6, 6);
			Background(buttonStyle, button);
			fieldStyle = new GUIStyle(GUI.skin.textField);
			fieldStyle.fontSize = 15;
			fieldStyle.padding = new RectOffset(5, 5, 5, 5);
			Background(fieldStyle, field);
			labelStyle = new GUIStyle(GUI.skin.label);
			labelStyle.fontSize = 15;
			labelStyle.normal.textColor = Color.white;
			headingStyle = new GUIStyle(labelStyle);
			headingStyle.fontSize = 18;
			headingStyle.fontStyle = (FontStyle)1;
			sliderStyle = new GUIStyle(GUI.skin.horizontalSlider);
			Background(sliderStyle, button);
			thumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb);
			Background(thumbStyle, accent);
			thumbStyle.fixedWidth = 14f;
			thumbStyle.fixedHeight = 18f;
			logo = Branding.LoadIcon();
		}
	}

	public void Draw()
	{
		//IL_01fe: 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_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_003d: 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_004c: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Expected O, but got Unknown
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Invalid comparison between Unknown and I4
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Invalid comparison between Unknown and I4
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Invalid comparison between Unknown and I4
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Invalid comparison between Unknown and I4
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Invalid comparison between Unknown and I4
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Invalid comparison between Unknown and I4
		if (!Visible)
		{
			return;
		}
		Styles();
		Matrix4x4 matrix = GUI.matrix;
		Color color = GUI.color;
		Color backgroundColor = GUI.backgroundColor;
		int depth = GUI.depth;
		float scale = Scale;
		try
		{
			GUI.matrix = Matrix4x4.Scale(new Vector3(scale, scale, 1f));
			GUI.color = (GUI.backgroundColor = Color.white);
			GUI.depth = -10000;
			((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Mathf.Max(0f, (float)Screen.width / scale - ((Rect)(ref rect)).width));
			((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Mathf.Max(0f, (float)Screen.height / scale - ((Rect)(ref rect)).height));
			Event current = Event.current;
			bool flag = ((Rect)(ref rect)).Contains(current.mousePosition);
			bool flag2 = pointerHeld;
			if ((int)current.rawType == 0)
			{
				if (flag)
				{
					pointerHeld = true;
				}
				else
				{
					GUIUtility.keyboardControl = 0;
					keyboardFocused = false;
				}
			}
			rect = GUILayout.Window(19471353, rect, new WindowFunction(Contents), "Logistics Architect — Loki Moon Labs", panelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
			keyboardFocused = Visible && GUI.GetNameOfFocusedControl().StartsWith("LA.", StringComparison.Ordinal);
			if ((int)current.rawType == 1)
			{
				pointerHeld = false;
			}
			UpdateShield();
			bool flag3 = (int)current.type == 0 || (int)current.type == 1 || (int)current.type == 3 || (int)current.type == 6;
			bool flag4 = (int)current.type == 4 || (int)current.type == 5;
			if ((flag3 && (flag || flag2 || pointerHeld)) || (flag4 && keyboardFocused))
			{
				current.Use();
			}
		}
		finally
		{
			GUI.matrix = matrix;
			GUI.color = color;
			GUI.backgroundColor = backgroundColor;
			GUI.depth = depth;
		}
	}

	private void Contents(int id)
	{
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		if ((Object)(object)logo != (Object)null)
		{
			GUILayout.Label((Texture)(object)logo, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(54f),
				GUILayout.Height(54f)
			});
		}
		GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label("Station auto-configuration", headingStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label("Apply affects the current planet. Changing presets or slider limits alone does not change existing buildings.", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.EndVertical();
		if (GUILayout.Button("Close", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) }))
		{
			Close();
		}
		GUILayout.EndHorizontal();
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		bool flag = GUILayout.Toggle(plugin.Settings.Enabled.Value, "Enable Logistics Architect", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(215f) });
		if (flag != plugin.Settings.Enabled.Value)
		{
			plugin.Settings.Enabled.Value = flag;
			plugin.Dirty();
		}
		bool flag2 = GUILayout.Toggle(plugin.Settings.FillCarriers.Value, "Fill carriers from inventory", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) });
		if (flag2 != plugin.Settings.FillCarriers.Value)
		{
			plugin.Settings.FillCarriers.Value = flag2;
			plugin.Dirty();
		}
		ranges = GUILayout.Toggle(ranges, "Edit slider limits (min / max / step)", (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.EndHorizontal();
		GUILayout.Label(plugin.Status, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) });
		scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(535f) });
		foreach (Preset preset in plugin.Settings.Presets)
		{
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.Label(preset.Name, headingStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(510f) });
			bool flag3 = GUILayout.Toggle(preset.OnBuild.Value, "Configure new buildings", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			if (flag3 != preset.OnBuild.Value)
			{
				preset.OnBuild.Value = flag3;
				plugin.Dirty();
			}
			GUILayout.FlexibleSpace();
			bool enabled = GUI.enabled;
			GUI.enabled = plugin.CanApply;
			if (GUILayout.Button("Apply All", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }) && CommitAll(preset))
			{
				plugin.Apply(preset, null);
			}
			GUI.enabled = enabled;
			GUILayout.EndHorizontal();
			foreach (Setting setting in preset.Settings)
			{
				Row(preset, setting);
			}
		}
		GUILayout.EndScrollView();
		GUILayout.Label("Open with the Loki Moon Labs minimap icon  •  Esc closes  •  Carrier targets respect modded building capacities.", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUI.DragWindow(new Rect(0f, 0f, 880f, 25f));
	}

	private bool CommitAll(Preset preset)
	{
		foreach (Setting setting in preset.Settings)
		{
			if (!setting.Boolean && (!Parse(editors[setting].Value, out var value) || !setting.ValidValue(value)))
			{
				plugin.Message("Invalid value for " + setting.Label + ". Allowed: " + Number(setting.HardMin) + " to " + Number(setting.HardMax) + ".");
				return false;
			}
		}
		foreach (Setting setting2 in preset.Settings)
		{
			if (!setting2.Boolean)
			{
				Parse(editors[setting2].Value, out var value2);
				setting2.SetValue(value2);
			}
		}
		plugin.Dirty();
		return true;
	}

	private void Row(Preset preset, Setting setting)
	{
		Editor editor = editors[setting];
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		GUILayout.Label(setting.Label, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
		if (setting.Boolean)
		{
			bool flag = GUILayout.Toggle(setting.Value.Value != 0.0, "Enabled", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(395f) });
			if (flag != (setting.Value.Value != 0.0))
			{
				setting.SetValue(flag ? 1 : 0);
				plugin.Dirty();
			}
		}
		else
		{
			GUI.changed = false;
			float num = GUILayout.HorizontalSlider((float)setting.Normalize(), 0f, 1f, sliderStyle, thumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(225f) });
			if (GUI.changed)
			{
				setting.SetValue(setting.FromSlider(num));
				editor.Value = Number(setting.Value.Value);
				plugin.Dirty();
			}
			GUI.SetNextControlName(string.Concat("LA.", preset.Kind, ".", setting.Key));
			editor.Value = GUILayout.TextField(editor.Value, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
			GUILayout.Label(setting.Unit, labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(65f) });
		}
		GUILayout.FlexibleSpace();
		bool enabled = GUI.enabled;
		GUI.enabled = plugin.CanApply;
		if (GUILayout.Button("Apply", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
		{
			if (setting.Boolean || (Parse(editor.Value, out var value) && setting.SetValue(value)))
			{
				plugin.Dirty();
				plugin.Apply(preset, setting.Key);
			}
			else
			{
				plugin.Message("Invalid " + setting.Label + ": allowed " + Number(setting.HardMin) + " to " + Number(setting.HardMax) + ".");
			}
		}
		GUI.enabled = enabled;
		GUILayout.EndHorizontal();
		if (!ranges || setting.Boolean)
		{
			return;
		}
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Space(28f);
		GUILayout.Label("Min", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(35f) });
		GUI.SetNextControlName(string.Concat("LA.", preset.Kind, ".", setting.Key, ".Min"));
		editor.Min = GUILayout.TextField(editor.Min, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
		GUILayout.Label("Max", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(35f) });
		GUI.SetNextControlName(string.Concat("LA.", preset.Kind, ".", setting.Key, ".Max"));
		editor.Max = GUILayout.TextField(editor.Max, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
		GUILayout.Label("Step", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
		GUI.SetNextControlName(string.Concat("LA.", preset.Kind, ".", setting.Key, ".Step"));
		editor.Step = GUILayout.TextField(editor.Step, fieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(105f) });
		if (GUILayout.Button("Save range", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
		{
			if (Parse(editor.Min, out var value2) && Parse(editor.Max, out var value3) && Parse(editor.Step, out var value4) && setting.SetRange(value2, value3, value4))
			{
				plugin.Dirty();
				plugin.Message("Slider range saved. Preset and existing facilities were not changed.");
			}
			else
			{
				plugin.Message("Invalid range: use finite minimum < maximum, a positive step, and the setting's physical bounds.");
			}
		}
		GUILayout.EndHorizontal();
	}

	public void Dispose()
	{
		if ((Object)(object)shield != (Object)null)
		{
			Object.Destroy((Object)(object)shield);
		}
		Texture2D[] array = (Texture2D[])(object)new Texture2D[5] { dark, button, field, accent, logo };
		foreach (Texture2D val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}
}
internal static class Branding
{
	internal static byte[] ReadIcon()
	{
		using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("LokiMoonLabs.LogisticsArchitect.icon.png");
		if (stream == null)
		{
			throw new InvalidOperationException("Embedded Loki Moon Labs icon is missing.");
		}
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		return memoryStream.ToArray();
	}

	internal static Texture2D LoadIcon()
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		Texture2D val = new Texture2D(2, 2);
		if (!ImageConversion.LoadImage(val, ReadIcon()))
		{
			Object.Destroy((Object)(object)val);
			throw new InvalidOperationException("Cannot load the embedded Loki Moon Labs icon.");
		}
		return val;
	}
}
internal static class InputPolicy
{
	public static bool Block(bool visible, bool overWindow, bool dragging, bool editingText, bool closingFrame)
	{
		if (!closingFrame)
		{
			if (visible)
			{
				if (!overWindow && !dragging)
				{
					return editingText;
				}
				return true;
			}
			return false;
		}
		return true;
	}
}
internal sealed class LauncherClickGate
{
	private int lastFrame = -1;

	public bool Accept(int frame)
	{
		if (lastFrame == frame)
		{
			return false;
		}
		lastFrame = frame;
		return true;
	}
}
internal static class LauncherLayout
{
	public static Vector2 Next(Vector2 previous, Vector2 last, float fallbackGap)
	{
		//IL_006e: 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)
		float num = last.x - previous.x;
		float num2 = last.y - previous.y;
		if (num * num + num2 * num2 < 1f)
		{
			return new Vector2(last.x + fallbackGap * 0.075f, last.y - fallbackGap);
		}
		return new Vector2(last.x + Math.Abs(num) * 0.25f, last.y - Math.Abs(num2));
	}
}
internal sealed class MinimapLauncher : IDisposable
{
	private readonly Action toggle;

	private readonly Action<string> report;

	private UIPlanetGlobe owner;

	private GameObject root;

	private RectTransform rect;

	private Image icon;

	private readonly LauncherClickGate clicks = new LauncherClickGate();

	public MinimapLauncher(Action toggle, Action<string> report)
	{
		this.toggle = toggle;
		this.report = report;
	}

	public void Update(UIPlanetGlobe globe)
	{
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)owner != (Object)(object)globe || ((Object)(object)owner != (Object)null && (Object)(object)root == (Object)null))
		{
			Dispose();
			owner = globe;
		}
		if ((Object)(object)globe == (Object)null || (Object)(object)globe.button3 == (Object)null || (Object)(object)globe.button2 == (Object)null)
		{
			return;
		}
		bool flag = (Object)(object)root == (Object)null;
		if (flag)
		{
			Create(globe.button3);
		}
		if ((Object)(object)icon != (Object)null && (Object)(object)icon.sprite == (Object)null && (Object)(object)LDB.items != (Object)null)
		{
			ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2104);
			if (val != null)
			{
				icon.sprite = val.iconSprite;
			}
		}
		RectTransform val2 = (RectTransform)((Component)globe.button3).transform;
		RectTransform val3 = (RectTransform)((Component)globe.button2).transform;
		RectTransform val4 = (((Object)(object)globe.minimap == (Object)null) ? null : ((Graphic)globe.minimap).rectTransform);
		if ((Object)(object)val4 != (Object)null)
		{
			Rect val5 = val3.rect;
			Vector2 previous = Vector2.op_Implicit(((Transform)val4).InverseTransformPoint(((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref val5)).center))));
			Rect val6 = val2.rect;
			Vector2 last = Vector2.op_Implicit(((Transform)val4).InverseTransformPoint(((Transform)val2).TransformPoint(Vector2.op_Implicit(((Rect)(ref val6)).center))));
			Rect val7 = val2.rect;
			Vector2 val8 = LauncherLayout.Next(previous, last, ((Rect)(ref val7)).height + 10f);
			((Transform)rect).position = ((Transform)val4).TransformPoint(Vector2.op_Implicit(val8));
		}
		else
		{
			RectTransform obj = rect;
			Rect val9 = val2.rect;
			Vector2 center = ((Rect)(ref val9)).center;
			Rect val10 = val2.rect;
			float num = (((Rect)(ref val10)).height + 10f) * 0.075f;
			Rect val11 = val2.rect;
			((Transform)obj).position = ((Transform)val2).TransformPoint(Vector2.op_Implicit(center + new Vector2(num, 0f - ((Rect)(ref val11)).height - 10f)));
		}
		if (flag)
		{
			Action<string> action = report;
			object[] array = new object[9]
			{
				"Minimap button created: active=",
				root.activeInHierarchy,
				", position=",
				((Transform)rect).position,
				", size=",
				null,
				null,
				null,
				null
			};
			Rect val12 = rect.rect;
			array[5] = ((Rect)(ref val12)).size;
			array[6] = ", parent=";
			array[7] = ((Object)((Transform)rect).parent).name;
			array[8] = ". Using the game's ILS icon.";
			action(string.Concat(array));
		}
	}

	private void Create(Button template)
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Expected O, but got Unknown
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: 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_0234: Expected O, but got Unknown
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Expected O, but got Unknown
		//IL_034a: 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_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: 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_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		root = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent, false);
		((Object)root).name = "Logistics Architect minimap button";
		rect = root.GetComponent<RectTransform>();
		rect.pivot = new Vector2(0.5f, 0.5f);
		Button component = root.GetComponent<Button>();
		((Behaviour)component).enabled = true;
		((Selectable)component).interactable = true;
		root.transform.SetAsLastSibling();
		component.onClick = new ButtonClickedEvent();
		((UnityEvent)component.onClick).AddListener(new UnityAction(Click));
		Graphic[] componentsInChildren = root.GetComponentsInChildren<Graphic>(true);
		foreach (Graphic val in componentsInChildren)
		{
			if ((Object)(object)((Component)val).transform != (Object)(object)root.transform && ((Object)val).name.IndexOf("icon", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				((Behaviour)val).enabled = false;
			}
		}
		UIButton val2 = root.GetComponent<UIButton>() ?? root.AddComponent<UIButton>();
		TipSettings tips = val2.tips;
		((Behaviour)val2).enabled = true;
		val2.button = component;
		val2.eventReceiver = null;
		val2.onClick += delegate
		{
			Click();
		};
		val2.tips = new TipSettings
		{
			tipTitle = "Logistics Architect",
			tipText = "Configure logistics stations.\nClick to open or close.",
			width = 260,
			delay = 0.35f,
			corner = tips.corner,
			offset = tips.offset,
			topLevel = tips.topLevel,
			level = tips.level,
			simpleGeneralTipPrefab = tips.simpleGeneralTipPrefab,
			type = (ItemTipType)(-1)
		};
		val2.tipTitleFormatString = val2.tips.tipTitle;
		val2.tipTextFormatString = val2.tips.tipText;
		GameObject val3 = new GameObject("Interstellar Logistics Station icon", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val3.transform.SetParent(root.transform, false);
		Image val4 = (icon = val3.GetComponent<Image>());
		val4.preserveAspect = true;
		((Graphic)val4).color = Color.white;
		((Graphic)val4).raycastTarget = true;
		RectTransform rectTransform = ((Graphic)val4).rectTransform;
		Vector2 val5 = (rectTransform.pivot = new Vector2(0.5f, 0.5f));
		Vector2 anchorMin = (rectTransform.anchorMax = val5);
		rectTransform.anchorMin = anchorMin;
		Rect val8 = rect.rect;
		float width = ((Rect)(ref val8)).width;
		Rect val9 = rect.rect;
		float num = Mathf.Min(width, ((Rect)(ref val9)).height) * 0.65f;
		rectTransform.sizeDelta = new Vector2(num, num);
		GameObject val10 = new GameObject("Launcher hit surface", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val10.transform.SetParent(root.transform, false);
		Image component2 = val10.GetComponent<Image>();
		((Graphic)component2).color = Color.clear;
		((Graphic)component2).raycastTarget = true;
		RectTransform rectTransform2 = ((Graphic)component2).rectTransform;
		rectTransform2.anchorMin = Vector2.zero;
		rectTransform2.anchorMax = Vector2.one;
		Vector2 offsetMin = (rectTransform2.offsetMax = Vector2.zero);
		rectTransform2.offsetMin = offsetMin;
		root.SetActive(true);
	}

	private void Click()
	{
		if (clicks.Accept(Time.frameCount))
		{
			report("Minimap launcher clicked; toggling Logistics Architect window.");
			toggle();
		}
	}

	public void Dispose()
	{
		if ((Object)(object)root != (Object)null)
		{
			Object.Destroy((Object)(object)root);
		}
		root = null;
		rect = null;
		icon = null;
		owner = null;
	}
}
internal static class OpenPanels
{
	private static readonly Action<UIStationWindow> station = Bind<UIStationWindow>("OnStationIdChange");

	private static readonly Action<UIDispenserWindow> dispenser = Bind<UIDispenserWindow>("OnDispenserIdChange");

	private static readonly Action<UIBattleBaseWindow> battleBase = Bind<UIBattleBaseWindow>("OnBattleBaseIdChange");

	private static Action<T> Bind<T>(string name)
	{
		return (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), AccessTools.Method(typeof(T), name, (Type[])null, (Type[])null));
	}

	public static void Refresh()
	{
		UIRoot instance = UIRoot.instance;
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.uiGame == (Object)null))
		{
			UIGame uiGame = instance.uiGame;
			if ((Object)(object)uiGame.stationWindow != (Object)null && ((ManualBehaviour)uiGame.stationWindow).active)
			{
				station(uiGame.stationWindow);
			}
			if ((Object)(object)uiGame.dispenserWindow != (Object)null && ((ManualBehaviour)uiGame.dispenserWindow).active)
			{
				dispenser(uiGame.dispenserWindow);
			}
			if ((Object)(object)uiGame.battleBaseWindow != (Object)null && ((ManualBehaviour)uiGame.battleBaseWindow).active)
			{
				battleBase(uiGame.battleBaseWindow);
			}
		}
	}
}
[BepInPlugin("LokiMoonLabs.LogisticsArchitect", "Logistics Architect", "0.1.6")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PlanetTransport), "NewStationComponent")]
	private static class NewStation
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PlanetTransport __instance, StationComponent __result)
		{
			if (!((Object)(object)instance == (Object)null) && __result != null && !__result.isCollector)
			{
				instance.NewFacility(__instance.factory, __result.isVeinCollector ? Facility.AdvancedMiners : (__result.isStellar ? Facility.ILS : Facility.PLS), __result.id, __result);
			}
		}
	}

	[HarmonyPatch(typeof(PlanetTransport), "NewDispenserComponent")]
	private static class NewDispenser
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PlanetTransport __instance, int __result)
		{
			if ((Object)(object)instance != (Object)null && StationService.Has(__instance.dispenserPool, __result) && __result > 0)
			{
				instance.NewFacility(__instance.factory, Facility.Distributors, __result, __instance.dispenserPool[__result]);
			}
		}
	}

	[HarmonyPatch(typeof(DefenseSystem), "NewBattleBaseComponent")]
	private static class NewBattleBase
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(DefenseSystem __instance, int __result)
		{
			if ((Object)(object)instance != (Object)null && __instance.battleBases != null && StationService.Has(__instance.battleBases.buffer, __result) && __result > 0)
			{
				instance.NewFacility(__instance.factory, Facility.BattleBases, __result, __instance.battleBases.buffer[__result]);
			}
		}
	}

	[HarmonyPatch(typeof(VFInput), "UpdateGameStates")]
	private static class ModalInput
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			if (!((Object)(object)instance == (Object)null) && instance.window != null && instance.window.Blocking)
			{
				VFInput.onGUI = true;
				VFInput.onGUIOperate = true;
				VFInput.inScrollView = true;
				if (instance.window.KeyboardBlocking)
				{
					VFInput.inputing = true;
				}
			}
		}
	}

	public const string Guid = "LokiMoonLabs.LogisticsArchitect";

	private static Plugin instance;

	internal Settings Settings;

	internal readonly ApplyQueue Jobs = new ApplyQueue();

	private ArchitectWindow window;

	private MinimapLauncher launcher;

	private Harmony harmony;

	private ConfigEntry<bool> uxAutoConfig;

	private float saveAt;

	public string Status
	{
		get
		{
			if (!Conflict)
			{
				return Jobs.Status;
			}
			return "UXAssist Auto-config logistic stations is enabled. Turn off that one UXAssist feature to use Apply or automatic configuration here.";
		}
	}

	internal bool Conflict
	{
		get
		{
			if (uxAutoConfig != null)
			{
				return uxAutoConfig.Value;
			}
			return false;
		}
	}

	internal bool CanApply
	{
		get
		{
			if (Settings.Enabled.Value && !Conflict && (Object)(object)GameMain.instance != (Object)null && !GameMain.instance.isMenuDemo && GameMain.data != null && GameMain.data.localPlanet != null)
			{
				return GameMain.data.localPlanet.factory != null;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
		Settings = new Settings(((BaseUnityPlugin)this).Config);
		((BaseUnityPlugin)this).Config.Save();
		if (Chainloader.PluginInfos.TryGetValue("org.soardev.uxassist", out var value) && (Object)(object)value.Instance != (Object)null)
		{
			value.Instance.Config.TryGetEntry<bool>(new ConfigDefinition("Factory", "AutoConfigLogistics"), ref uxAutoConfig);
		}
		instance = this;
		window = new ArchitectWindow(this);
		launcher = new MinimapLauncher(delegate
		{
			window.Toggle();
		}, delegate(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		});
		harmony = new Harmony("LokiMoonLabs.LogisticsArchitect");
		harmony.PatchAll(typeof(Plugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Logistics Architect ready. Open it with the ILS minimap button.");
	}

	private void Update()
	{
		if (window.Visible && Input.GetKeyDown((KeyCode)27))
		{
			window.Close();
		}
		window.UpdateShield();
		if (launcher != null && (Object)(object)GameMain.instance != (Object)null && !GameMain.instance.isMenuDemo)
		{
			UIRoot val = UIRoot.instance;
			launcher.Update(((Object)(object)val == (Object)null || (Object)(object)val.uiGame == (Object)null) ? null : val.uiGame.planetGlobe);
		}
		if (saveAt > 0f && Time.unscaledTime >= saveAt)
		{
			saveAt = 0f;
			try
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			catch (Exception ex)
			{
				Jobs.Status = "Could not save preset: " + ex.Message;
			}
		}
		if (!Settings.Enabled.Value || Conflict)
		{
			if (Jobs.Pending > 0)
			{
				Jobs.Clear();
			}
			return;
		}
		int revision = Jobs.Revision;
		Jobs.Tick(GameMain.data);
		if (Jobs.Revision == revision)
		{
			return;
		}
		try
		{
			OpenPanels.Refresh();
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Settings applied, but an open panel could not refresh: " + ex2.Message));
		}
	}

	internal void Dirty()
	{
		saveAt = Time.unscaledTime + 0.75f;
	}

	internal void Message(string text)
	{
		Jobs.Status = text;
	}

	internal void Apply(Preset preset, string only)
	{
		if (!CanApply)
		{
			Message(Conflict ? Status : "Load a planet before applying settings.");
			return;
		}
		GameData data = GameMain.data;
		PlanetFactory factory = data.localPlanet.factory;
		ICarrierStock inventory = (Settings.FillCarriers.Value ? new PlayerStock(data.mainPlayer, factory.planet) : null);
		Jobs.Enqueue(data, new ApplyJob(factory, preset.Snapshot(only), inventory));
	}

	private void NewFacility(PlanetFactory factory, Facility kind, int id, object expected)
	{
		if (!Settings.Enabled.Value || Conflict || factory == null || factory.gameData == null || id <= 0 || (Object)(object)GameMain.instance == (Object)null || GameMain.instance.isMenuDemo)
		{
			return;
		}
		foreach (Preset preset in Settings.Presets)
		{
			if (preset.Kind == kind && preset.OnBuild.Value)
			{
				ICarrierStock inventory = (Settings.FillCarriers.Value ? new PlayerStock(factory.gameData.mainPlayer, factory.planet) : null);
				Jobs.Enqueue(factory.gameData, new ApplyJob(factory, preset.Snapshot(null), inventory, id, expected));
				break;
			}
		}
	}

	private void OnGUI()
	{
		if (window != null)
		{
			window.Draw();
		}
	}

	private void OnDestroy()
	{
		if (saveAt > 0f)
		{
			try
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not save Logistics Architect presets: " + ex.Message));
			}
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if (window != null)
		{
			window.Dispose();
		}
		if (launcher != null)
		{
			launcher.Dispose();
		}
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}
}
internal enum Facility
{
	PLS,
	ILS,
	Distributors,
	AdvancedMiners,
	BattleBases
}
internal sealed class Setting
{
	public readonly string Key;

	public readonly string Label;

	public readonly string Unit;

	public readonly double HardMin;

	public readonly double HardMax;

	public readonly bool Integral;

	public readonly bool Boolean;

	public readonly ConfigEntry<double> Value;

	public readonly ConfigEntry<double> Minimum;

	public readonly ConfigEntry<double> Maximum;

	public readonly ConfigEntry<double> Step;

	public Setting(ConfigFile config, string section, string key, string label, string unit, double value, double min, double max, double step, double hardMin, double hardMax, bool integral = false, bool boolean = false)
	{
		Key = key;
		Label = label;
		Unit = unit;
		HardMin = hardMin;
		HardMax = hardMax;
		Integral = integral;
		Boolean = boolean;
		Value = config.Bind<double>(section, key, value, label + ((unit.Length == 0) ? "" : (" (" + unit + ")")) + ". Saved preset; only Apply or new-building configuration changes buildings.");
		Minimum = config.Bind<double>(section + ".SliderLimits", key + "Minimum", min, "Editable slider minimum. Does not change the preset or existing buildings.");
		Maximum = config.Bind<double>(section + ".SliderLimits", key + "Maximum", max, "Editable slider maximum. Does not expand physical carrier arrays or change existing buildings.");
		Step = config.Bind<double>(section + ".SliderLimits", key + "Step", step, "Slider increment in the displayed units.");
		if (!ValidValue(Value.Value))
		{
			Value.Value = value;
		}
		if (!ValidRange(Minimum.Value, Maximum.Value, Step.Value))
		{
			Minimum.Value = min;
			Maximum.Value = max;
			Step.Value = step;
		}
	}

	public static bool Finite(double number)
	{
		if (!double.IsNaN(number))
		{
			return !double.IsInfinity(number);
		}
		return false;
	}

	public bool ValidValue(double number)
	{
		if (Finite(number) && number >= HardMin && number <= HardMax)
		{
			if (Integral)
			{
				return number == Math.Round(number);
			}
			return true;
		}
		return false;
	}

	public bool ValidRange(double min, double max, double step)
	{
		if (ValidValue(min) && ValidValue(max) && min < max && Finite(step) && step > 0.0 && step <= max - min)
		{
			if (Integral)
			{
				return step == Math.Round(step);
			}
			return true;
		}
		return false;
	}

	public bool SetValue(double number)
	{
		if (!ValidValue(number))
		{
			return false;
		}
		Value.Value = number;
		return true;
	}

	public bool SetRange(double min, double max, double step)
	{
		if (!ValidRange(min, max, step))
		{
			return false;
		}
		Minimum.Value = min;
		Maximum.Value = max;
		Step.Value = step;
		return true;
	}

	public double Normalize()
	{
		return Math.Max(0.0, Math.Min(1.0, (Value.Value - Minimum.Value) / (Maximum.Value - Minimum.Value)));
	}

	public double FromSlider(double fraction)
	{
		double num = Minimum.Value + Math.Max(0.0, Math.Min(1.0, fraction)) * (Maximum.Value - Minimum.Value);
		num = Minimum.Value + Math.Round((num - Minimum.Value) / Step.Value) * Step.Value;
		num = Math.Max(Minimum.Value, Math.Min(Maximum.Value, num));
		if (!Integral)
		{
			return num;
		}
		return Math.Round(num);
	}
}
internal sealed class Preset
{
	public readonly Facility Kind;

	public readonly string Name;

	public readonly ConfigEntry<bool> OnBuild;

	public readonly List<Setting> Settings = new List<Setting>();

	private readonly ConfigFile config;

	public Preset(ConfigFile config, Facility kind, string name)
	{
		this.config = config;
		Kind = kind;
		Name = name;
		OnBuild = config.Bind<bool>(kind.ToString(), "ConfigureNewBuildings", true, "Apply this preset when a matching facility is built. Existing facilities require Apply.");
	}

	public Setting Add(string key, string label, string unit, double value, double min, double max, double step, double hardMin, double hardMax, bool integral = false, bool boolean = false)
	{
		Setting setting = new Setting(config, Kind.ToString(), key, label, unit, value, min, max, step, hardMin, hardMax, integral, boolean);
		Settings.Add(setting);
		return setting;
	}

	public void Flag(string key, string label, bool value)
	{
		Add(key, label, "", value ? 1 : 0, 0.0, 1.0, 1.0, 0.0, 1.0, integral: true, boolean: true);
	}

	public PresetSnapshot Snapshot(string only)
	{
		PresetSnapshot presetSnapshot = new PresetSnapshot(Kind);
		foreach (Setting setting in Settings)
		{
			if (setting.Key == "VesselRange")
			{
				presetSnapshot.VesselRangeLY = setting.Value.Value;
			}
			if (setting.Key == "UnlimitedVesselRange")
			{
				presetSnapshot.UnlimitedRange = setting.Value.Value != 0.0;
			}
		}
		foreach (Setting setting2 in Settings)
		{
			if ((only == null || only == setting2.Key) && setting2.ValidValue(setting2.Value.Value))
			{
				presetSnapshot.Values.Add(setting2.Key, setting2.Value.Value);
			}
		}
		return presetSnapshot;
	}
}
internal sealed class PresetSnapshot
{
	public readonly Facility Kind;

	public double VesselRangeLY;

	public bool UnlimitedRange;

	public readonly Dictionary<string, double> Values = new Dictionary<string, double>();

	public PresetSnapshot(Facility kind)
	{
		Kind = kind;
	}

	public bool Has(string key)
	{
		return Values.ContainsKey(key);
	}

	public double Get(string key)
	{
		return Values[key];
	}
}
internal sealed class Settings
{
	public readonly List<Preset> Presets = new List<Preset>();

	public readonly ConfigEntry<bool> Enabled;

	public readonly ConfigEntry<bool> FillCarriers;

	public Settings(ConfigFile config)
	{
		Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Logistics Architect.");
		FillCarriers = config.Bind<bool>("General", "FillCarriersFromInventory", true, "Carrier-count Apply buttons take real bots/drones/vessels from Icarus's normal inventory on the same planet. Existing carriers are never removed.");
		Preset p = Add(config, Facility.PLS, "Planetary Logistics Stations (PLS)");
		Station(p, stellar: false);
		Preset p2 = Add(config, Facility.ILS, "Interstellar Logistics Stations (ILS)");
		Station(p2, stellar: true);
		Preset preset = Add(config, Facility.Distributors, "Logistics Distributors");
		Power(preset, 9.0, 0.9, 9.0, 0.3);
		preset.Add("Bots", "Bots to fill", "", 10.0, 0.0, 100.0, 1.0, 0.0, 1000000.0, integral: true);
		preset.Flag("AutoReplenishBots", "Native automatic bot replenishment", value: false);
		Preset preset2 = Add(config, Facility.AdvancedMiners, "Advanced Mining Machines");
		preset2.Add("MiningSpeed", "Collecting speed", "%", 300.0, 100.0, 1000.0, 10.0, 1.0, 1000000.0, integral: true);
		Piler(preset2);
		Preset p3 = Add(config, Facility.BattleBases, "Battlefield Analysis Bases");
		Power(p3, 12.0, 1.2, 12.0, 0.3);
	}

	private Preset Add(ConfigFile file, Facility kind, string name)
	{
		Preset preset = new Preset(file, kind, name);
		Presets.Add(preset);
		return preset;
	}

	private static void Power(Preset p, double value, double min, double max, double step)
	{
		p.Add("PowerMW", "Maximum charging power", "MW", value, min, max, step, 0.0, 1000000000.0);
	}

	private static void Piler(Preset p)
	{
		p.Add("Piler", "Outgoing stack size (0 = technology)", "", 4.0, 0.0, 30.0, 1.0, 0.0, 255.0, integral: true);
	}

	private static void Station(Preset p, bool stellar)
	{
		Power(p, stellar ? 9000 : 360, stellar ? 30 : 6, stellar ? 9000 : 360, stellar ? 15 : 3);
		p.Add("DroneRange", "Drone transport range", "degrees", 180.0, 1.0, 180.0, 1.0, 0.0, 180.0);
		p.Add("DroneLoad", "Minimum drone load", "%", 100.0, 1.0, 100.0, 1.0, 1.0, 100.0, integral: true);
		Piler(p);
		p.Add("Drones", "Drones to fill", "", stellar ? 100 : 50, 0.0, stellar ? 100 : 50, 1.0, 0.0, 1000000.0, integral: true);
		p.Flag("AutoReplenishDrones", "Native automatic drone replenishment", value: false);
		if (stellar)
		{
			p.Add("VesselRange", "Vessel transport range", "LY", 60.0, 1.0, 60.0, 1.0, 0.0, 1000000000.0);
			p.Flag("UnlimitedVesselRange", "Unlimited vessel transport range", value: true);
			p.Add("WarpDistance", "Warp activation distance", "AU", 2.0, 0.0, 60.0, 0.5, 0.0, 1000000000.0);
			p.Add("VesselLoad", "Minimum vessel load", "%", 100.0, 1.0, 100.0, 1.0, 1.0, 100.0, integral: true);
			p.Add("Vessels", "Vessels to fill", "", 20.0, 0.0, 20.0, 1.0, 0.0, 1000000.0, integral: true);
			p.Flag("AutoReplenishVessels", "Native automatic vessel replenishment", value: false);
			p.Flag("IncludeCollectors", "Include orbital collectors", value: true);
			p.Flag("RequireWarpers", "Require warpers", value: true);
			p.Flag("RemoteStorage", "Set remote slot modes to Storage", value: false);
		}
	}
}
internal interface ICarrierStock
{
	int Take(int item, int requested);
}
internal sealed class PlayerStock : ICarrierStock
{
	private readonly Player player;

	private readonly PlanetData planet;

	public PlayerStock(Player player, PlanetData planet)
	{
		this.player = player;
		this.planet = planet;
	}

	public int Take(int item, int requested)
	{
		if (player == null || player.package == null || !object.ReferenceEquals(player.planetData, planet) || requested <= 0)
		{
			return 0;
		}
		int num = default(int);
		return player.package.TakeItem(item, requested, ref num);
	}
}
internal sealed class ApplyResult
{
	public int Changed;

	public int Limited;

	public int AddedCarriers;

	public int Skipped;

	public string Summary()
	{
		return Changed + " facilities configured; " + AddedCarriers + " carriers added; " + Limited + " carrier targets limited by building capacity; " + Skipped + " skipped.";
	}
}
internal static class StationService
{
	internal static bool Has<T>(T[] array, int index)
	{
		if (array != null && index >= 0)
		{
			return index < array.Length;
		}
		return false;
	}

	public static long PowerPerTick(double megawatts)
	{
		if (!Setting.Finite(megawatts) || megawatts < 0.0 || megawatts > 1000000000.0)
		{
			throw new ArgumentOutOfRangeException("megawatts");
		}
		return (long)Math.Round(megawatts * 1000000.0 / 60.0, MidpointRounding.AwayFromZero);
	}

	private static bool Power(PlanetFactory factory, int pc, double value)
	{
		if (factory.powerSystem == null || !Has(factory.powerSystem.consumerPool, pc) || pc <= 0 || factory.powerSystem.consumerPool[pc].id != pc)
		{
			return false;
		}
		factory.powerSystem.consumerPool[pc].workEnergyPerTick = PowerPerTick(value);
		return true;
	}

	private static PrefabDesc Desc(PlanetFactory factory, int entity)
	{
		if (!Has(factory.entityPool, entity) || entity <= 0 || factory.entityPool[entity].id != entity)
		{
			return null;
		}
		int protoId = factory.entityPool[entity].protoId;
		ItemProto val = ((protoId > 0) ? ((ProtoSet<ItemProto>)(object)LDB.items).Select(protoId) : null);
		if (val != null && val.prefabDesc != null)
		{
			return val.prefabDesc;
		}
		int modelIndex = factory.entityPool[entity].modelIndex;
		if (!Has(PlanetFactory.PrefabDescByModelIndex, modelIndex))
		{
			return null;
		}
		return PlanetFactory.PrefabDescByModelIndex[modelIndex];
	}

	private static int Capacity(int model, int data, int orders, int ceiling)
	{
		if (model <= 0 || data <= 0 || orders <= 0)
		{
			return 0;
		}
		return Math.Min(ceiling, Math.Min(model, Math.Min(data, orders)));
	}

	public static int DroneCapacity(PlanetFactory factory, StationComponent station)
	{
		PrefabDesc val = Desc(factory, station.entityId);
		if (val != null)
		{
			return Capacity(val.stationMaxDroneCount, (station.workDroneDatas != null) ? station.workDroneDatas.Length : 0, (station.workDroneOrders != null) ? station.workDroneOrders.Length : 0, int.MaxValue);
		}
		return 0;
	}

	public static int ShipCapacity(PlanetFactory factory, StationComponent station)
	{
		PrefabDesc val = Desc(factory, station.entityId);
		if (val != null)
		{
			return Capacity(val.stationMaxShipCount, (station.workShipDatas != null) ? station.workShipDatas.Length : 0, (station.workShipOrders != null) ? station.workShipOrders.Length : 0, 64);
		}
		return 0;
	}

	private static int Fill(int requested, int idle, int working, int capacity, int item, ICarrierStock inventory, ApplyResult result)
	{
		int num = Math.Min(Math.Max(0, requested), capacity);
		if (requested > capacity)
		{
			result.Limited++;
		}
		if (idle < 0 || working < 0 || inventory == null)
		{
			return 0;
		}
		int num2 = (int)Math.Max(0L, (long)num - (long)idle - working);
		if (num2 == 0)
		{
			return 0;
		}
		int num3 = inventory.Take(item, num2);
		if (num3 < 0 || num3 > num2)
		{
			throw new InvalidOperationException("Carrier inventory returned an invalid item count.");
		}
		result.AddedCarriers += num3;
		return num3;
	}

	public static bool Matches(StationComponent station, Facility kind)
	{
		if (station == null || station.id <= 0 || station.isCollector)
		{
			return false;
		}
		if (station.isVeinCollector)
		{
			return kind == Facility.AdvancedMiners;
		}
		return kind == (Facility)(station.isStellar ? 1 : 0);
	}

	public static void Station(PlanetFactory factory, StationComponent station, PresetSnapshot preset, ICarrierStock inventory, ApplyResult result)
	{
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		if (factory == null || !Matches(station, preset.Kind) || factory.transport == null || !Has(factory.transport.stationPool, station.id) || !object.ReferenceEquals(factory.transport.stationPool[station.id], station))
		{
			result.Skipped++;
			return;
		}
		if (preset.Has("PowerMW"))
		{
			Power(factory, station.pcId, preset.Get("PowerMW"));
		}
		if (preset.Has("DroneRange"))
		{
			station.tripRangeDrones = Math.Cos(preset.Get("DroneRange") * Math.PI / 180.0);
		}
		if (preset.Has("DroneLoad"))
		{
			station.deliveryDrones = (int)preset.Get("DroneLoad");
		}
		if (preset.Has("Piler"))
		{
			station.pilerCount = (int)preset.Get("Piler");
		}
		if (preset.Has("Drones"))
		{
			station.idleDroneCount += Fill((int)preset.Get("Drones"), station.idleDroneCount, station.workDroneCount, DroneCapacity(factory, station), 5001, inventory, result);
		}
		if (preset.Has("AutoReplenishDrones"))
		{
			station.droneAutoReplenish = preset.Get("AutoReplenishDrones") != 0.0;
		}
		if (station.isStellar)
		{
			if (preset.Has("VesselRange") || preset.Has("UnlimitedVesselRange"))
			{
				station.tripRangeShips = (preset.UnlimitedRange ? 10000.0 : preset.VesselRangeLY) * 2400000.0;
			}
			if (preset.Has("WarpDistance"))
			{
				station.warpEnableDist = preset.Get("WarpDistance") * 40000.0;
			}
			if (preset.Has("VesselLoad"))
			{
				station.deliveryShips = (int)preset.Get("VesselLoad");
			}
			if (preset.Has("Vessels"))
			{
				station.idleShipCount += Fill((int)preset.Get("Vessels"), station.idleShipCount, station.workShipCount, ShipCapacity(factory, station), 5002, inventory, result);
			}
			if (preset.Has("AutoReplenishVessels"))
			{
				station.shipAutoReplenish = preset.Get("AutoReplenishVessels") != 0.0;
			}
			if (preset.Has("IncludeCollectors"))
			{
				station.includeOrbitCollector = preset.Get("IncludeCollectors") != 0.0;
			}
			if (preset.Has("RequireWarpers"))
			{
				station.warperNecessary = preset.Get("RequireWarpers") != 0.0;
			}
			if (preset.Has("RemoteStorage") && preset.Get("RemoteStorage") != 0.0 && station.storage != null)
			{
				for (int i = 0; i < station.storage.Length; i++)
				{
					station.storage[i].remoteLogic = (ELogisticStorage)0;
				}
			}
		}
		if (station.isVeinCollector && preset.Has("MiningSpeed"))
		{
			int minerId = station.minerId;
			if (minerId <= 0 && Has(factory.entityPool, station.entityId))
			{
				minerId = factory.entityPool[station.entityId].minerId;
			}
			if (factory.factorySystem != null && Has(factory.factorySystem.minerPool, minerId) && minerId > 0 && factory.factorySystem.minerPool[minerId].id == minerId)
			{
				factory.factorySystem.minerPool[minerId].speed = (int)Math.Round(preset.Get("MiningSpeed") * 100.0);
			}
		}
		result.Changed++;
	}

	public static void Dispenser(PlanetFactory factory, DispenserComponent dispenser, PresetSnapshot preset, ICarrierStock inventory, ApplyResult result)
	{
		if (factory == null || dispenser == null || dispenser.id <= 0 || factory.transport == null || !Has(factory.transport.dispenserPool, dispenser.id) || !object.ReferenceEquals(factory.transport.dispenserPool[dispenser.id], dispenser))
		{
			result.Skipped++;
			return;
		}
		if (preset.Has("PowerMW"))
		{
			Power(factory, dispenser.pcId, preset.Get("PowerMW"));
		}
		if (preset.Has("Bots"))
		{
			PrefabDesc val = Desc(factory, dispenser.entityId);
			int capacity = ((val != null && dispenser.workCourierDatas != null && dispenser.orders != null) ? Capacity(val.dispenserMaxCourierCount, dispenser.workCourierDatas.Length, dispenser.orders.Length, int.MaxValue) : 0);
			dispenser.idleCourierCount += Fill((int)preset.Get("Bots"), dispenser.idleCourierCount, dispenser.workCourierCount, capacity, 5003, inventory, result);
		}
		if (preset.Has("AutoReplenishBots"))
		{
			dispenser.courierAutoReplenish = preset.Get("AutoReplenishBots") != 0.0;
		}
		result.Changed++;
	}

	public static void BattleBase(PlanetFactory factory, BattleBaseComponent battleBase, PresetSnapshot preset, ApplyResult result)
	{
		if (factory == null || battleBase == null || battleBase.id <= 0 || factory.defenseSystem == null || factory.defenseSystem.battleBases == null || !Has(factory.defenseSystem.battleBases.buffer, battleBase.id) || !object.ReferenceEquals(factory.defenseSystem.battleBases.buffer[battleBase.id], battleBase))
		{
			result.Skipped++;
			return;
		}
		if (preset.Has("PowerMW"))
		{
			Power(factory, battleBase.pcId, preset.Get("PowerMW"));
		}
		result.Changed++;
	}
}