Decompiled source of TogglerPlus v0.1.1

plugins\StonewardsTogglerPlus.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UIElements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("StonewardsTogglerPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+6557580b83d29caabaf930de35fe95c20191b641")]
[assembly: AssemblyProduct("StonewardsTogglerPlus")]
[assembly: AssemblyTitle("StonewardsTogglerPlus")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
}
namespace StonewardsTogglerPlus
{
	[BepInPlugin("com.thereisnouser.stonewards.togglerplus", "Stonewards Toggler Plus", "0.1.1")]
	public sealed class TogglerPlusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.thereisnouser.stonewards.togglerplus";

		private const string AddedClass = "stonewards-tp-default";

		private static TogglerPlusPlugin _plugin;

		private Harmony _harmony;

		private static Type _menuType;

		private static Type _buttonType;

		private static Type _upgradeCategoryType;

		private static FieldInfo _menuManager;

		private static FieldInfo _menuTemplate;

		private static FieldInfo _menuArchetypes;

		private static FieldInfo _buttonUnlockable;

		private static FieldInfo _buttonCanClick;

		private static MethodInfo _getAvailable;

		private static MethodInfo _buttonInit;

		private static MethodInfo _buttonSetUpgrade;

		private static MethodInfo _buttonEnableToggle;

		private static MethodInfo _showUnlockable;

		private static MethodInfo _getTogglerLevel;

		private static readonly HashSet<string> Warnings = new HashSet<string>();

		private void Awake()
		{
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			_plugin = this;
			_menuType = AccessTools.TypeByName("UnlockableMenu");
			_buttonType = AccessTools.TypeByName("UnlockUpgradeButton");
			_upgradeCategoryType = AccessTools.TypeByName("UpgradeCategory");
			Type type = AccessTools.TypeByName("UpgradeManager");
			Type type2 = AccessTools.TypeByName("UnlockableManager");
			if (_menuType == null || _buttonType == null || _upgradeCategoryType == null || type == null || type2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Stonewards upgrade types not found. Toggler Plus disabled for this game build.");
				return;
			}
			_menuManager = AccessTools.Field(_menuType, "upgradeManager");
			_menuTemplate = AccessTools.Field(_menuType, "unlockableButtonTemplate");
			_menuArchetypes = AccessTools.Field(_menuType, "archetypeDatabaseSo");
			_buttonUnlockable = AccessTools.Field(_buttonType, "unlockable");
			_buttonCanClick = AccessTools.Field(_buttonType, "canClick");
			_getAvailable = AccessTools.Method(type, "GetAvailableUpgrades", (Type[])null, (Type[])null);
			_buttonInit = AccessTools.Method(_buttonType, "Init", (Type[])null, (Type[])null);
			_buttonSetUpgrade = AccessTools.Method(_buttonType, "SetUpgrade", (Type[])null, (Type[])null);
			_buttonEnableToggle = AccessTools.Method(_buttonType, "EnableToggle", (Type[])null, (Type[])null);
			_showUnlockable = AccessTools.Method(_menuType, "ShowUnlockable", (Type[])null, (Type[])null);
			_getTogglerLevel = AccessTools.Method(type2, "GetUpgradableTogglerLevel", (Type[])null, (Type[])null);
			if (_menuManager == null || _menuTemplate == null || _menuArchetypes == null || _buttonUnlockable == null || _buttonCanClick == null || _getAvailable == null || _buttonInit == null || _buttonSetUpgrade == null || _buttonEnableToggle == null || _showUnlockable == null || _getTogglerLevel == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Upgrade UI API has changed; no UI patches installed.");
				return;
			}
			_harmony = new Harmony("com.thereisnouser.stonewards.togglerplus");
			Patch("InitUI", "AfterMenuBuilt", null);
			Patch("RebuildShopButtons", "AfterMenuBuilt", null);
			Patch("Show", "AfterShow", new Type[1] { typeof(bool) });
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Toggler Plus initialized. Default rings/tomes will be added to the existing shop UI.");
		}

