Decompiled source of PowerGridIsolator v1.0.0

plugins\PowerGridIsolator.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using PowerNetworkStructures;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PowerGridIsolator")]
[assembly: AssemblyDescription("Dyson Sphere Program BepInEx mod.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PowerGridIsolator")]
[assembly: AssemblyCopyright("Copyright (c) 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("00000000-0000-0000-0000-000000000000")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PowerGridIsolator;

internal sealed class PluginConfig
{
	public readonly ConfigEntry<bool> EnableIsolation;

	public readonly ConfigEntry<int> MaxGroups;

	public readonly ConfigEntry<KeyboardShortcut> ToggleTagModeKey;

	public readonly ConfigEntry<bool> DebugLog;

	public PluginConfig(ConfigFile config)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		EnableIsolation = config.Bind<bool>("General", "EnableIsolation", true, "Master switch for the power-grid isolation filter. When true, poles tagged into different isolation groups never merge into the same PowerNetwork, even if physically in range. When false, the patch short-circuits and vanilla merge behaviour applies regardless of any tags.");
		MaxGroups = config.Bind<int>("General", "MaxGroups", 9, "Highest selectable isolation group id (1-9 by default). Group 0 is always \"ungrouped / vanilla\" and is not counted against this limit.");
		ToggleTagModeKey = config.Bind<KeyboardShortcut>("Hotkeys", "ToggleTagModeKey", new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Toggle pole-tagging mode. While active, a small window shows the current group (pick 1-MaxGroups via its buttons): left-click a power pole to assign it to the current group, right-click a tagged pole clears it back to group 0 (vanilla). Works on already-built poles, not just newly placed ones.");
		DebugLog = config.Bind<bool>("Diagnostics", "DebugLog", false, "Enable verbose diagnostic logging. Off by default; toggle on for first-run verification. Prints category-tagged lines ([config], [patch], [merge]) to the BepInEx console.");
	}
}
internal static class PowerGridIsolatorLog
{
	private static ManualLogSource logger;

	private static ConfigEntry<bool> debugEntry;

	public static void Init(ManualLogSource src, ConfigEntry<bool> debug)
	{
		logger = src;
		debugEntry = debug;
	}

	public static void Info(string msg)
	{
		if (debugEntry != null && debugEntry.Value && logger != null)
		{
			logger.LogInfo((object)("[PowerGridIsolator] " + msg));
		}
	}

	public static void Warn(string msg)
	{
		if (logger != null)
		{
			logger.LogWarning((object)("[PowerGridIsolator] " + msg));
		}
	}

	public static void Error(string msg)
	{
		if (logger != null)
		{
			logger.LogError((object)("[PowerGridIsolator] " + msg));
		}
	}

	public static bool IsDebugEnabled()
	{
		if (debugEntry != null)
		{
			return debugEntry.Value;
		}
		return false;
	}
}
[HarmonyPatch(typeof(UIBuildingGrid), "Update")]
internal static class DragBoxGridPatch
{
	private static readonly FieldRef<UIBuildingGrid, Material> MaterialRef = AccessTools.FieldRefAccess<UIBuildingGrid, Material>("material");

	private static readonly FieldRef<UIBuildingGrid, float> DisplayScaleRef = AccessTools.FieldRefAccess<UIBuildingGrid, float>("displayScale");

	private static readonly Color TintColor = new Color(1f, 0.5f, 0.05f, 1f);

	[HarmonyPostfix]
	[HarmonyPriority(200)]
	private static void Postfix(UIBuildingGrid __instance)
	{
		//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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		TagTool tool = TagToolInitPatch.tool;
		if (tool == null || !((BuildTool)tool).active || !tool.DragGratBox.HasValue)
		{
			return;
		}
		PlanetData localPlanet = GameMain.localPlanet;
		if (localPlanet != null && localPlanet.aux != null)
		{
			PlanetGrid val = null;
			if (localPlanet.aux.activeGridIndex < localPlanet.aux.customGrids.Count)
			{
				val = localPlanet.aux.customGrids[localPlanet.aux.activeGridIndex];
			}
			if (val != null)
			{
				Vector4 value = tool.DragGratBox.Value;
				float num = localPlanet.realRadius * 2f;
				float num2 = DisplayScaleRef.Invoke(__instance);
				num2 = ((Mathf.Abs(num2 - num) > 10f) ? num : (num2 * 0.8f + num * 0.2f));
				DisplayScaleRef.Invoke(__instance) = num2;
				__instance.gridRnd.enabled = true;
				((Component)__instance.gridRnd).transform.localScale = new Vector3(num2, num2, num2);
				((Component)__instance.gridRnd).transform.rotation = val.rotation;
				Material obj = MaterialRef.Invoke(__instance);
				obj.SetFloat("_Segment", (float)val.segment);
				obj.SetColor("_TintColor", TintColor);
				obj.SetFloat("_ReformMode", 0f);
				obj.SetFloat("_ZMin", -0.5f);
				obj.SetVector("_CursorGratBox", value);
			}
		}
	}
}
[HarmonyPatch(typeof(PowerSystem), "OnNodeAdded")]
internal static class PowerNetworkPatch
{
	internal sealed class HiddenNetwork
	{
		public PowerNetwork Net;

		public List<Node> Nodes;
	}

	private static readonly List<Node> EmptyNodes = new List<Node>();

	[HarmonyPrefix]
	private static void Prefix(PowerSystem __instance, int nodeId, out List<HiddenNetwork> __state)
	{
		__state = null;
		try
		{
			if (!Plugin.Config.EnableIsolation.Value || __instance == null || __instance.nodePool == null || nodeId <= 0 || nodeId >= __instance.nodePool.Length)
			{
				return;
			}
			int planetId = ((__instance.planet != null) ? __instance.planet.id : 0);
			int entityId = __instance.nodePool[nodeId].entityId;
			int num = GroupStore.GetGroup(planetId, entityId);
			List<HiddenNetwork> list = (__state = new List<HiddenNetwork>());
			PowerNetwork[] netPool = __instance.netPool;
			PowerNodeComponent[] nodePool = __instance.nodePool;
			for (int i = 1; i < __instance.netCursor; i++)
			{
				PowerNetwork val = netPool[i];
				if (val != null && val.id != 0 && val.nodes != null && val.nodes.Count != 0)
				{
					int id = val.nodes[0].id;
					if (id > 0 && id < nodePool.Length && GroupStore.GetGroup(planetId, nodePool[id].entityId) != num)
					{
						list.Add(new HiddenNetwork
						{
							Net = val,
							Nodes = val.nodes
						});
						val.nodes = EmptyNodes;
					}
				}
			}
			if (list.Count > 0 && PowerGridIsolatorLog.IsDebugEnabled())
			{
				PowerGridIsolatorLog.Info("[merge] entityId=" + entityId + " group=" + num + " hid " + list.Count + " out-of-group network(s) for this connection pass");
			}
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("OnNodeAdded group-filter prefix threw: " + ex);
		}
	}

	[HarmonyFinalizer]
	private static Exception Finalizer(Exception __exception, List<HiddenNetwork> __state)
	{
		if (__state != null)
		{
			for (int i = 0; i < __state.Count; i++)
			{
				__state[i].Net.nodes = __state[i].Nodes;
			}
		}
		return __exception;
	}
}
[HarmonyPatch(typeof(GameMain), "Start")]
internal static class QuickBarButtonPatch
{
	private static UIButton button;

	[HarmonyPostfix]
	private static void Postfix()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: 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)
		if ((Object)(object)button != (Object)null)
		{
			return;
		}
		try
		{
			UIButton infiniteEnergyButton = UIRoot.instance.uiGame.energyBar.infiniteEnergyButton;
			if ((Object)(object)infiniteEnergyButton == (Object)null)
			{
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)infiniteEnergyButton).gameObject, ((Component)infiniteEnergyButton).transform.parent.parent);
			((Object)val).name = "[PowerGridIsolator] Toggle";
			RectTransform val2 = (RectTransform)((Component)UIRoot.instance.uiGame.energyBar.energyChangesTip).transform;
			Transform transform = val.transform;
			float x = ((Transform)val2).localPosition.x;
			Rect rect = val2.rect;
			transform.localPosition = new Vector3(x - ((Rect)(ref rect)).width / 1.5f - 50f, val.transform.localPosition.y, val.transform.localPosition.z);
			val.SetActive(true);
			Sprite val3 = FindPowerNodeIcon();
			if ((Object)(object)val3 != (Object)null)
			{
				Transform val4 = val.transform.Find("icon");
				if ((Object)(object)val4 != (Object)null)
				{
					Image component = ((Component)val4).GetComponent<Image>();
					if ((Object)(object)component != (Object)null)
					{
						component.sprite = val3;
					}
				}
			}
			button = val.GetComponent<UIButton>();
			button.onClick += OnClick;
			button.tips.corner = 8;
			button.tips.tipTitle = "PowerGridIsolator";
			button.tips.tipText = "Toggle pole-tagging mode (" + FormatShortcut(Plugin.Config.ToggleTagModeKey.Value) + ")";
			PowerGridIsolatorLog.Info("[ui] Quick-bar toggle button created.");
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Warn("[ui] Failed to create quick-bar button: " + ex);
		}
	}

	private static void OnClick(int _)
	{
		if (Plugin.Config.EnableIsolation.Value)
		{
			TagToolActivatePatch.RequestToggle();
		}
	}

	private static string FormatShortcut(KeyboardShortcut shortcut)
	{
		//IL_0016: 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_001d: 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)
		StringBuilder stringBuilder = new StringBuilder();
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
		{
			stringBuilder.Append(modifier).Append(" + ");
		}
		stringBuilder.Append(((KeyboardShortcut)(ref shortcut)).MainKey);
		return stringBuilder.ToString();
	}

	private static Sprite FindPowerNodeIcon()
	{
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val != null && val.prefabDesc != null && val.prefabDesc.isPowerNode)
			{
				return val.iconSprite;
			}
		}
		return null;
	}
}
[HarmonyPatch(typeof(GameMain), "Begin")]
internal static class GameBeginHookPatch
{
	[HarmonyPostfix]
	private static void Postfix()
	{
		try
		{
			GroupStore.Clear();
			SaveIO.TryLoad((GameMain.data != null) ? GameMain.data.gameName : null);
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("GameMain.Begin postfix threw: " + ex);
		}
	}
}
[HarmonyPatch(typeof(GameSave), "SaveCurrentGame")]
internal static class GameSaveHookPatch
{
	[HarmonyPostfix]
	private static void Postfix(bool __result)
	{
		try
		{
			if (__result)
			{
				SaveIO.Save((GameMain.data != null) ? GameMain.data.gameName : null);
			}
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("GameSave.SaveCurrentGame postfix threw: " + ex);
		}
	}
}
[HarmonyPatch(typeof(PlayerAction_Build), "Init")]
internal static class TagToolInitPatch
{
	internal static TagTool tool;

