Decompiled source of ReadableNumbers v1.0.2

plugins/ReadableNumbers.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using HarmonyLib;
using Infoholic.MonoBehaviours;
using Microsoft.CodeAnalysis;
using ReadableNumbers.Patches.Compatibility;
using TabInfo.Utils;
using UnboundLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ReadableNumbers
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.aalund13.rounds.readable_numbers", "Readable Numbers", "1.0.2")]
	[BepInProcess("Rounds.exe")]
	public class ReadableNumbers : BaseUnityPlugin
	{
		internal const string modId = "com.aalund13.rounds.readable_numbers";

		internal const string ModName = "Readable Numbers";

		internal const string modInitials = "RN";

		internal static ReadableNumbers instance;

		internal static AssetBundle assets;

		internal static ManualLogSource ModLogger { get; private set; }

		internal static Harmony Harmony { get; private set; }

		private void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			instance = this;
			ModLogger = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("com.aalund13.rounds.readable_numbers");
			Harmony.PatchAll();
			((Component)this).gameObject.AddComponent<NumberDisplayController>();
			List<BaseUnityPlugin> obj = (List<BaseUnityPlugin>)typeof(Chainloader).GetField("_plugins", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
			if (obj.Exists((BaseUnityPlugin plugin) => plugin.Info.Metadata.GUID == "com.penial.rounds.Infoholic"))
			{
				InfoholicGameStatusUpdatePatch.Patch(Harmony);
			}
			if (obj.Exists((BaseUnityPlugin plugin) => plugin.Info.Metadata.GUID == "Systems.R00t.RSUI"))
			{
				RootStatUIStatDesplyerPatch.Patch(Harmony);
			}
			Unbound.RegisterClientSideMod("com.aalund13.rounds.readable_numbers");
			Debug.Log("Readable Numbers loaded!");
		}

		private void Start()
		{
			Debug.Log("Readable Numbers started!");
			if (((List<BaseUnityPlugin>)typeof(Chainloader).GetField("_plugins", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null)).Exists((BaseUnityPlugin plugin) => plugin.Info.Metadata.GUID == "com.willuwontu.rounds.tabinfo"))
			{
				ExtensionMethods.ExecuteAfterFrames((MonoBehaviour)(object)this, 5, (Action)delegate
				{
					TabInfoManagerPatch.PatchAllDisplayValue(Harmony);
				});
			}
		}
	}
	public class NumberDisplayController : MonoBehaviour
	{
		private static DisplayType currentDisplayType = DisplayType.Suffix;

		public static bool isDisable { get; private set; } = false;


		public static DisplayType CurrentDisplayType
		{
			get
			{
				if (isDisable)
				{
					return DisplayType.None;
				}
				return currentDisplayType;
			}
		}

		public void Update()
		{
			if (Input.GetKey((KeyCode)306) && Input.GetKeyDown((KeyCode)105))
			{
				CycleDisplayType();
			}
			if (Input.GetKeyDown((KeyCode)305))
			{
				isDisable = true;
			}
			else if (Input.GetKeyUp((KeyCode)305))
			{
				isDisable = false;
			}
		}

		private void CycleDisplayType()
		{
			switch (currentDisplayType)
			{
			case DisplayType.Suffix:
				currentDisplayType = DisplayType.Name;
				break;
			case DisplayType.Name:
				currentDisplayType = DisplayType.Suffix;
				break;
			default:
				currentDisplayType = DisplayType.Suffix;
				break;
			}
		}

		public static string DisplayNumber(float number, string format = null)
		{
			return NumberFormatter.DisplayNumber(number, CurrentDisplayType, format);
		}

		public static string DisplayNumber(int number, string format = null)
		{
			return NumberFormatter.DisplayNumber(number, CurrentDisplayType, format);
		}
	}
	public enum DisplayType
	{
		None,
		Name,
		Suffix
	}
	public static class NumberFormatter
	{
		public static List<NumberSuffix> suffixes = new List<NumberSuffix>
		{
			new NumberSuffix("K", "Thousand"),
			new NumberSuffix("M", "Million"),
			new NumberSuffix("B", "Billion"),
			new NumberSuffix("T", "Trillion"),
			new NumberSuffix("Qa", "Quadrillion"),
			new NumberSuffix("Qi", "Quintillion"),
			new NumberSuffix("Sx", "Sextillion"),
			new NumberSuffix("Sp", "Septillion"),
			new NumberSuffix("Oc", "Octillion"),
			new NumberSuffix("No", "Nonillion"),
			new NumberSuffix("Dc", "Decillion"),
			new NumberSuffix("Ud", "Undecillion")
		};

		public static string DisplayNumber(float number, DisplayType displayType, string format = null)
		{
			bool flag = number < 0f;
			float num = Mathf.Abs(number);
			if (num == 0f)
			{
				if (format == null)
				{
					return number.ToString();
				}
				return number.ToString(format);
			}
			int num2 = Mathf.FloorToInt(Mathf.Log10(num) / 3f);
			float num3 = num / Mathf.Pow(10f, (float)(num2 * 3));
			int num4 = 1 + Mathf.FloorToInt(Mathf.Log10(num3));
			int num5 = (int)Mathf.Pow(10f, (float)(4 - num4));
			num3 = Mathf.Floor(num3 * (float)num5) / (float)num5;
			string text = ((format != null) ? num3.ToString(format) : num3.ToString());
			string text2 = ((format != null) ? num.ToString(format) : num.ToString());
			if (flag)
			{
				text = "-" + text;
				text2 = "-" + text2;
			}
			if (num2 <= 0)
			{
				return number.ToString("0." + new string('#', Mathf.Max(0, 4 - num4)), CultureInfo.InvariantCulture);
			}
			return displayType switch
			{
				DisplayType.None => number.ToString("0.##", CultureInfo.InvariantCulture), 
				DisplayType.Name => text + " " + suffixes[num2 - 1].Name, 
				_ => text + suffixes[num2 - 1].Suffix, 
			};
		}

		public static string DisplayNumber(int number, DisplayType displayType, string format = null)
		{
			return DisplayNumber((float)number, displayType, (string)null);
		}
	}
	public struct NumberSuffix
	{
		public string Suffix { get; private set; }

		public string Name { get; private set; }

		public NumberSuffix(string suffix, string name)
		{
			Suffix = suffix;
			Name = name;
		}
	}
}
namespace ReadableNumbers.Patches.Compatibility
{
	internal class InfoholicGameStatusUpdatePatch
	{
		public static Regex Regex = new Regex("\\{\\d+:([^}]+)\\}");