		private void Patch(string methodName, string postfixName, Type[] arguments)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = ((arguments == null) ? AccessTools.Method(_menuType, methodName, (Type[])null, (Type[])null) : AccessTools.Method(_menuType, methodName, arguments, (Type[])null));
				if (methodInfo == null)
				{
					WarnOnce("patch:" + methodName, "Method not found: UnlockableMenu." + methodName);
					return;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(TogglerPlusPlugin), postfixName, (Type[])null, (Type[])null);
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Patched UnlockableMenu." + methodName));
			}
			catch (Exception ex)
			{
				WarnOnce("patch:" + methodName, "Could not patch UnlockableMenu." + methodName + ": " + ex);
			}
		}

		private static void AfterMenuBuilt(object __instance)
		{
			TryAppendDefaults(__instance);
		}

		private static void AfterShow(object __instance, bool _Show)
		{
			if (_Show)
			{
				TryAppendDefaults(__instance);
			}
		}

		private static void TryAppendDefaults(object menu)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_plugin == (Object)null || menu == null)
			{
				return;
			}
			try
			{
				Component val = (Component)((menu is Component) ? menu : null);
				UIDocument val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<UIDocument>() : null);
				VisualElement val3 = (((Object)(object)val2 != (Object)null) ? val2.rootVisualElement : null);
				object value = _menuManager.GetValue(menu);
				object? value2 = _menuTemplate.GetValue(menu);
				VisualTreeAsset val4 = (VisualTreeAsset)((value2 is VisualTreeAsset) ? value2 : null);
				if (val3 == null || value == null || (Object)(object)val4 == (Object)null)
				{
					return;
				}
				Dictionary<string, VisualElement> dictionary = new Dictionary<string, VisualElement>(StringComparer.Ordinal);
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				foreach (VisualElement item in UQueryExtensions.Query<VisualElement>(val3, (string)null, (string)null).ToList())
				{
					if (!_buttonType.IsInstanceOfType(item) || item.parent == null)
					{
						continue;
					}
					object value3 = _buttonUnlockable.GetValue(item);
					string text = ReadString(value3, "ID");
					if (!string.IsNullOrEmpty(text))
					{
						hashSet.Add(text);
					}
					if (item.ClassListContains("stonewards-tp-default"))
					{
						RefreshAddedToggle(item);
						continue;
					}
					object value4 = _buttonCanClick.GetValue(item);
					if (value4 is bool && (bool)value4)
					{
						if (value3 != null && ReadString(value3, "UpgradeCategory") != null && !ReadBool(value3, "Unlockable", fallback: true) && !ReadBool(value3, "HiddenUpgrade", fallback: false))
						{
							RefreshAddedToggle(item);
						}
						string text2 = ReadString(value3, "Category");
						if ((text2 == "LEVELUP" || text2 == "PICKUP") && !dictionary.ContainsKey(text2))
						{
							dictionary.Add(text2, item.parent);
						}
					}
				}
				AppendCategory(menu, value, val4, dictionary, hashSet, 0, "LEVELUP");
				AppendCategory(menu, value, val4, dictionary, hashSet, 1, "PICKUP");
			}
			catch (Exception ex)
			{
				WarnOnce("inject", "Failed to add default upgrade buttons: " + ex);
			}
		}

		private static void AppendCategory(object menu, object manager, VisualTreeAsset template, Dictionary<string, VisualElement> categoryParents, HashSet<string> alreadyPresent, int categoryValue, string categoryName)
		{
			if (!categoryParents.TryGetValue(categoryName, out var value))
			{
				WarnOnce("missing:" + categoryName, "No existing " + categoryName + " button to locate its vanilla grid. Try opening the unlock shop with some upgrades in this category.");
				return;
			}
			object obj = Enum.ToObject(_upgradeCategoryType, categoryValue);
			if (!(_getAvailable.Invoke(manager, new object[1] { obj }) is IEnumerable enumerable))
			{
				return;
			}
			object value2 = _menuArchetypes.GetValue(menu);
			int num = 0;
			foreach (object item in enumerable)
			{
				if (item == null || ReadBool(item, "Unlockable", fallback: true) || ReadBool(item, "HiddenUpgrade", fallback: false))
				{
					continue;
				}
				string text = ReadString(item, "ID");
				if (string.IsNullOrEmpty(text) || alreadyPresent.Contains(text))
				{
					continue;
				}
				object? obj2 = Activator.CreateInstance(_buttonType, nonPublic: true);
				VisualElement val = (VisualElement)((obj2 is VisualElement) ? obj2 : null);
				if (val != null)
				{
					template.CloneTree(val);
					_buttonInit.Invoke(val, new object[3] { manager, value2, true });
					_buttonSetUpgrade.Invoke(val, new object[1] { item });
					val.AddToClassList("stonewards-tp-default");
					RefreshAddedToggle(val);
					VisualElement currentCard = val;
					object currentUpgrade = item;
					((CallbackEventHandler)val).RegisterCallback<ClickEvent>((EventCallback<ClickEvent>)delegate
					{
						ShowDetails(menu, currentUpgrade, currentCard);
					}, (TrickleDown)0);
					((CallbackEventHandler)val).RegisterCallback<NavigationSubmitEvent>((EventCallback<NavigationSubmitEvent>)delegate
					{
						ShowDetails(menu, currentUpgrade, currentCard);
					}, (TrickleDown)0);
					value.Add(val);
					alreadyPresent.Add(text);
					num++;
				}
			}
			if (num > 0)
			{
				((BaseUnityPlugin)_plugin).Logger.LogInfo((object)("Added " + num + " default " + categoryName + " upgrades."));
			}
		}

		private static void ShowDetails(object menu, object upgrade, VisualElement card)
		{
			try
			{
				_showUnlockable.Invoke(menu, new object[2] { upgrade, card });
			}
			catch (Exception ex)
			{
				WarnOnce("details", "Could not select default upgrade: " + ex);
			}
		}

		private static void RefreshAddedToggle(VisualElement card)
		{
			try
			{
				object obj = AccessTools.Property(AccessTools.TypeByName("UnlockableManager"), "Instance")?.GetValue(null, null);
				object value = _buttonCanClick.GetValue(card);
				bool flag = default(bool);
				int num;
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
				bool flag2 = ((uint)num & (flag ? 1u : 0u)) != 0 && obj != null && Convert.ToInt32(_getTogglerLevel.Invoke(obj, null)) > 0;
				_buttonEnableToggle.Invoke(card, new object[1] { flag2 });
			}
			catch (Exception ex)
			{
				WarnOnce("toggle", "Could not refresh default toggle: " + ex);
			}
		}

		private static string ReadString(object obj, string propertyName)
		{
			if (obj == null)
			{
				return null;
			}
			return AccessTools.Property(obj.GetType(), propertyName)?.GetValue(obj, null)?.ToString();
		}

		private static bool ReadBool(object obj, string propertyName, bool fallback)
		{
			if (obj == null)
			{
				return fallback;
			}
			object obj2 = AccessTools.Property(obj.GetType(), propertyName)?.GetValue(obj, null);
			if (obj2 is bool)
			{
				return (bool)obj2;
			}
			return fallback;
		}

		private static void WarnOnce(string key, string message)
		{
			if ((Object)(object)_plugin != (Object)null && Warnings.Add(key))
			{
				((BaseUnityPlugin)_plugin).Logger.LogWarning((object)message);
			}
		}

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