Decompiled source of GridSolverPlus v1.0.0

BepInEx/plugins/GridSolverPlus.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.UI;
using Sparroh.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("GridSolverPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GridSolverPlus")]
[assembly: AssemblyTitle("GridSolverPlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[BepInPlugin("sparroh.gridsolverplus", "GridSolverPlus", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class GridSolverPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.gridsolverplus";

	public const string PluginName = "GridSolverPlus";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Logger;

	public static GridSolverPlugin Instance;

	private UpgradeSolver upgradeSolver;

	private void Awake()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		Logger = ((BaseUnityPlugin)this).Logger;
		Instance = this;
		upgradeSolver = new UpgradeSolver();
		UpgradeSolver.Instance = upgradeSolver;
		new Harmony("sparroh.gridsolverplus").PatchAll();
		Logger.LogInfo((object)"GridSolverPlus v1.0.0 loaded.");
	}

	private void OnDestroy()
	{
		try
		{
			upgradeSolver?.SolverUI?.Close();
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to close UpgradeSolver UI: " + ex.Message));
		}
	}

	private void Update()
	{
		upgradeSolver?.Update();
	}

	private void OnGUI()
	{
		upgradeSolver?.OnGUI();
	}
}
public class UpgradeSolver
{
	public Coroutine? SolverCoroutine;

	internal static UpgradeSolver Instance;

	internal SolverUI SolverUI = new SolverUI(null, null);

	public void Update()
	{
		SolverUI.Update();
		if (GearActionBar.IsGearMenuOpen())
		{
			SolverUI.EnsureBarIfNeeded();
		}
	}

	internal void OnUpgradeWindowOpen(IUpgradeWindow window, IUpgradable gear, MonoBehaviour mono)
	{
		SolverUI.UpgradeWindow = window;
		SolverUI.CurrentGear = gear;
		SolverUI.OnWindowOpened();
		SolverUI.PatchUpgradeClick();
		mono.StartCoroutine(DelayPatch());
	}

	private IEnumerator DelayPatch()
	{
		yield return null;
		SolverUI.PatchUpgradeClick();
	}

	internal void OnUpgradeWindowClosed()
	{
		SolverUI.Close();
	}

	public void OnGUI()
	{
		SolverUI.OnGUI();
	}
}
public static class UpgradeSolverPatches
{
	[HarmonyPatch(typeof(GearDetailsWindow), "OnOpen")]
	public static class GearDetailsWindowPatch
	{
		[HarmonyPostfix]
		public static void Postfix(GearDetailsWindow __instance)
		{
			object? obj = _upgradablePrefabProperty?.GetValue(__instance);
			IUpgradable gear = (IUpgradable)((obj is IUpgradable) ? obj : null);
			UpgradeSolver.Instance.OnUpgradeWindowOpen((IUpgradeWindow)(object)__instance, gear, (MonoBehaviour)(object)GridSolverPlugin.Instance);
		}
	}

	[HarmonyPatch(typeof(GearDetailsWindow), "OnCloseCallback")]
	public static class GearDetailsWindowClosePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			UpgradeSolver.Instance.OnUpgradeWindowClosed();
		}
	}

	[HarmonyPatch(typeof(OuroGearWindow), "OnOpen")]
	public static class OuroGearWindowPatch
	{
		[HarmonyPostfix]
		public static void Postfix(OuroGearWindow __instance)
		{
			object? obj = _selectedGearField?.GetValue(__instance);
			IUpgradable gear = (IUpgradable)((obj is IUpgradable) ? obj : null);
			UpgradeSolver.Instance.OnUpgradeWindowOpen((IUpgradeWindow)(object)__instance, gear, (MonoBehaviour)(object)GridSolverPlugin.Instance);
		}
	}

	[HarmonyPatch(typeof(OuroGearWindow), "OnCloseCallback")]
	public static class OuroGearWindowClosePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			UpgradeSolver.Instance.OnUpgradeWindowClosed();
		}
	}

	private static readonly PropertyInfo _upgradablePrefabProperty = typeof(GearDetailsWindow).GetProperty("UpgradablePrefab", BindingFlags.Instance | BindingFlags.Public);

	private static readonly FieldInfo _selectedGearField = typeof(OuroGearWindow).GetField("selectedGear", BindingFlags.Instance | BindingFlags.NonPublic);
}
public class SolverUI
{
	private readonly Color _defaultSecondaryColor = new Color(0.9434f, 0.9434f, 0.9434f, 1f);

