Decompiled source of ReefPacksAzuUIFix v1.0.2

BepInEx/plugins/ReefPacksAzuUIFix/ReefPacksAzuUIFix.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ReefPacksAzuUIFix")]
[assembly: AssemblyDescription("UI-only worn ReefPack counts for AzuCraftyBoxes")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyVersion("1.0.2.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 ReefPacksAzuUIFix
{
	internal static class DisplayCount
	{
		private static readonly Regex Pattern = new Regex("^(?<before>(?:\\s|<[^>]+>)*)(?<available>[0-9][0-9.,\\s]*[KMkm]?)(?<separator>(?:\\s|<[^>]+>)*/(?:\\s|<[^>]+>)*)(?<required>[0-9][0-9.,\\s]*)(?<after>(?:\\s|<[^>]+>)*)$");

		internal static bool TryAdd(string original, int pack, out string corrected, out bool enough)
		{
			corrected = original;
			enough = false;
			if (pack < 0 || string.IsNullOrEmpty(original))
			{
				return false;
			}
			Match match = Pattern.Match(original);
			if (!match.Success || !TryNumber(match.Groups["available"].Value, out var value) || !TryNumber(match.Groups["required"].Value, out var value2) || value2 <= 0)
			{
				return false;
			}
			long num = Math.Min(2147483647L, value + pack);
			enough = num >= value2;
			if (pack == 0)
			{
				return true;
			}
			corrected = match.Groups["before"].Value + num.ToString(CultureInfo.InvariantCulture) + match.Groups["separator"].Value + match.Groups["required"].Value + match.Groups["after"].Value;
			return true;
		}

		private static bool TryNumber(string token, out long value)
		{
			value = 0L;
			token = token.Trim();
			decimal num = 1m;
			if (token.EndsWith("K", StringComparison.OrdinalIgnoreCase))
			{
				num = 1000m;
			}
			else if (token.EndsWith("M", StringComparison.OrdinalIgnoreCase))
			{
				num = 1000000m;
			}
			if (num != 1m)
			{
				token = token.Substring(0, token.Length - 1);
			}
			NumberStyles style = ((num == 1m) ? (NumberStyles.Integer | NumberStyles.AllowThousands) : NumberStyles.Number);
			if (!decimal.TryParse(token, style, CultureInfo.CurrentCulture, out var result) || result < 0m || result * num > 2147483647m)
			{
				return false;
			}
			value = (long)decimal.Round(result * num, 0, MidpointRounding.AwayFromZero);
			return true;
		}
	}
	[BepInPlugin("local.ReefPacksAzuUIFix", "ReefPacksAzuUIFix", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "local.ReefPacksAzuUIFix";

		private static Plugin instance;

		private ConfigEntry<bool> enabledSetting;

		private ConfigEntry<bool> diagnostics;

		private Harmony harmony;

		private WornPackReader reader;

		private readonly Dictionary<string, string> lastMessages = new Dictionary<string, string>();

		private int messageCount;

		private void Awake()
		{
			instance = this;
			enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Correct only final crafting requirement text and color.");
			diagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DiagnosticLogging", true, "Log changed requirement results for this session (maximum 200 messages). Disable after testing.");
		}

		private void Start()
		{
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			PluginInfo value;
			bool flag = Chainloader.PluginInfos.TryGetValue("Azumatt.AzuCraftyBoxes", out value);
			PluginInfo value2;
			bool flag2 = Chainloader.PluginInfos.TryGetValue("reef.packs", out value2);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("AzuCraftyBoxes found: " + flag + (flag ? (" (" + value.Metadata.Version?.ToString() + ")") : "")));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ReefPacks found: " + flag2 + (flag2 ? (" (" + value2.Metadata.Version?.ToString() + ")") : "")));
			if (!flag || !flag2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"UI compatibility patch not applied: required mod absent.");
				return;
			}
			try
			{
				reader = new WornPackReader(((object)value2.Instance).GetType().Assembly);
				MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "SetupRequirement", new Type[6]
				{
					typeof(Transform),
					typeof(Requirement),
					typeof(Player),
					typeof(bool),
					typeof(int),
					typeof(int)
				}, (Type[])null);
				if (methodInfo == null || methodInfo.ReturnType != typeof(bool))
				{
					throw new MissingMethodException("InventoryGui.SetupRequirement signature changed");
				}
				harmony = new Harmony("local.ReefPacksAzuUIFix");
				List<string> list = new List<string> { "Azumatt.AzuCraftyBoxes" };
				Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
				if (patchInfo != null)
				{
					foreach (string owner in patchInfo.Owners)
					{
						if (owner != "local.ReefPacksAzuUIFix" && !list.Contains(owner))
						{
							list.Add(owner);
						}
					}
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterRequirement", (Type[])null)
				{
					priority = 0,
					after = list.ToArray()
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("UI compatibility patch successfully applied: InventoryGui.SetupRequirement POSTFIX, Priority.Last, after=" + string.Join(",", list) + "; Enabled=" + enabledSetting.Value));
			}
			catch (Exception ex)
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogWarning((object)("UI compatibility patch not applied: " + ex.GetBaseException().Message));
			}
		}

		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "Azumatt.AzuCraftyBoxes" })]
		private static void AfterRequirement(bool __result, Transform elementRoot, Requirement req, Player player)
		{
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			Plugin plugin = instance;
			if ((Object)(object)plugin == (Object)null || !plugin.enabledSetting.Value || plugin.reader == null)
			{
				return;
			}
			string text = "<unknown>";
			try
			{
				plugin.Trace("entered", "SetupRequirement postfix executed");
				if (!__result || !Object.op_Implicit((Object)(object)elementRoot) || !Object.op_Implicit((Object)(object)player) || (Object)(object)player != (Object)(object)Player.m_localPlayer || req?.m_resItem?.m_itemData?.m_shared == null)
				{
					return;
				}
				text = req.m_resItem.m_itemData.m_shared.m_name;
				Transform obj = ((Component)elementRoot).transform.Find("res_amount");
				TextMeshProUGUI val = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
				if (!Object.op_Implicit((Object)(object)val) || string.IsNullOrEmpty(text))
				{
					return;
				}
				string text2 = ((TMP_Text)val).text;
				string status;
				int num = plugin.reader.Count(player, text, out status);
				if (!DisplayCount.TryAdd(text2, num, out var corrected, out var enough))
				{
					plugin.Trace(text, "SetupRequirement " + text + " original=" + text2 + " pack=" + num + " corrected=<unchanged: unsupported format>; " + status);
					return;
				}
				if (num > 0)
				{
					((TMP_Text)val).text = corrected;
					if (enough)
					{
						((Graphic)val).color = Color.white;
					}
				}
				plugin.Trace(text, "SetupRequirement " + text + " original=" + text2 + " pack=" + num + " corrected=" + corrected + "; " + status);
			}
			catch (Exception ex)
			{
				plugin.Trace("error:" + text, "SetupRequirement " + text + " skipped: " + ex.GetBaseException().Message);
			}
		}

		private void Trace(string key, string message)
		{
			if (diagnostics.Value && messageCount < 200 && (!lastMessages.TryGetValue(key, out var value) || !(value == message)))
			{
				lastMessages[key] = message;
				messageCount++;
				((BaseUnityPlugin)this).Logger.LogInfo((object)message);
				if (messageCount == 200)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"UI diagnostic session limit reached; further UI logs suppressed until restart.");
				}
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (instance == this)
			{
				instance = null;
			}
		}
	}
	internal sealed class WornPackReader
	{
		private const BindingFlags Static = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private const BindingFlags Instance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private readonly MethodInfo wornPack;

		private readonly MethodInfo tryGet;

		private readonly FieldInfo cache;

		private readonly FieldInfo packInventory;

		private readonly FieldInfo packItem;

		private readonly FieldInfo inventoryItems;

		internal WornPackReader(Assembly reef)
		{
			Type type = reef.GetType("ReefPacks.PackUi", throwOnError: true);
			Type type2 = reef.GetType("ReefPacks.PackData", throwOnError: true);
			wornPack = type.GetMethod("WornPack", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Player) }, null);
			if (wornPack == null || wornPack.ReturnType != typeof(ItemData))
			{
				throw new MissingMethodException("PackUi.WornPack");
			}
			cache = Field(type2, "cache", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, typeof(ConditionalWeakTable<, >).MakeGenericType(typeof(ItemData), type2));
			tryGet = cache.FieldType.GetMethod("TryGetValue", new Type[2]
			{
				typeof(ItemData),
				type2.MakeByRefType()
			});
			if (tryGet == null)
			{
				throw new MissingMethodException("PackData.cache.TryGetValue");
			}
			packInventory = Field(type2, "Inv", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, typeof(Inventory));
			packItem = Field(type2, "Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, typeof(ItemData));
			inventoryItems = Field(typeof(Inventory), "m_inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, typeof(List<ItemData>));
		}

		private static FieldInfo Field(Type type, string name, BindingFlags flags, Type expected)
		{
			FieldInfo field = type.GetField(name, flags);
			if (field == null || field.FieldType != expected)
			{
				throw new MissingFieldException(type.FullName, name);
			}
			return field;
		}

		internal int Count(Player player, string name, out string status)
		{
			status = "no worn pack";
			object? obj = wornPack.Invoke(null, new object[1] { player });
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			if (val == null)
			{
				return 0;
			}
			object[] array = new object[2] { val, null };
			status = "worn pack cache unavailable";
			object value = cache.GetValue(null);
			if (value == null || !(bool)tryGet.Invoke(value, array) || array[1] == null)
			{
				return 0;
			}
			object obj2 = array[1];
			status = "pack owner mismatch";
			if (packItem.GetValue(obj2) != val)
			{
				return 0;
			}
			status = "pack inventory unavailable";
			object? value2 = packInventory.GetValue(obj2);
			Inventory val2 = (Inventory)((value2 is Inventory) ? value2 : null);
			if (val2 == null)
			{
				return 0;
			}
			if (!(inventoryItems.GetValue(val2) is List<ItemData> list))
			{
				return 0;
			}
			long num = 0L;
			foreach (ItemData item in list)
			{
				if (item?.m_shared?.m_name == name && item.m_worldLevel >= Game.m_worldLevel && item.m_stack > 0)
				{
					num += item.m_stack;
				}
			}
			status = "read worn pack";
			return (int)Math.Min(2147483647L, num);
		}
	}
}