Decompiled source of Upgrade List Enhance v0.1.0

plugins\GastrodonGroup-UpgradeListEnhance\UpgradeListEnhance.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GastrodonGroup.UpgradeListEnhance.Behaviours;
using GastrodonGroup.UpgradeListEnhance.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("GastrodonGroup")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+99644d73c5f5eba0254006439b2f2e344ed28143")]
[assembly: AssemblyProduct("UpgradeListEnhance")]
[assembly: AssemblyTitle("UpgradeListEnhance")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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;
		}
	}
}
namespace GastrodonGroup.UpgradeListEnhance
{
	[BepInPlugin("GastrodonGroup.UpgradeListEnhance", "Upgrade List Enhance", "0.1.0")]
	public class UpgradeListEnhancePlugin : BaseUnityPlugin
	{
		internal const string TextUpgradesUIScaleGuid = "DarkSpider90.TextUpgradesUIScale";

		internal const string DefaultHeaderEnglish = "UPGRADES";

		private Harmony? _harmony;

		internal static UpgradeListEnhancePlugin Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal static ConfigEntry<bool> EnableAlign { get; private set; }

		internal static ConfigEntry<bool> AdjustNames { get; private set; }

		internal static ConfigEntry<float> NameFontSize { get; private set; }

		internal static ConfigEntry<float> NameLineSpacing { get; private set; }

		internal static ConfigEntry<bool> AdjustNumbers { get; private set; }

		internal static ConfigEntry<bool> RewriteNumbersNoBold { get; private set; }

		internal static ConfigEntry<float> NumberFontSizeOffset { get; private set; }

		internal static ConfigEntry<float> NumberLineSpacing { get; private set; }

		internal static ConfigEntry<float> HeaderOffset { get; private set; }

		internal static ConfigEntry<string> HeaderEnglish { get; private set; }

		internal static ConfigEntry<bool> EnablePaging { get; private set; }

		internal static ConfigEntry<int> PageSize { get; private set; }

		internal static ConfigEntry<float> PageCycleSeconds { get; private set; }

		internal static ConfigEntry<bool> ShowPageInHeader { get; private set; }

		internal static ConfigEntry<bool> LogOnFetch { get; private set; }

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			BindConfig();
			if (Chainloader.PluginInfos.ContainsKey("DarkSpider90.TextUpgradesUIScale"))
			{
				Logger.LogInfo((object)"Detected DarkSpider90.TextUpgradesUIScale: layout applies after it on Fetch. If rows still shrink/fight this mod, set TextUpgradesUIScale \"Start shrinking after upgrades count\" to 100 (effectively ignore shrink).");
			}
			_harmony = new Harmony("GastrodonGroup.UpgradeListEnhance");
			_harmony.PatchAll(typeof(StatsUIAlignPatch));
			Logger.LogInfo((object)string.Format("{0} v{1} has loaded! Build: {2}", ((BaseUnityPlugin)this).Info.Metadata.GUID, ((BaseUnityPlugin)this).Info.Metadata.Version, "2026-08-09 17:26"));
		}

		private void BindConfig()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Expected O, but got Unknown
			EnableAlign = ((BaseUnityPlugin)this).Config.Bind<bool>("Align", "EnableAlign", true, "Master switch for StatsUI upgrade-list layout tweaks after Fetch.");
			AdjustNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Align", "AdjustNames", true, "When true, change name-column font size and lineSpacing.");
			NameFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("Align", "NameFontSize", 28f, new ConfigDescription("Font size for the name column (× 名稱).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 48f), Array.Empty<object>()));
			NameLineSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Align", "NameLineSpacing", -50f, new ConfigDescription("ABSOLUTE TMP lineSpacing for names (float OK). Default -50 for English; try about -70 for Traditional Chinese packs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 80f), Array.Empty<object>()));
			AdjustNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Align", "AdjustNumbers", false, "When false, leave number column fontSize/lineSpacing as vanilla (still sliced when paging).");
			RewriteNumbersNoBold = ((BaseUnityPlugin)this).Config.Bind<bool>("Align", "RewriteNumbersNoBold", true, "When AdjustNumbers=true: rewrite page numbers without <b>.");
			NumberFontSizeOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Align", "NumberFontSizeOffset", 0.4f, new ConfigDescription("When AdjustNumbers=true: number fontSize = NameFontSize + this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-10f, 10f), Array.Empty<object>()));
			NumberLineSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Align", "NumberLineSpacing", -50f, new ConfigDescription("When AdjustNumbers=true: ABSOLUTE TMP lineSpacing for numbers (same tip as NameLineSpacing).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, 80f), Array.Empty<object>()));
			HeaderOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Align", "HeaderOffset", 7f, new ConfigDescription("When AdjustNames=true: header fontSize = NameFontSize + this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>()));
			HeaderEnglish = ((BaseUnityPlugin)this).Config.Bind<string>("Align", "HeaderEnglish", "UPGRADES", "Vanilla English header written by this mod (so 漢化 can translate). Page suffix: \"UPGRADES (1/2)\".");
			LogOnFetch = ((BaseUnityPlugin)this).Config.Bind<bool>("Align", "LogOnFetch", false, "Log applied layout / page each StatsUI.Fetch or page change.");
			EnablePaging = ((BaseUnityPlugin)this).Config.Bind<bool>("Paging", "EnablePaging", true, "When active upgrades exceed PageSize, cycle pages over time.");
			PageSize = ((BaseUnityPlugin)this).Config.Bind<int>("Paging", "PageSize", 12, new ConfigDescription("Max upgrades shown per page.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 40), Array.Empty<object>()));
			PageCycleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Paging", "PageCycleSeconds", 3f, new ConfigDescription("Seconds between page switches while the list is visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			ShowPageInHeader = ((BaseUnityPlugin)this).Config.Bind<bool>("Paging", "ShowPageInHeader", true, "Append English \" (page/total)\" to HeaderEnglish when more than one page.");
		}
	}
	internal static class PluginInfo
	{
		internal const string PLUGIN_GUID = "GastrodonGroup.UpgradeListEnhance";

		internal const string PLUGIN_NAME = "Upgrade List Enhance";

		internal const string PLUGIN_VERSION = "0.1.0";
	}
	internal static class BuildInfo
	{
		internal const string Timestamp = "2026-08-09 17:26";
	}
}
namespace GastrodonGroup.UpgradeListEnhance.Patches
{
	internal static class StatsUIAlignPatch
	{
		private readonly struct Row
		{
			public readonly int Value;

			public readonly string Name;

			public Row(int value, string name)
			{
				Value = value;
				Name = name;
			}
		}