	[HarmonyPostfix]
	private static void Postfix(PlayerAction_Build __instance)
	{
		BuildTool[] tools = __instance.tools;
		if (tools != null)
		{
			BuildTool[] array = (BuildTool[])(object)new BuildTool[tools.Length + 1];
			tools.CopyTo(array, 0);
			tool = new TagTool();
			array[^1] = (BuildTool)(object)tool;
			__instance.tools = array;
			PowerGridIsolatorLog.Info("[tag] TagTool registered into PlayerAction_Build.tools. Total: " + array.Length);
		}
	}
}
[HarmonyPatch(typeof(PlayerAction_Build), "DetermineActive")]
internal static class TagToolActivatePatch
{
	private static bool toggleRequested;

	private static int hotkeyConsumedFrame = -1;

	public static void RequestToggle()
	{
		toggleRequested = true;
	}

	[HarmonyPostfix]
	private static void Postfix(PlayerAction_Build __instance, ref bool __result)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		TagTool tool = TagToolInitPatch.tool;
		if (tool == null || !Plugin.Config.EnableIsolation.Value)
		{
			toggleRequested = false;
			return;
		}
		bool flag = toggleRequested;
		bool flag2 = false;
		KeyboardShortcut value = Plugin.Config.ToggleTagModeKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown() && Time.frameCount != hotkeyConsumedFrame)
		{
			flag2 = true;
			hotkeyConsumedFrame = Time.frameCount;
		}
		bool flag3 = flag || flag2;
		toggleRequested = false;
		if (flag3 && PowerGridIsolatorLog.IsDebugEnabled())
		{
			PowerGridIsolatorLog.Info("[tag] toggle triggered via " + (flag ? "quick-bar button" : "hotkey"));
		}
		if (tool.IsEnable && (object)__instance.activeTool == tool)
		{
			if (flag3)
			{
				tool.IsEnable = false;
			}
			else
			{
				__result = true;
			}
		}
		else if (flag3 && (int)__instance.blueprintMode == 0 && VFInput.readyToBuild)
		{
			((PlayerAction)__instance).player.SetHandItems(0, 0, 0);
			((CommandState)(ref ((PlayerAction)__instance).player.controller.cmd)).SetNoneCommand();
			tool.IsEnable = true;
			__result = true;
		}
	}
}
internal static class SaveIO
{
	private static string SaveDir => Path.Combine(Paths.ConfigPath, "PowerGridIsolator", "saves");

