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 _originalOnHoverEnters = new Dictionary(); private Dictionary _selectedUpgrades = new Dictionary(); private GearUpgradeUI? _hoveredUpgrade; private bool _showSolveButton; private bool _solveButtonEnabled; private readonly HashSet _toggledThisSession = new HashSet(); 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, "/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)_selectedUpgrades.Values).FirstOrDefault((Func)((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 source = (from x in ((Component)val).GetComponentsInChildren() where _selectedUpgrades.ContainsKey(((HoverInfoUpgrade)x).Upgrade.InstanceID) select x).ToList(); _selectedUpgrades = source.ToDictionary((GearUpgradeUI ui) => ((HoverInfoUpgrade)ui).Upgrade.InstanceID); foreach (KeyValuePair 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(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 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() 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 _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, Offset> _offsetCache = new Dictionary, Offset>(); private readonly Dictionary> _uniqueRotationsCache = new Dictionary>(); 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 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> dictionary = new Dictionary>(); foreach (UpgradeInstance upgrade in _upgrades) { HexMap pattern = upgrade.GetPattern(false); string hexMapKey = GetHexMapKey(HexMapUtils.CanonicalizeHexMap(pattern)); if (!dictionary.ContainsKey(hexMapKey)) { dictionary[hexMapKey] = new List(); } dictionary[hexMapKey].Add(upgrade); _uniqueRotationsCache[upgrade] = GetUniqueRotations(upgrade); } foreach (KeyValuePair> item in dictionary) { if (item.Value.Count > 1) { string.Join(", ", item.Value.Select((UpgradeInstance u) => u.Upgrade.Name)); } } } private List GetUniqueRotations(UpgradeInstance upgrade) { HexMap pattern = upgrade.GetPattern(false); Dictionary dictionary = new Dictionary(); List list = new List(); 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 key = new Tuple(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 allUpgrades = PlayerData.GetAllUpgrades(gear, true); List second = new List(); 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()) { _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 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 onComplete) { yield return SolveDfs(0); onComplete(_foundSolution); } public void TrySolve(Action 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)_upgrades).FirstOrDefault((Func)((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 { 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) { } } }