		private static readonly StringBuilder TextBuilder = new StringBuilder(256);

		private static readonly List<Row> Rows = new List<Row>(32);

		private static int _pageIndex;

		private static int _rowsHash;

		internal static int PageCount { get; private set; } = 1;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StatsUI), "Fetch")]
		[HarmonyAfter(new string[] { "DarkSpider90.TextUpgradesUIScale" })]
		private static void FetchPostfix(StatsUI __instance)
		{
			if (!UpgradeListEnhancePlugin.EnableAlign.Value)
			{
				return;
			}
			TextMeshProUGUI text = __instance.Text;
			TextMeshProUGUI textNumbers = __instance.textNumbers;
			if ((Object)(object)text == (Object)null || (Object)(object)textNumbers == (Object)null)
			{
				return;
			}
			Dictionary<string, int> playerUpgrades = __instance.playerUpgrades;
			if (playerUpgrades == null || playerUpgrades.Count == 0 || (string.IsNullOrEmpty(((TMP_Text)text).text) && string.IsNullOrEmpty(((TMP_Text)textNumbers).text)))
			{
				return;
			}
			int num = BuildRows(__instance, playerUpgrades);
			PageCount = ComputePageCount(Rows.Count);
			bool flag = num != _rowsHash;
			_rowsHash = num;
			if (flag)
			{
				_pageIndex = 0;
				UpgradeListPager.Ensure();
				UpgradeListPager.Instance?.ResetTimer();
			}
			else
			{
				UpgradeListPager.Ensure();
				if (_pageIndex >= PageCount)
				{
					_pageIndex = 0;
				}
			}
			ApplyPage(__instance);
			if (UpgradeListEnhancePlugin.LogOnFetch.Value)
			{
				UpgradeListEnhancePlugin.Logger.LogInfo((object)($"[Fetch] rows={Rows.Count}, page={_pageIndex + 1}/{PageCount}, changed={flag}, " + "header=" + UpgradeListEnhancePlugin.HeaderEnglish.Value + ", " + $"nameSize={((TMP_Text)text).fontSize:0.##}, nameLineSpacing={((TMP_Text)text).lineSpacing:0.##}"));
			}
		}

		internal static void AdvancePage(StatsUI ui)
		{
			if (PageCount > 1 && Rows.Count != 0)
			{
				_pageIndex = (_pageIndex + 1) % PageCount;
				ApplyPage(ui);
				if (UpgradeListEnhancePlugin.LogOnFetch.Value)
				{
					UpgradeListEnhancePlugin.Logger.LogInfo((object)$"[Page] {_pageIndex + 1}/{PageCount}");
				}
			}
		}

		private static void ApplyPage(StatsUI ui)
		{
			TextMeshProUGUI text = ui.Text;
			TextMeshProUGUI textNumbers = ui.textNumbers;
			if (!((Object)(object)text == (Object)null) && !((Object)(object)textNumbers == (Object)null))
			{
				int num = Mathf.Max(1, UpgradeListEnhancePlugin.PageSize.Value);
				bool flag = UpgradeListEnhancePlugin.EnablePaging.Value && Rows.Count > num;
				int num2 = (flag ? (_pageIndex * num) : 0);
				int count = (flag ? Mathf.Min(num, Rows.Count - num2) : Rows.Count);
				WriteColumns(text, textNumbers, num2, count);
				ApplyLayout(text, textNumbers, ui.upgradesHeader);
				UpdateHeader(ui.upgradesHeader);
			}
		}

		private static int BuildRows(StatsUI ui, Dictionary<string, int> upgrades)
		{
			Rows.Clear();
			int num = Rows.Count;
			foreach (KeyValuePair<string, int> upgrade in upgrades)
			{
				if (upgrade.Value > 0)
				{
					string text = StatsUI.GetUpgradeDisplayName(upgrade.Key);
					if (string.IsNullOrEmpty(text))
					{
						text = upgrade.Key.ToUpperInvariant();
					}
					Rows.Add(new Row(upgrade.Value, text));
					num = (num * 397) ^ upgrade.Key.GetHashCode();
					num = (num * 397) ^ upgrade.Value;
				}
			}
			return (num * 397) ^ Rows.Count;
		}

		private static void WriteColumns(TextMeshProUGUI names, TextMeshProUGUI numbers, int start, int count)
		{
			TextBuilder.Clear();
			for (int i = 0; i < count; i++)
			{
				TextBuilder.Append(Rows[start + i].Name).Append('\n');
			}
			((TMP_Text)names).text = TextBuilder.ToString();
			TextBuilder.Clear();
			bool flag = UpgradeListEnhancePlugin.AdjustNumbers.Value && UpgradeListEnhancePlugin.RewriteNumbersNoBold.Value;
			for (int j = 0; j < count; j++)
			{
				int value = Rows[start + j].Value;
				if (flag)
				{
					TextBuilder.Append(' ').Append(value).Append(" \n");
				}
				else
				{
					TextBuilder.Append("<b>").Append(value).Append("</b>\n");
				}
			}
			((TMP_Text)numbers).text = TextBuilder.ToString();
		}

		private static void ApplyLayout(TextMeshProUGUI names, TextMeshProUGUI numbers, TextMeshProUGUI? header)
		{
			if (UpgradeListEnhancePlugin.AdjustNames.Value)
			{
				float num = (((TMP_Text)names).fontSize = UpgradeListEnhancePlugin.NameFontSize.Value);
				((TMP_Text)names).lineSpacing = UpgradeListEnhancePlugin.NameLineSpacing.Value;
				if ((Object)(object)header != (Object)null)
				{
					((TMP_Text)header).fontSize = num + UpgradeListEnhancePlugin.HeaderOffset.Value;
				}
			}
			if (UpgradeListEnhancePlugin.AdjustNumbers.Value)
			{
				float num2 = (UpgradeListEnhancePlugin.AdjustNames.Value ? UpgradeListEnhancePlugin.NameFontSize.Value : ((TMP_Text)names).fontSize);
				((TMP_Text)numbers).fontSize = num2 + UpgradeListEnhancePlugin.NumberFontSizeOffset.Value;
				((TMP_Text)numbers).lineSpacing = UpgradeListEnhancePlugin.NumberLineSpacing.Value;
			}
		}

		private static void UpdateHeader(TextMeshProUGUI? header)
		{
			if (!((Object)(object)header == (Object)null))
			{
				string text = UpgradeListEnhancePlugin.HeaderEnglish.Value;
				if (string.IsNullOrEmpty(text))
				{
					text = "UPGRADES";
				}
				if (!UpgradeListEnhancePlugin.ShowPageInHeader.Value || PageCount <= 1)
				{
					((TMP_Text)header).text = text;
				}
				else
				{
					((TMP_Text)header).text = $"{text} ({_pageIndex + 1}/{PageCount})";
				}
			}
		}

		private static int ComputePageCount(int rowCount)
		{
			if (!UpgradeListEnhancePlugin.EnablePaging.Value || rowCount <= 0)
			{
				return 1;
			}
			int num = Mathf.Max(1, UpgradeListEnhancePlugin.PageSize.Value);
			if (rowCount <= num)
			{
				return 1;
			}
			return (rowCount + num - 1) / num;
		}
	}
}
namespace GastrodonGroup.UpgradeListEnhance.Behaviours
{
	internal sealed class UpgradeListPager : MonoBehaviour
	{
		private float _cycleTimer;

		internal static UpgradeListPager? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_cycleTimer = UpgradeListEnhancePlugin.PageCycleSeconds.Value;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			if (!UpgradeListEnhancePlugin.EnableAlign.Value || !UpgradeListEnhancePlugin.EnablePaging.Value || StatsUIAlignPatch.PageCount <= 1)
			{
				return;
			}
			StatsUI instance = StatsUI.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.upgradesHeader == (Object)null) && ((Behaviour)instance.upgradesHeader).enabled)
			{
				_cycleTimer -= Time.deltaTime;
				if (!(_cycleTimer > 0f))
				{
					_cycleTimer = UpgradeListEnhancePlugin.PageCycleSeconds.Value;
					StatsUIAlignPatch.AdvancePage(instance);
				}
			}
		}

		internal void ResetTimer()
		{
			_cycleTimer = UpgradeListEnhancePlugin.PageCycleSeconds.Value;
		}

		internal static void Ensure()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("UpgradeListEnhancePager");
				Object.DontDestroyOnLoad((Object)(object)val);
				((Object)val).hideFlags = (HideFlags)61;
				val.AddComponent<UpgradeListPager>();
			}
		}
	}
}