	public static void TryLoad(string gameName)
	{
		try
		{
			string path = PathFor(gameName);
			if (!File.Exists(path))
			{
				PowerGridIsolatorLog.Info("[save] no sidecar for '" + gameName + "' - starting untagged.");
				return;
			}
			int num = 0;
			string[] array = File.ReadAllLines(path);
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					string[] array2 = text.Split(',');
					if (array2.Length == 3 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2) && int.TryParse(array2[2], out var result3))
					{
						GroupStore.SetGroup(result, result2, result3);
						num++;
					}
				}
			}
			PowerGridIsolatorLog.Info("[save] loaded " + num + " group tag(s) for '" + gameName + "'.");
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("[save] failed to load tags for '" + gameName + "': " + ex);
		}
	}

	public static void Save(string gameName)
	{
		try
		{
			Directory.CreateDirectory(SaveDir);
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			foreach (var item in GroupStore.ExportAll())
			{
				stringBuilder.Append(item.planetId).Append(',').Append(item.entityId)
					.Append(',')
					.Append(item.groupId)
					.Append('\n');
				num++;
			}
			File.WriteAllText(PathFor(gameName), stringBuilder.ToString());
			PowerGridIsolatorLog.Info("[save] wrote " + num + " group tag(s) for '" + gameName + "'.");
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("[save] failed to write tags for '" + gameName + "': " + ex);
		}
	}

	private static string PathFor(string gameName)
	{
		return Path.Combine(SaveDir, Sanitize(gameName) + ".txt");
	}

	private static string Sanitize(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return "unnamed";
		}
		char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
		StringBuilder stringBuilder = new StringBuilder(name.Length);
		foreach (char c in name)
		{
			stringBuilder.Append((Array.IndexOf(invalidFileNameChars, c) >= 0) ? '_' : c);
		}
		return stringBuilder.ToString();
	}
}
[BepInPlugin("com.zicarius.PowerGridIsolator", "PowerGridIsolator", "1.0.0")]
[BepInProcess("DSPGAME.exe")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string GUID = "com.zicarius.PowerGridIsolator";

	public const string NAME = "PowerGridIsolator";

	public const string VERSION = "1.0.0";

	internal static PluginConfig Config;

	private static Harmony _harmony;

	private void Awake()
	{
		//IL_0083: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected O, but got Unknown
		Config = new PluginConfig(((BaseUnityPlugin)this).Config);
		PowerGridIsolatorLog.Init(((BaseUnityPlugin)this).Logger, Config.DebugLog);
		PowerGridIsolatorLog.Info("[config] Loaded with config: enableIsolation=" + Config.EnableIsolation.Value + ", maxGroups=" + Config.MaxGroups.Value + ", toggleTagModeKey=" + ((object)Config.ToggleTagModeKey.Value/*cast due to .constrained prefix*/).ToString() + ", debug=" + Config.DebugLog.Value);
		try
		{
			_harmony = new Harmony("com.zicarius.PowerGridIsolator");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			PowerGridIsolatorLog.Info("[patch] Applied Harmony patches: PowerNetworkPatch, GameBeginHookPatch, GameSaveHookPatch, TagToolInitPatch, TagToolActivatePatch, QuickBarButtonPatch.");
		}
		catch (Exception ex)
		{
			PowerGridIsolatorLog.Error("Harmony PatchAll failed: " + ex);
		}
		DumpTargetMethodSignatures();
	}

	private static void DumpTargetMethodSignatures()
	{
		string[][] array = new string[6][]
		{
			new string[2] { "PowerSystem", "OnNodeAdded" },
			new string[2] { "GameMain", "Begin" },
			new string[2] { "GameSave", "SaveCurrentGame" },
			new string[2] { "PlayerAction_Build", "Init" },
			new string[2] { "PlayerAction_Build", "DetermineActive" },
			new string[2] { "GameMain", "Start" }
		};
		foreach (string[] array2 in array)
		{
			try
			{
				Type type = AccessTools.TypeByName(array2[0]);
				if (type == null)
				{
					PowerGridIsolatorLog.Warn("[diag] Type not found: " + array2[0]);
					continue;
				}
				MethodInfo methodInfo = AccessTools.Method(type, array2[1], (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					PowerGridIsolatorLog.Warn("[diag] Method not found: " + array2[0] + "." + array2[1]);
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("[diag] ").Append(array2[0]).Append(".")
					.Append(array2[1])
					.Append("(");
				for (int j = 0; j < parameters.Length; j++)
				{
					if (j > 0)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append(parameters[j].ParameterType.Name).Append(" ").Append(parameters[j].Name);
				}
				stringBuilder.Append(")");
				PowerGridIsolatorLog.Info(stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				PowerGridIsolatorLog.Error("[diag] Failed to inspect " + array2[0] + "." + array2[1] + ": " + ex.Message);
			}
		}
	}

	private void OnGUI()
	{
		TagWindow.OnGUI();
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		_harmony = null;
	}
}
internal static class GroupStore
{
	private static readonly Dictionary<int, Dictionary<int, int>> groupsByPlanet = new Dictionary<int, Dictionary<int, int>>();

	public static int GetGroup(int planetId, int entityId)
	{
		if (!groupsByPlanet.TryGetValue(planetId, out var value))
		{
			return 0;
		}
		if (!value.TryGetValue(entityId, out var value2))
		{
			return 0;
		}
		return value2;
	}

	public static void SetGroup(int planetId, int entityId, int groupId)
	{
		if (!groupsByPlanet.TryGetValue(planetId, out var value))
		{
			if (groupId == 0)
			{
				return;
			}
			value = new Dictionary<int, int>();
			groupsByPlanet[planetId] = value;
		}
		if (groupId == 0)
		{
			value.Remove(entityId);
		}
		else
		{
			value[entityId] = groupId;
		}
	}

	public static void Clear()
	{
		groupsByPlanet.Clear();
	}

	public static IEnumerable<(int planetId, int entityId, int groupId)> ExportAll()
	{
		foreach (KeyValuePair<int, Dictionary<int, int>> planetEntry in groupsByPlanet)
		{
			foreach (KeyValuePair<int, int> item in planetEntry.Value)
			{
				yield return (planetId: planetEntry.Key, entityId: item.Key, groupId: item.Value);
			}
		}
	}
}
internal sealed class TagTool : BuildTool
{
	private int dragButton = -1;

	private Vector2 dragStartScreenPos;

	private bool isDragging;

	private const float DragThresholdPixels = 6f;

	private int liveCountThrottle;

	private const int LiveCountEveryNTicks = 6;

	private const int GroundLayerMask = 8720;

	public bool IsEnable { get; set; }

	public int CurrentGroup { get; private set; } = 1;

	public bool IsHoveringPole { get; private set; }

	public Vector3 DragStartGroundDir { get; private set; }

	public Vector4? DragGratBox { get; private set; }

	public int DragSelectionCount { get; private set; }

	public void SetCurrentGroup(int group)
	{
		int num = Mathf.Max(1, Plugin.Config.MaxGroups.Value);
		int num2 = Mathf.Clamp(group, 1, num);
		if (num2 != CurrentGroup)
		{
			CurrentGroup = num2;
			PowerGridIsolatorLog.Info("[tag] current group -> " + CurrentGroup);
		}
	}

	public override bool DetermineActive()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (IsEnable && (int)((BuildTool)this).actionBuild.blueprintMode == 0)
		{
			return ((BuildTool)this).controller.cmd.mode == 0;
		}
		return false;
	}

	protected override void _OnOpen()
	{
		IsHoveringPole = false;
		PowerGridIsolatorLog.Info("[tag] tag mode ON, current group=" + CurrentGroup);
	}

	protected override void _OnClose()
	{
		IsEnable = false;
		IsHoveringPole = false;
		PowerGridIsolatorLog.Info("[tag] tag mode OFF");
	}

	protected unsafe override void _OnTick(long time)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: 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)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		if (VFInput.escape)
		{
			IsEnable = false;
			((BuildTool)this)._Close();
			return;
		}
		int num = ResolveHoveredPole();
		IsHoveringPole = num > 0;
		if (TagWindow.MouseOverWindow)
		{
			DragGratBox = null;
			((BuildTool)this).actionBuild.model.cursorText = "";
			return;
		}
		if (dragButton == -1)
		{
			if (Input.GetMouseButtonDown(0))
			{
				StartDrag(0);
			}
			else if (Input.GetMouseButtonDown(1))
			{
				StartDrag(1);
			}
		}
		if (dragButton == -1)
		{
			return;
		}
		Vector2 val = Vector2.op_Implicit(Input.mousePosition);
		Vector2 val2;
		if (!isDragging)
		{
			val2 = val - dragStartScreenPos;
			if (((Vector2)(ref val2)).magnitude > 6f)
			{
				isDragging = true;
			}
		}
		if (isDragging)
		{
			Vector3 val3 = RaycastGroundDir();
			if (DragStartGroundDir != Vector3.zero && val3 != Vector3.zero)
			{
				DragGratBox = BuildGratBox(DragStartGroundDir, val3);
			}
			if (DragGratBox.HasValue)
			{
				liveCountThrottle++;
				if (liveCountThrottle >= 6)
				{
					liveCountThrottle = 0;
					DragSelectionCount = ScanPolesInGratBox(DragGratBox.Value, -1);
				}
				((BuildTool)this).actionBuild.model.cursorText = "PowerGridIsolator - " + DragSelectionCount + " pole(s) selected";
			}
			if (liveCountThrottle == 0 && PowerGridIsolatorLog.IsDebugEnabled())
			{
				string[] obj = new string[8] { "[tag] drag mousePos=", null, null, null, null, null, null, null };
				val2 = val;
				obj[1] = ((object)(*(Vector2*)(&val2))/*cast due to .constrained prefix*/).ToString();
				obj[2] = " screen=";
				obj[3] = Screen.width.ToString();
				obj[4] = "x";
				obj[5] = Screen.height.ToString();
				obj[6] = " gratBox=";
				obj[7] = DragGratBox.ToString();
				PowerGridIsolatorLog.Info(string.Concat(obj));
			}
		}
		else
		{
			DragGratBox = null;
		}
		if ((dragButton == 0) ? Input.GetMouseButtonUp(0) : Input.GetMouseButtonUp(1))
		{
			int num2 = ((dragButton == 0) ? CurrentGroup : 0);
			bool flag = false;
			if (isDragging && DragGratBox.HasValue)
			{
				PowerGridIsolatorLog.Info("[tag] drag-select: tagged " + ScanPolesInGratBox(DragGratBox.Value, num2) + " pole(s) to group " + num2);
			}
			else if (num > 0)
			{
				Tag(num, num2);
			}
			else if (dragButton == 1)
			{
				flag = true;
			}
			if (dragButton == 0)
			{
				VFInput.UseMouseLeft();
			}
			else
			{
				VFInput.UseMouseRight();
			}
			dragButton = -1;
			isDragging = false;
			DragGratBox = null;
			DragSelectionCount = 0;
			liveCountThrottle = 0;
			((BuildTool)this).actionBuild.model.cursorText = "";
			if (flag)
			{
				IsEnable = false;
				((BuildTool)this)._Close();
			}
		}
	}

	private void StartDrag(int button)
	{
		//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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		dragButton = button;
		dragStartScreenPos = Vector2.op_Implicit(Input.mousePosition);
		DragStartGroundDir = RaycastGroundDir();
		isDragging = false;
	}

	private static Vector4 BuildGratBox(Vector3 startDir, Vector3 currentDir)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: 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_0015: 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)
		float longitudeRad = BlueprintUtils.GetLongitudeRad(startDir);
		float latitudeRad = BlueprintUtils.GetLatitudeRad(startDir);
		float longitudeRad2 = BlueprintUtils.GetLongitudeRad(currentDir);
		float latitudeRad2 = BlueprintUtils.GetLatitudeRad(currentDir);
		return new Vector4(Mathf.Min(longitudeRad, longitudeRad2), Mathf.Min(latitudeRad, latitudeRad2), Mathf.Max(longitudeRad, longitudeRad2), Mathf.Max(latitudeRad, latitudeRad2));
	}

	internal static Vector3 RaycastGroundDir()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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_0043: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Camera.main == (Object)null)
		{
			return Vector3.zero;
		}
		RaycastHit val = default(RaycastHit);
		if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), ref val, 800f, 8720, (QueryTriggerInteraction)2))
		{
			return Vector3.zero;
		}
		Vector3 point = ((RaycastHit)(ref val)).point;
		return ((Vector3)(ref point)).normalized;
	}

	private int ScanPolesInGratBox(Vector4 box, int groupIdOrCountOnly)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: 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)
		if (base.factory == null || base.factory.entityPool == null)
		{
			return 0;
		}
		BPGratBox val = (BPGratBox)box;
		EntityData[] entityPool = base.factory.entityPool;
		int entityCursor = base.factory.entityCursor;
		int num = 0;
		for (int i = 1; i < entityCursor; i++)
		{
			if (entityPool[i].id == i && entityPool[i].powerNodeId > 0 && ((BPGratBox)(ref val)).InGratBox(entityPool[i].pos))
			{
				if (groupIdOrCountOnly >= 0)
				{
					Tag(i, groupIdOrCountOnly);
				}
				num++;
			}
		}
		return num;
	}

	private int ResolveHoveredPole()
	{
		RaycastLogic raycast = ((BuildTool)this).controller.cmd.raycast;
		if (raycast == null)
		{
			return 0;
		}
		int id = raycast.castEntity.id;
		if (id <= 0)
		{
			return 0;
		}
		if (base.factory == null || base.factory.entityPool == null)
		{
			return 0;
		}
		if (id >= base.factory.entityPool.Length)
		{
			return 0;
		}
		if (base.factory.entityPool[id].powerNodeId <= 0)
		{
			return 0;
		}
		return id;
	}

	private void Tag(int entityId, int groupId)
	{
		if (base.factory == null || base.factory.entityPool == null || base.factory.powerSystem == null || entityId <= 0 || entityId >= base.factory.entityPool.Length)
		{
			return;
		}
		int powerNodeId = base.factory.entityPool[entityId].powerNodeId;
		if (powerNodeId <= 0)
		{
			return;
		}
		int planetId = ((base.factory.powerSystem.planet != null) ? base.factory.powerSystem.planet.id : 0);
		int num = GroupStore.GetGroup(planetId, entityId);
		if (num != groupId)
		{
			GroupStore.SetGroup(planetId, entityId, groupId);
			base.factory.powerSystem.OnNodeRemoving(powerNodeId);
			base.factory.powerSystem.OnNodeAdded(powerNodeId);
			if (base.planet != null && (Object)(object)base.planet.factoryModel != (Object)null)
			{
				base.planet.factoryModel.RefreshPowerNodes();
			}
			PowerGridIsolatorLog.Info("[tag] pole entityId=" + entityId + " planet=" + planetId + " group " + num + " -> " + groupId);
		}
	}
}
internal static class TagWindow
{
	private const int WindowId = 872341001;

