Decompiled source of XPNumbers v0.2.2

plugins/MycopunkXpNumbers/MycopunkXpNumbers.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MycopunkShared;
using Pigeon.Movement;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MycopunkXpNumbers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+fe8cef1291afd0a7f7ea8a9ddfd28d3607c4cdd5")]
[assembly: AssemblyProduct("MycopunkXpNumbers")]
[assembly: AssemblyTitle("MycopunkXpNumbers")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[module: UnverifiableCode]
[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 MycopunkXpNumbers
{
	internal static class MenuText
	{
		private static readonly Dictionary<string, Dictionary<string, string>> Names = new Dictionary<string, Dictionary<string, string>>
		{
			["en"] = new Dictionary<string, string> { ["xp.level"] = "XP numbers on level bars" },
			["ja"] = new Dictionary<string, string> { ["xp.level"] = "レベルバーにXPを表示" }
		};

		private static readonly Dictionary<string, Dictionary<string, string>> Descriptions = new Dictionary<string, Dictionary<string, string>> { ["ja"] = new Dictionary<string, string> { ["xp.level"] = "レベルバーの横に、現在のレベルで得たXPと、次のレベルまでに必要なXPを表示します。TAB の画面、ビルド画面、ミッションのリザルト画面に表示されます。次にバーが更新されたときから反映されます。" } };

		public static object[] Label(string key)
		{
			return ModsMenuTag.Label(key, (IDictionary<string, Dictionary<string, string>>)Names, (IDictionary<string, Dictionary<string, string>>)Descriptions);
		}
	}
	[BepInPlugin("t4t5u0.mycopunk.xpnumbers", "Mycopunk XP Numbers", "0.2.2")]
	[BepInDependency("doku_macaron.mycopunk.macaroncore", "1.1.0")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "t4t5u0.mycopunk.xpnumbers";

		public const string Name = "Mycopunk XP Numbers";

		public const string Version = "0.2.2";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> ResultsFontScale;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, new ConfigDescription("Show the XP into the current level and the XP the next level costs next to the level bars (the class screen after TAB, the build screen of weapons, gear and classes, and the mission results). Shown from the next time a bar is filled.", (AcceptableValueBase)null, MenuText.Label("xp.level")));
			ResultsFontScale = ((BaseUnityPlugin)this).Config.Bind<float>("Results", "FontScale", 0.7f, new ConfigDescription("Size of the numbers under the bars of the mission results, relative to the level text.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 2f), Array.Empty<object>()));
			_harmony = new Harmony("t4t5u0.mycopunk.xpnumbers");
			ModSetup.Try(Log, "XP numbers", (Action)delegate
			{
				_harmony.CreateClassProcessor(typeof(XpBars.DetailsPatch)).Patch();
			});
			ModSetup.Try(Log, "XP numbers", (Action)delegate
			{
				_harmony.CreateClassProcessor(typeof(XpBars.SelectionPatch)).Patch();
			});
			ModSetup.Try(Log, "XP numbers on the mission results", (Action)delegate
			{
				_harmony.CreateClassProcessor(typeof(XpResults.ShowXPPatch)).Patch();
			});
			ModSetup.Try(Log, "MODS tab", (Action)delegate
			{
				ModsMenu.Install(_harmony, (BaseUnityPlugin)(object)this);
			});
			ModSetup.Try(Log, "hotkey report", (Action)delegate
			{
				Hotkeys.ReportConflicts((BaseUnityPlugin)(object)this);
			});
			Log.LogInfo((object)("Mycopunk XP Numbers 0.2.2 loaded (enabled=" + Enabled.Value + ")."));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			XpResults.Cleanup();
		}
	}
	internal static class XpBars
	{
		[HarmonyPatch(typeof(GearDetailsWindow), "UpdateXPBar")]
		internal static class DetailsPatch
		{
			[HarmonyPostfix]
			private static void Postfix(GearDetailsWindow __instance)
			{
				try
				{
					if (Plugin.Enabled.Value)
					{
						IUpgradable upgradablePrefab = __instance.UpgradablePrefab;
						TextMeshProUGUI levelText = __instance.levelText;
						string text = ((upgradablePrefab != null) ? Progress(PlayerData.GetGearData(upgradablePrefab)) : "");
						if ((Object)(object)levelText != (Object)null && text.Length > 0)
						{
							((TMP_Text)levelText).text = ((TMP_Text)levelText).text + "  <size=80%>" + text + "</size>";
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("XP numbers on the build screen failed: " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(GearSelectionWindow), "UpdateXPBar")]
		internal static class SelectionPatch
		{
			[HarmonyPostfix]
			private static void Postfix(GearSelectionWindow __instance)
			{
				try
				{
					if (Plugin.Enabled.Value)
					{
						Player localPlayer = Player.LocalPlayer;
						Character val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.Character : null);
						TextMeshProUGUI levelText = __instance.levelText;
						string text = (((Object)(object)val != (Object)null) ? Progress(PlayerData.GetGearData((IUpgradable)(object)val)) : "");
						if ((Object)(object)levelText != (Object)null && text.Length > 0)
						{
							((TMP_Text)levelText).text = "<size=70%>" + text + "</size>  " + ((TMP_Text)levelText).text;
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("XP numbers on the class screen failed: " + ex));
				}
			}
		}

		private static string Progress(GearData data)
		{
			if (data != null)
			{
				return XpText.Progress(data.LevelXP, data.NextLevelXPCost, data.Level, data.MaxLevel);
			}
			return "";
		}
	}
	internal static class XpResults
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		internal static class ShowXPPatch
		{
			[HarmonyPostfix]
			private static void Postfix(object __instance)
			{
				if (_fields == 0)
				{
					_fields = (FindFields(__instance.GetType()) ? 1 : (-1));
				}
				if (_fields < 0)
				{
					return;
				}
				try
				{
					object? value = _ui.GetValue(__instance);
					ResourceUI val = (ResourceUI)((value is ResourceUI) ? value : null);
					if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy || ((Component)val).transform.childCount < 5)
					{
						return;
					}
					TextMeshProUGUI val2 = Label(((Component)val).transform);
					if ((Object)(object)val2 == (Object)null)
					{
						return;
					}
					if (!Plugin.Enabled.Value)
					{
						((TMP_Text)val2).text = "";
						return;
					}
					GearInfo gearInfo = val.GearInfo;
					GearData data = (((Object)(object)gearInfo != (Object)null) ? PlayerData.GetGearData(gearInfo) : null);
					if (data == null)
					{
						((TMP_Text)val2).text = "";
						return;
					}
					int num = Convert.ToInt32(_prevLevel.GetValue(__instance));
					int num2 = Convert.ToInt32(_level.GetValue(__instance));
					float num3 = Convert.ToSingle(_prevXP.GetValue(__instance));
					float num4 = Convert.ToSingle(_xp.GetValue(__instance));
					float t = Mathf.Clamp01(Convert.ToSingle(_time.GetValue(__instance)));
					Func<int, int> func = (int n) => data.GetLevelXPCost(n, false);
					float num5 = (float)num + num3 / (float)func(num + 1);
					float num6 = (float)num2 + num4 / (float)func(num2 + 1);
					XpText.AtFractionalLevel(Mathf.LerpUnclamped(num5, num6, XpText.EaseOutQuartic(t)), func, out var level, out var xp, out var cost);
					((TMP_Text)val2).text = XpText.Progress(xp, cost, level, data.MaxLevel);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("XP numbers on the mission results failed: " + ex));
				}
			}
		}

		private static FieldInfo _ui;

		private static FieldInfo _xp;

		private static FieldInfo _level;

		private static FieldInfo _prevXP;

		private static FieldInfo _prevLevel;

		private static FieldInfo _time;

		private static int _fields;

		private const string LabelName = "XP numbers";

		private static bool _loggedLayout;

		private static readonly List<GameObject> Labels = new List<GameObject>();

		public static void Cleanup()
		{
			foreach (GameObject label in Labels)
			{
				if ((Object)(object)label != (Object)null)
				{
					Object.Destroy((Object)(object)label);
				}
			}
			Labels.Clear();
		}

		private static bool FindFields(Type t)
		{
			_ui = AccessTools.Field(t, "ui");
			_xp = AccessTools.Field(t, "xp");
			_level = AccessTools.Field(t, "level");
			_prevXP = AccessTools.Field(t, "prevXP");
			_prevLevel = AccessTools.Field(t, "prevLevel");
			_time = AccessTools.Field(t, "<time>5__2");
			if (_ui == null || _xp == null || _level == null || _prevXP == null || _prevLevel == null || _time == null)
			{
				Plugin.Log.LogWarning((object)"ShowXPCoroutine is not as expected; no XP numbers on the mission results.");
				return false;
			}
			return true;
		}

		private unsafe static TextMeshProUGUI Label(Transform row)
		{
			//IL_0095: 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_009e: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			Transform child = row.GetChild(3);
			RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = ((Transform)val).Find("XP numbers");
			if ((Object)(object)val2 != (Object)null)
			{
				return ((Component)val2).GetComponent<TextMeshProUGUI>();
			}
			TextMeshProUGUI component = ((Component)row.GetChild(4)).GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			Vector2 size = default(Vector2);
			if (!_loggedLayout)
			{
				_loggedLayout = true;
				ManualLogSource log = Plugin.Log;
				string[] obj = new string[12]
				{
					"results row ",
					((Object)row).name,
					": bar ",
					((Object)val).name,
					" ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Rect rect = val.rect;
				size = ((Rect)(ref rect)).size;
				obj[5] = ((object)(*(Vector2*)(&size))/*cast due to .constrained prefix*/).ToString();
				obj[6] = ", level text ";
				obj[7] = ((Object)component).name;
				obj[8] = " size ";
				obj[9] = ((TMP_Text)component).fontSize.ToString();
				obj[10] = ", align ";
				obj[11] = ((object)((TMP_Text)component).alignment/*cast due to .constrained prefix*/).ToString();
				log.LogInfo((object)string.Concat(obj));
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)component).gameObject, (Transform)(object)val, false);
			Labels.Add(val3);
			((Object)val3).name = "XP numbers";
			for (int num = val3.transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)val3.transform.GetChild(num)).gameObject);
			}
			TextMeshProUGUI component2 = val3.GetComponent<TextMeshProUGUI>();
			((Graphic)component2).raycastTarget = false;
			((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component2).alignment = (TextAlignmentOptions)260;
			((TMP_Text)component2).fontSize = ((TMP_Text)component).fontSize * Plugin.ResultsFontScale.Value;
			((TMP_Text)component2).text = "";
			RectTransform val4 = (RectTransform)val3.transform;
			((Vector2)(ref size))..ctor(1f, 0f);
			val4.anchorMax = size;
			val4.anchorMin = size;
			val4.pivot = new Vector2(1f, 1f);
			((Transform)val4).localScale = Vector3.one;
			((Transform)val4).localRotation = Quaternion.identity;
			val4.sizeDelta = new Vector2(400f, ((TMP_Text)component2).fontSize * 1.4f);
			val4.anchoredPosition = new Vector2(0f, -4f);
			return component2;
		}
	}
	internal static class XpText
	{
		public static string Progress(int levelXP, int nextLevelCost, int level, int maxLevel)
		{
			if (level >= maxLevel || nextLevelCost <= 0)
			{
				return "";
			}
			return levelXP.ToString("N0", CultureInfo.InvariantCulture) + " / " + nextLevelCost.ToString("N0", CultureInfo.InvariantCulture) + " XP";
		}

		public static float EaseOutQuartic(float t)
		{
			float num = 1f - t;
			return 1f - num * num * num * num;
		}

		public static void AtFractionalLevel(float v, Func<int, int> costOf, out int level, out int xp, out int cost)
		{
			level = (int)Math.Floor(v);
			cost = costOf(level + 1);
			xp = (int)Math.Round((v - (float)level) * (float)cost);
			if (xp >= cost && cost > 0)
			{
				xp = cost - 1;
			}
			if (xp < 0)
			{
				xp = 0;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}