	private readonly Color _grayedOutColor = new Color(0.9434f, 0.9434f, 0.9434f, 0.1484f);

	internal IUpgradeWindow? UpgradeWindow;

	internal IUpgradable? CurrentGear;

	private readonly Dictionary<int, UnityEvent> _originalOnHoverEnters = new Dictionary<int, UnityEvent>();

	private Dictionary<int, GearUpgradeUI> _selectedUpgrades = new Dictionary<int, GearUpgradeUI>();

	private GearUpgradeUI? _hoveredUpgrade;

	private bool _showSolveButton;

	private bool _solveButtonEnabled;

	private readonly HashSet<UpgradeInstance> _toggledThisSession = new HashSet<UpgradeInstance>();

	private readonly InputActionMap _solverControls;

	private readonly InputAction _addForSolve;

	private bool _barRegistered;

	private bool _lastSolveEnabled;

	private bool _lastCancelEnabled;

	private bool _lastClearEnabled;

	private bool _buttonStateInitialized;

	private static FieldInfo? GetPrivateField(string name, Type type)
	{
		try
		{
			return type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
		}
		catch
		{
			return null;
		}
	}

	public SolverUI(IUpgradeWindow? upgradeWindow, IUpgradable? currentGear)
	{
		//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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		UpgradeWindow = upgradeWindow;
		CurrentGear = currentGear;
		_solverControls = new InputActionMap("SolverControls");
		_addForSolve = InputActionSetupExtensions.AddAction(_solverControls, "AddForSolve", (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);
		InputActionSetupExtensions.AddBinding(_addForSolve, "<Keyboard>/n", (string)null, (string)null, (string)null);
	}

	internal void OnWindowOpened()
	{
		_showSolveButton = true;
		_solveButtonEnabled = false;
		EnsureButtons();
		RefreshButtonStates();
	}

	internal void EnsureBarIfNeeded()
	{
		if (GearActionBar.IsGearMenuOpen())
		{
			_showSolveButton = true;
			EnsureButtons();
			RefreshButtonStates();
		}
	}

	private void SelectUpgrade()
	{
		//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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: 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_01f8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_hoveredUpgrade == (Object)null || !((HoverInfoUpgrade)_hoveredUpgrade).Upgrade.IsUnlocked)
		{
			return;
		}
		UpgradeInstance upgrade = ((HoverInfoUpgrade)_hoveredUpgrade).Upgrade;
		RarityData val = Global.Instance.Rarities[upgrade.Upgrade.Rarity];
		FieldInfo privateField = GetPrivateField("button", typeof(GearUpgradeUI));
		FieldInfo idField = GetPrivateField("upgradeID", typeof(Upgrade));
		FieldInfo privateField2 = GetPrivateField("hoverColor", typeof(DefaultButton));
		if (privateField == null)
		{
			return;
		}
		if (_selectedUpgrades.TryGetValue(upgrade.InstanceID, out var value))
		{
			object? value2 = privateField.GetValue(value);
			DefaultButton val2 = (DefaultButton)((value2 is DefaultButton) ? value2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.SetDefaultColor(val.backgroundColor);
			}
			_selectedUpgrades.Remove(upgrade.InstanceID);
			_solveButtonEnabled = _selectedUpgrades.Count > 0;
			RefreshButtonStates();
			return;
		}
		if (!upgrade.CanStack)
		{
			GearUpgradeUI val3 = ((IEnumerable<GearUpgradeUI>)_selectedUpgrades.Values).FirstOrDefault((Func<GearUpgradeUI, bool>)((GearUpgradeUI u) => !upgrade.CanStack && idField != null && (int)idField.GetValue(((HoverInfoUpgrade)u).Upgrade) == (int)idField.GetValue(upgrade.Upgrade)));
			if ((Object)(object)val3 != (Object)null)
			{
				Color backgroundColor = Global.Instance.Rarities[((HoverInfoUpgrade)val3).Upgrade.Upgrade.Rarity].backgroundColor;
				object? value3 = privateField.GetValue(val3);
				DefaultButton val4 = (DefaultButton)((value3 is DefaultButton) ? value3 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					val4.SetDefaultColor(backgroundColor);
				}
				_selectedUpgrades.Remove(((HoverInfoUpgrade)val3).Upgrade.InstanceID);
			}
		}
		object? value4 = privateField.GetValue(_hoveredUpgrade);
		DefaultButton val5 = (DefaultButton)((value4 is DefaultButton) ? value4 : null);
		if ((Object)(object)val5 != (Object)null && privateField2 != null)
		{
			Color? val6 = privateField2.GetValue(val5) as Color?;
			if (val6.HasValue)
			{
				val5.SetDefaultColor(val6.Value);
			}
		}
		_selectedUpgrades[upgrade.InstanceID] = _hoveredUpgrade;
		_solveButtonEnabled = true;
		RefreshButtonStates();
	}

	internal void RebuildSelectedUpgrades()
	{
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		if (UpgradeWindow == null)
		{
			return;
		}
		FieldInfo privateField = GetPrivateField("upgradeListParent", ((object)UpgradeWindow).GetType());
		FieldInfo privateField2 = GetPrivateField("button", typeof(GearUpgradeUI));
		FieldInfo privateField3 = GetPrivateField("hoverColor", typeof(DefaultButton));
		if (privateField == null || privateField2 == null)
		{
			return;
		}
		object? value = privateField.GetValue(UpgradeWindow);
		Transform val = (Transform)((value is Transform) ? value : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		List<GearUpgradeUI> source = (from x in ((Component)val).GetComponentsInChildren<GearUpgradeUI>()
			where _selectedUpgrades.ContainsKey(((HoverInfoUpgrade)x).Upgrade.InstanceID)
			select x).ToList();
		_selectedUpgrades = source.ToDictionary((GearUpgradeUI ui) => ((HoverInfoUpgrade)ui).Upgrade.InstanceID);
		foreach (KeyValuePair<int, GearUpgradeUI> selectedUpgrade in _selectedUpgrades)
		{
			object? value2 = privateField2.GetValue(selectedUpgrade.Value);
			DefaultButton val2 = (DefaultButton)((value2 is DefaultButton) ? value2 : null);
			Color? val3 = privateField3?.GetValue(val2) as Color?;
			if ((Object)(object)val2 != (Object)null && val3.HasValue)
			{
				val2.SetDefaultColor(val3.Value);
			}
		}
		_solveButtonEnabled = _selectedUpgrades.Count > 0;
		RefreshButtonStates();
	}

	internal void Close()
	{
		_solverControls.Disable();
		_showSolveButton = false;
		_originalOnHoverEnters.Clear();
		_selectedUpgrades.Clear();
		Coroutine solverCoroutine = UpgradeSolver.Instance.SolverCoroutine;
		if (solverCoroutine != null)
		{
			((MonoBehaviour)GridSolverPlugin.Instance).StopCoroutine(solverCoroutine);
		}
		RefreshButtonStates();
	}

	internal void Update()
	{
		if (Keyboard.current != null)
		{
			if (!((ButtonControl)Keyboard.current.nKey).isPressed)
			{
				if (_toggledThisSession.Count > 0)
				{
					_toggledThisSession.Clear();
				}
			}
			else
			{
				GearUpgradeUI val = null;
				if (UIRaycaster.RaycastForComponent<GearUpgradeUI>(ref val))
				{
					UpgradeInstance upgrade = ((HoverInfoUpgrade)val).Upgrade;
					if (upgrade != null && !_toggledThisSession.Contains(upgrade))
					{
						_hoveredUpgrade = val;
						SelectUpgrade();
						_toggledThisSession.Add(upgrade);
					}
				}
			}
		}
		GearActionBar.Tick();
		EnsureBarIfNeeded();
	}

	private void EnsureButtons()
	{
		if (!_barRegistered)
		{
			GearActionBar.Register("solve", "Solve", 20, (Action)OnSolveClicked, (UIButtonStyle)1);
			GearActionBar.Register("cancel_solve", "Cancel", 30, (Action)OnCancelClicked, (UIButtonStyle)2);
			GearActionBar.Register("clear_selection", "Deselect", 40, (Action)OnClearClicked, (UIButtonStyle)0);
			GearActionBar.SetSlotVisible("solve", true);
			GearActionBar.SetSlotVisible("cancel_solve", true);
			GearActionBar.SetSlotVisible("clear_selection", true);
			_barRegistered = true;
		}
	}

	private void RefreshButtonStates()
	{
		if (_barRegistered)
		{
			bool flag = UpgradeSolver.Instance != null && UpgradeSolver.Instance.SolverCoroutine != null;
			bool flag2 = _solveButtonEnabled && !flag;
			bool flag3 = flag;
			bool flag4 = _selectedUpgrades.Count > 0 && !flag;
			if (!_buttonStateInitialized || flag2 != _lastSolveEnabled || flag3 != _lastCancelEnabled || flag4 != _lastClearEnabled)
			{
				_buttonStateInitialized = true;
				_lastSolveEnabled = flag2;
				_lastCancelEnabled = flag3;
				_lastClearEnabled = flag4;
				GearActionBar.SetInteractable("solve", flag2);
				GearActionBar.SetInteractable("cancel_solve", flag3);
				GearActionBar.SetInteractable("clear_selection", flag4);
			}
		}
	}

	private void OnSolveClicked()
	{
		if (UpgradeWindow == null || !_solveButtonEnabled || UpgradeSolver.Instance.SolverCoroutine != null)
		{
			return;
		}
		foreach (GearUpgradeUI value in _selectedUpgrades.Values)
		{
			GridSolverPlugin.Logger.LogInfo((object)("\t • " + FormatUpgrade(value)));
		}
		List<UpgradeInstance> upgrades = (from u in _selectedUpgrades
			select ((HoverInfoUpgrade)u.Value).Upgrade into u
			orderby (!(u.Upgrade.Name == "Boundary Incursion")) ? u.GetPattern(false).GetCellCount() : int.MaxValue descending
			select u).ToList();
		Solver solver = new Solver(UpgradeWindow, CurrentGear, upgrades);
		if (!solver.CanFitAll())
		{
			UIDialog.Alert("Solve Error", "The selected upgrades cannot fit in the available space.", (Action)null, "OK");
			return;
		}
		solver.TrySolve(delegate(bool success)
		{
			GridSolverPlugin.Logger.LogInfo((object)(success ? "Found a solution" : "No solution"));
			ResetSelectionColors();
			_selectedUpgrades.Clear();
			_solveButtonEnabled = false;
			UpgradeSolver.Instance.SolverCoroutine = null;
			RefreshButtonStates();
		});
		RefreshButtonStates();
	}

	private void OnCancelClicked()
	{
		if (UpgradeSolver.Instance.SolverCoroutine != null)
		{
			((MonoBehaviour)GridSolverPlugin.Instance).StopCoroutine(UpgradeSolver.Instance.SolverCoroutine);
			UpgradeSolver.Instance.SolverCoroutine = null;
			RefreshButtonStates();
		}
	}

	private void OnClearClicked()
	{
		ResetSelectionColors();
		_selectedUpgrades.Clear();
		_solveButtonEnabled = false;
		RefreshButtonStates();
	}

	private void ResetSelectionColors()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		FieldInfo privateField = GetPrivateField("button", typeof(GearUpgradeUI));
		foreach (GearUpgradeUI value in _selectedUpgrades.Values)
		{
			RarityData val = Global.Instance.Rarities[((HoverInfoUpgrade)value).Upgrade.Upgrade.Rarity];
			object? obj = privateField?.GetValue(value);
			DefaultButton val2 = (DefaultButton)((obj is DefaultButton) ? obj : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.SetDefaultColor(val.backgroundColor);
			}
		}
	}

	private static string FormatUpgrade(GearUpgradeUI upgrade)
	{
		UpgradeInstance upgrade2 = ((HoverInfoUpgrade)upgrade).Upgrade;
		return $"[{upgrade2.Upgrade.RarityName}] {upgrade2.Upgrade.Name} ({upgrade2.InstanceID})";
	}

	internal void PatchUpgradeClick()
	{
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Expected O, but got Unknown
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Expected O, but got Unknown
		if (UpgradeWindow == null)
		{
			return;
		}
		_solverControls.Enable();
		FieldInfo privateField = GetPrivateField("upgradeListParent", ((object)UpgradeWindow).GetType());
		FieldInfo privateField2 = GetPrivateField("button", typeof(GearUpgradeUI));
		if (privateField == null || privateField2 == null)
		{
			return;
		}
		object? value = privateField.GetValue(UpgradeWindow);
		Transform val = (Transform)((value is Transform) ? value : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		foreach (GearUpgradeUI upgradeUI in (from x in ((Component)val).GetComponentsInChildren<GearUpgradeUI>()
			where ((Component)x).gameObject.activeSelf
			select x).ToList())
		{
			object? value2 = privateField2.GetValue(upgradeUI);
			DefaultButton val2 = (DefaultButton)((value2 is DefaultButton) ? value2 : null);
			if (val2 == null)
			{
				continue;
			}
			int instanceID = ((HoverInfoUpgrade)upgradeUI).Upgrade.InstanceID;
			if (!_originalOnHoverEnters.ContainsKey(instanceID))
			{
				UnityEvent onHoverEnter = ((Button)val2).OnHoverEnter;
				_originalOnHoverEnters[instanceID] = onHoverEnter;
				((Button)val2).OnHoverExit.AddListener((UnityAction)delegate
				{
					_hoveredUpgrade = null;
				});
				((Button)val2).OnHoverEnter.AddListener((UnityAction)delegate
				{
					_hoveredUpgrade = upgradeUI;
				});
			}
		}
	}

	public void OnGUI()
	{
	}
}
public static class HexMapUtils
{
	private static readonly FieldInfo _hexMapWidthField = typeof(HexMap).GetField("width", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo _hexMapHeightField = typeof(HexMap).GetField("height", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo _hexMapNodesField = typeof(HexMap).GetField("nodes", BindingFlags.Instance | BindingFlags.NonPublic);

	public static HexMap CloneHexMap(HexMap original)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		if (original == null)
		{
			return null;
		}
		int num = (int)_hexMapWidthField.GetValue(original);
		int num2 = (int)_hexMapHeightField.GetValue(original);
		HexMap val = new HexMap(num, num2);
		for (int i = 0; i < num2; i++)
		{
			for (int j = 0; j < num; j++)
			{
				val[j, i] = original[j, i];
			}
		}
		return val;
	}

	public static HexMap CanonicalizeHexMap(HexMap map)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Expected O, but got Unknown
		//IL_00d2: 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)
		if (map == null)
		{
			return null;
		}
		int num = (int)_hexMapWidthField.GetValue(map);
		int num2 = (int)_hexMapHeightField.GetValue(map);
		int num3 = int.MaxValue;
		int num4 = int.MaxValue;
		bool flag = false;
		for (int i = 0; i < num2; i++)
		{
			for (int j = 0; j < num; j++)
			{
				if (map[j, i].enabled)
				{
					if (j < num3)
					{
						num3 = j;
					}
					if (i < num4)
					{
						num4 = i;
					}
					flag = true;
				}
			}
		}
		if (!flag)
		{
			return CloneHexMap(map);
		}
		int num5 = num - num3;
		int num6 = num2 - num4;
		HexMap val = new HexMap(num5, num6);
		for (int k = 0; k < num2; k++)
		{
			for (int l = 0; l < num; l++)
			{
				if (map[l, k].enabled)
				{
					int num7 = l - num3;
					int num8 = k - num4;
					val[num7, num8] = map[l, k];
				}
			}
		}
		return val;
	}

	public static bool HexMapsEqual(HexMap a, HexMap b)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_0088: 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_0091: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		if (a == null && b == null)
		{
			return true;
		}
		if (a == null || b == null)
		{
			return false;
		}
		int num = (int)_hexMapWidthField.GetValue(a);
		int num2 = (int)_hexMapHeightField.GetValue(a);
		int num3 = (int)_hexMapWidthField.GetValue(b);
		int num4 = (int)_hexMapHeightField.GetValue(b);
		if (num != num3 || num2 != num4)
		{
			return false;
		}
		for (int i = 0; i < num2; i++)
		{
			for (int j = 0; j < num; j++)
			{
				Node val = a[j, i];
				Node val2 = b[j, i];
				if (val.enabled != val2.enabled || (val.enabled && val.connections != val2.connections))
				{
					return false;
				}
			}
		}
		return true;
	}
}
public class Offset(int offsetX, int offsetY)
{
	public readonly int OffsetX = offsetX;