	private static Rect windowRect = new Rect(140f, 140f, 260f, 0f);

	public static bool MouseOverWindow { get; private set; }

	public static void OnGUI()
	{
		//IL_0032: 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_0052: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		MouseOverWindow = false;
		TagTool tool = TagToolInitPatch.tool;
		if (tool != null && ((BuildTool)tool).active)
		{
			windowRect = GUILayout.Window(872341001, windowRect, (WindowFunction)delegate
			{
				DrawWindow(tool);
			}, "PowerGridIsolator - Tag Mode", Array.Empty<GUILayoutOption>());
			if (Event.current != null)
			{
				MouseOverWindow = ((Rect)(ref windowRect)).Contains(Event.current.mousePosition);
			}
		}
	}

	private static void DrawWindow(TagTool tool)
	{
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.Label(tool.IsHoveringPole ? "Pole under cursor" : "No pole under cursor", Array.Empty<GUILayoutOption>());
		GUILayout.Space(6f);
		GUILayout.Label("Group (left-click/drag over poles to assign):", Array.Empty<GUILayoutOption>());
		int num = Mathf.Max(1, Plugin.Config.MaxGroups.Value);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		for (int i = 1; i <= num; i++)
		{
			if (GUILayout.Button((i == tool.CurrentGroup) ? ("[" + i + "]") : i.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }))
			{
				tool.SetCurrentGroup(i);
			}
			if (i % 5 == 0 && i != num)
			{
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			}
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label("Right-click/drag over poles to clear them back to group 0.\nRight-click empty ground to exit.", Array.Empty<GUILayoutOption>());
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 20f));
	}
}