		public static void Patch(Harmony harmony)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(GameStatusUpdate), "Update", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(InfoholicGameStatusUpdatePatch), "Transpiler", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Expected O, but got Unknown
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Expected O, but got Unknown
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Expected O, but got Unknown
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(string), "Format", new Type[2]
			{
				typeof(string),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(string), "Format", new Type[3]
			{
				typeof(string),
				typeof(object),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(string), "Format", new Type[4]
			{
				typeof(string),
				typeof(object),
				typeof(object),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(NumberDisplayController), "DisplayNumber", new Type[2]
			{
				typeof(float),
				typeof(string)
			}, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(typeof(NumberDisplayController), "DisplayNumber", new Type[2]
			{
				typeof(int),
				typeof(string)
			}, (Type[])null);
			List<int> list2 = new List<int>();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (CodeInstructionExtensions.Calls(list[num], methodInfo) || CodeInstructionExtensions.Calls(list[num], methodInfo2) || CodeInstructionExtensions.Calls(list[num], methodInfo3))
				{
					list2.Add(num);
				}
			}
			foreach (int item in list2)
			{
				int num2 = 0;
				CodeInstruction val = list[item];
				if (CodeInstructionExtensions.Calls(val, methodInfo))
				{
					num2 = 1;
				}
				else if (CodeInstructionExtensions.Calls(val, methodInfo2))
				{
					num2 = 2;
				}
				else if (CodeInstructionExtensions.Calls(val, methodInfo3))
				{
					num2 = 3;
				}
				ReadableNumbers.ModLogger.LogInfo((object)$"Found string.Format call at index {item} with {num2} argument(s)");
				string text = "";
				for (int num3 = item - 1; num3 >= 0; num3--)
				{
					if (list[num3].opcode == OpCodes.Ldstr)
					{
						text = list[num3].operand.ToString();
						ReadableNumbers.ModLogger.LogInfo((object)("Format: " + list[num3].operand.ToString()));
						break;
					}
				}
				bool flag = false;
				if (text.StartsWith("DMG: ") || text.StartsWith("HP: "))
				{
					flag = true;
				}
				string[] array = (from Match m in Regex.Matches(text)
					select m.Groups[1].Value).ToArray();
				int num4 = 0;
				int num5 = item - 1;
				while (num5 >= item - num2 * 5 && num5 >= 0)
				{
					if (list[num5].opcode == OpCodes.Box)
					{
						Type type = list[num5].operand as Type;
						string text2 = ((array.Length > num4 && !flag) ? array[num4] : "");
						if (type == typeof(float))
						{
							list[num5] = new CodeInstruction(OpCodes.Ldstr, (object)text2);
							list.Insert(num5 + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo4));
						}
						else if (type == typeof(int))
						{
							list[num5] = new CodeInstruction(OpCodes.Ldstr, (object)text2);
							list.Insert(num5 + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo5));
						}
						num4++;
					}
					num5--;
				}
			}
			return list.AsEnumerable();
		}
	}
	public class RootStatUIStatDesplyerPatch
	{
		public static void Patch(Harmony harmony)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(StatDesplyer), "Format", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(RootStatUIStatDesplyerPatch), "Prefix", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public static bool Prefix(ref string __result, float value)
		{
			if (!NumberDisplayController.isDisable)
			{
				__result = NumberFormatter.DisplayNumber(value, DisplayType.Suffix);
			}
			return NumberDisplayController.isDisable;
		}
	}
	public class TabInfoManagerPatch
	{
		public static Regex Regex = new Regex("\\{\\d+:([^}]+)\\}");

		public static void PatchAllDisplayValue(Harmony harmony)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			foreach (StatCategory value in TabInfoManager.Categories.Values)
			{
				foreach (Stat value2 in value.Stats.Values)
				{
					Func<Player, string> displayValue = value2.displayValue;
					MethodInfo method = displayValue.Method;
					if (value2.name == "Damage")
					{
						value2.displayValue = (Player player) => NumberDisplayController.DisplayNumber(float.Parse(displayValue(player)));
						continue;
					}
					if (value2.name == "HP")
					{
						value2.displayValue = (Player player) => NumberDisplayController.DisplayNumber(player.data.health) + "/" + NumberDisplayController.DisplayNumber(player.data.maxHealth);
						continue;
					}
					MethodInfo methodInfo = AccessTools.Method(typeof(TabInfoManagerPatch), "PatchTranspiler", (Type[])null, (Type[])null);
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null);
					ReadableNumbers.ModLogger.LogInfo((object)("Patched the \"" + value2.name + "\" display value method from the \"" + value.name + "\" category"));
				}
			}
		}

		public static IEnumerable<CodeInstruction> PatchTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Expected O, but got Unknown
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Expected O, but got Unknown
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(string), "Format", new Type[2]
			{
				typeof(string),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(string), "Format", new Type[3]
			{
				typeof(string),
				typeof(object),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(string), "Format", new Type[4]
			{
				typeof(string),
				typeof(object),
				typeof(object),
				typeof(object)
			}, (Type[])null);
			MethodInfo methodInfo4 = AccessTools.Method(typeof(NumberDisplayController), "DisplayNumber", new Type[2]
			{
				typeof(float),
				typeof(string)
			}, (Type[])null);
			MethodInfo methodInfo5 = AccessTools.Method(typeof(NumberDisplayController), "DisplayNumber", new Type[2]
			{
				typeof(int),
				typeof(string)
			}, (Type[])null);
			List<int> list2 = new List<int>();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (CodeInstructionExtensions.Calls(list[num], methodInfo) || CodeInstructionExtensions.Calls(list[num], methodInfo2) || CodeInstructionExtensions.Calls(list[num], methodInfo3))
				{
					list2.Add(num);
				}
			}
			foreach (int item in list2)
			{
				int num2 = 0;
				CodeInstruction val = list[item];
				if (CodeInstructionExtensions.Calls(val, methodInfo))
				{
					num2 = 1;
				}
				else if (CodeInstructionExtensions.Calls(val, methodInfo2))
				{
					num2 = 2;
				}
				else if (CodeInstructionExtensions.Calls(val, methodInfo3))
				{
					num2 = 3;
				}
				ReadableNumbers.ModLogger.LogInfo((object)$"Found string.Format call at index {item} with {num2} argument(s)");
				string input = "";
				for (int num3 = item - 1; num3 >= 0; num3--)
				{
					if (list[num3].opcode == OpCodes.Ldstr)
					{
						input = list[num3].operand.ToString();
						ReadableNumbers.ModLogger.LogInfo((object)("Format: " + list[num3].operand.ToString()));
						break;
					}
				}
				string[] array = (from Match m in Regex.Matches(input)
					select m.Groups[1].Value).ToArray();
				int num4 = 0;
				int num5 = item - 1;
				while (num5 >= item - num2 * 5 && num5 >= 0)
				{
					if (list[num5].opcode == OpCodes.Box)
					{
						Type type = list[num5].operand as Type;
						string text = ((array.Length > num4) ? array[num4] : "");
						if (type == typeof(float))
						{
							list[num5] = new CodeInstruction(OpCodes.Ldstr, (object)text);
							list.Insert(num5 + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo4));
						}
						else if (type == typeof(int))
						{
							list[num5] = new CodeInstruction(OpCodes.Ldstr, (object)text);
							list.Insert(num5 + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo5));
						}
						num4++;
					}
					num5--;
				}
			}
			return list.AsEnumerable();
		}
	}
}