	public readonly int OffsetY = offsetY;
}
public class Solver
{
	private static readonly FieldInfo _modifiedMapWidthField = GetPrivateField("width", typeof(HexMap));

	private static readonly FieldInfo _modifiedMapHeightField = GetPrivateField("height", typeof(HexMap));

	private static readonly FieldInfo _hexMapWidthField = GetPrivateField("width", typeof(HexMap));

	private static readonly FieldInfo _hexMapHeightField = GetPrivateField("height", typeof(HexMap));

	private readonly IUpgradeWindow _upgradeWindow;

	private readonly List<UpgradeInstance> _upgrades;

	private readonly IUpgradable _gear;

	private readonly ModuleEquipSlots _equipSlots;

	private readonly HexMap _hexMap;

	private readonly int _maxRotations = ((!PlayerData.Instance.canRotateUpgrades) ? 1 : 6);

	private readonly Dictionary<Tuple<UpgradeInstance, int>, Offset> _offsetCache = new Dictionary<Tuple<UpgradeInstance, int>, Offset>();

	private readonly Dictionary<UpgradeInstance, List<int>> _uniqueRotationsCache = new Dictionary<UpgradeInstance, List<int>>();

	private bool _foundSolution;

	private static FieldInfo? GetPrivateField(string name, Type type)
	{
		try
		{
			return type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
		}
		catch
		{
			return null;
		}
	}

	public Solver(IUpgradeWindow upgradeWindow, IUpgradable gear, List<UpgradeInstance> upgrades)
	{
		_upgradeWindow = upgradeWindow;
		_upgrades = upgrades;
		_gear = gear;
		ref ModuleEquipSlots equipSlots = ref _equipSlots;
		object? obj = GetPrivateField("equipSlots", ((object)upgradeWindow).GetType())?.GetValue(upgradeWindow);
		equipSlots = (ModuleEquipSlots)((obj is ModuleEquipSlots) ? obj : null);
		FieldInfo privateField = GetPrivateField("hexMap", typeof(ModuleEquipSlots));
		if ((Object)(object)_equipSlots != (Object)null && privateField != null)
		{
			ref HexMap hexMap = ref _hexMap;
			object? value = privateField.GetValue(_equipSlots);
			hexMap = (HexMap)((value is HexMap) ? value : null);
		}
		Dictionary<string, List<UpgradeInstance>> dictionary = new Dictionary<string, List<UpgradeInstance>>();
		foreach (UpgradeInstance upgrade in _upgrades)
		{
			HexMap pattern = upgrade.GetPattern(false);
			string hexMapKey = GetHexMapKey(HexMapUtils.CanonicalizeHexMap(pattern));
			if (!dictionary.ContainsKey(hexMapKey))
			{
				dictionary[hexMapKey] = new List<UpgradeInstance>();
			}
			dictionary[hexMapKey].Add(upgrade);
			_uniqueRotationsCache[upgrade] = GetUniqueRotations(upgrade);
		}
		foreach (KeyValuePair<string, List<UpgradeInstance>> item in dictionary)
		{
			if (item.Value.Count > 1)
			{
				string.Join(", ", item.Value.Select((UpgradeInstance u) => u.Upgrade.Name));
			}
		}
	}

	private List<int> GetUniqueRotations(UpgradeInstance upgrade)
	{
		HexMap pattern = upgrade.GetPattern(false);
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		List<int> list = new List<int>();
		for (int i = 0; i < _maxRotations; i++)
		{
			HexMap map = HexMapUtils.CanonicalizeHexMap(pattern.GetModifiedMap(i, (HexMap)null));
			string hexMapKey = GetHexMapKey(map);
			if (!dictionary.ContainsKey(hexMapKey))
			{
				dictionary[hexMapKey] = i;
				list.Add(i);
			}
		}
		return list;
	}

	private string GetHexMapKey(HexMap map)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected I4, but got Unknown
		if (map == null)
		{
			return "";
		}
		int num = (int)_hexMapWidthField.GetValue(map);
		int num2 = (int)_hexMapHeightField.GetValue(map);
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < num2; i++)
		{
			for (int j = 0; j < num; j++)
			{
				Node val = map[j, i];
				stringBuilder.Append(val.enabled ? '1' : '0');
				stringBuilder.Append((int)val.connections);
				stringBuilder.Append(',');
			}
			stringBuilder.Append(';');
		}
		return stringBuilder.ToString();
	}

	private Offset GetOffsetsCached(UpgradeInstance upgrade, int rotation, UpgradeEquipCell cell)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		Tuple<UpgradeInstance, int> key = new Tuple<UpgradeInstance, int>(upgrade, rotation);
		if (_offsetCache.TryGetValue(key, out var value))
		{
			return new Offset(cell.X + value.offsetX, cell.Y + value.offsetY);
		}
		HexMap modifiedMap = upgrade.GetPattern(false).GetModifiedMap(rotation, (HexMap)null);
		int num = ((_modifiedMapWidthField != null) ? ((int)_modifiedMapWidthField.GetValue(modifiedMap)) : 8) / 2;
		int num2 = 0;
		int num3 = 0;
		for (int i = 0; i < ((_modifiedMapHeightField != null) ? ((int)_modifiedMapHeightField.GetValue(modifiedMap)) : 8); i++)
		{
			if (modifiedMap[num, i].enabled)
			{
				num2 += i;
				num3++;
			}
		}
		int num4 = -((num3 > 0) ? (num2 / num3) : 0);
		if (num % 2 == 1)
		{
			num4--;
		}
		value = new Offset(-num, num4);
		_offsetCache[key] = value;
		return new Offset(cell.X + value.offsetX, cell.Y + value.offsetY);
	}

	private void ClearSlots()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		if ((Object)(object)_equipSlots == (Object)null)
		{
			return;
		}
		IUpgradable gear = _gear;
		List<UpgradeInfo> allUpgrades = PlayerData.GetAllUpgrades(gear, true);
		List<UpgradeInfo> second = new List<UpgradeInfo>();
		if ((int)gear.GearType == 5)
		{
			second = PlayerData.GetAllUpgrades((IUpgradable)(object)Global.Instance, true);
		}
		foreach (UpgradeInfo item in from u in allUpgrades.Concat(second)
			where u != null
			select u)
		{
			if (item.Instances == null)
			{
				continue;
			}
			foreach (UpgradeInstance item2 in item.Instances.OfType<UpgradeInstance>())
			{
				_equipSlots.Unequip(gear, item2);
			}
		}
	}

	private IEnumerator SolveDfs(int index)
	{
		if ((Object)(object)_equipSlots == (Object)null)
		{
			_foundSolution = false;
			yield break;
		}
		if (index >= _upgrades.Count)
		{
			_foundSolution = true;
			yield break;
		}
		UpgradeInstance upgrade = _upgrades[index];
		List<int> uniqueRotations = _uniqueRotationsCache[upgrade];
		for (int y = 0; y < ((_hexMap != null && _hexMapHeightField != null) ? ((int)_hexMapHeightField.GetValue(_hexMap)) : 8); y++)
		{
			for (int x = 0; x < ((_hexMap != null && _hexMapWidthField != null) ? ((int)_hexMapWidthField.GetValue(_hexMap)) : 8); x++)
			{
				foreach (int item in uniqueRotations)
				{
					UpgradeEquipCell val = null;
					try
					{
						val = _equipSlots.GetCell(x, y);
					}
					catch
					{
					}
					if (val == null || ((HoverInfoUpgrade)val).Upgrade != null)
					{
						continue;
					}
					Offset offsetsCached = GetOffsetsCached(upgrade, item, val);
					int offsetX = offsetsCached.offsetX;
					int offsetY = offsetsCached.offsetY;
					int num = offsetX;
					if (_equipSlots.EquipModule(_gear, upgrade, num, offsetY, (byte)item, true, false))
					{
						yield return SolveDfs(index + 1);
						if (_foundSolution)
						{
							yield break;
						}
						_equipSlots.Unequip(_gear, upgrade);
					}
				}
			}
		}
	}

	private IEnumerator SolveAndNotify(Action<bool> onComplete)
	{
		yield return SolveDfs(0);
		onComplete(_foundSolution);
	}

	public void TrySolve(Action<bool> onComplete)
	{
		_foundSolution = false;
		ClearSlots();
		if (!CanFitAll())
		{
			onComplete(obj: false);
		}
		else
		{
			UpgradeSolver.Instance.SolverCoroutine = ((MonoBehaviour)GridSolverPlugin.Instance).StartCoroutine(SolveAndNotify(onComplete));
		}
	}

	public bool CanFitAll()
	{
		if (_hexMap == null)
		{
			return true;
		}
		UpgradeInstance boundary = ((IEnumerable<UpgradeInstance>)_upgrades).FirstOrDefault((Func<UpgradeInstance, bool>)((UpgradeInstance u) => u.Upgrade.Name == "Boundary Incursion"));
		if (boundary != null)
		{
			bool flag = false;
			int num = ((_hexMapHeightField != null) ? ((int)_hexMapHeightField.GetValue(_hexMap)) : 8);
			int num2 = ((_hexMapWidthField != null) ? ((int)_hexMapWidthField.GetValue(_hexMap)) : 8);
			for (int num3 = 0; num3 < num; num3++)
			{
				if (flag)
				{
					break;
				}
				for (int num4 = 0; num4 < num2; num4++)
				{
					if (flag)
					{
						break;
					}
					foreach (int item in _uniqueRotationsCache.ContainsKey(boundary) ? _uniqueRotationsCache[boundary] : new List<int> { 0 })
					{
						UpgradeEquipCell val = null;
						try
						{
							val = _equipSlots.GetCell(num4, num3);
						}
						catch
						{
						}
						if ((Object)(object)val != (Object)null && ((HoverInfoUpgrade)val).Upgrade == null)
						{
							Offset offsetsCached = GetOffsetsCached(boundary, item, val);
							if (_equipSlots.EquipModule(_gear, boundary, offsetsCached.offsetX, offsetsCached.offsetY, (byte)item, true, false))
							{
								flag = true;
								break;
							}
						}
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			int num5 = ((_hexMapHeightField != null) ? ((int)_hexMapHeightField.GetValue(_hexMap)) : 8);
			int num6 = ((_hexMapWidthField != null) ? ((int)_hexMapWidthField.GetValue(_hexMap)) : 8);
			int num7 = num5 * num6;
			bool result = (from u in _upgrades
				where u != boundary
				select u.GetPattern(false).GetCellCount()).Sum() <= num7;
			_equipSlots.Unequip(_gear, boundary);
			return result;
		}
		int num8 = ((_hexMapHeightField != null) ? ((int)_hexMapHeightField.GetValue(_hexMap)) : 8);
		int num9 = ((_hexMapWidthField != null) ? ((int)_hexMapWidthField.GetValue(_hexMap)) : 8);
		int num10 = num8 * num9;
		return _upgrades.Select((UpgradeInstance u) => u.GetPattern(false).GetCellCount()).Sum() <= num10;
	}
}
namespace GridSolverPlus
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "GridSolverPlus";

		public const string PLUGIN_NAME = "GridSolverPlus";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}