Decompiled source of FoodStats v1.0.0

plugins/FoodStats.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[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("FoodStats")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FoodStats")]
[assembly: AssemblyTitle("FoodStats")]
[assembly: AssemblyVersion("1.0.0.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 FoodStats
{
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? HideDefaultButton;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	public enum FoodSort
	{
		Default,
		Health,
		Stamina,
		Eitr,
		Total
	}
	internal static class FoodInfo
	{
		private const string HealthColor = "#ff8080";

		private const string StaminaColor = "#ffff80";

		private const string EitrColor = "#9090ff";

		public static SharedData Displayed(SharedData shared)
		{
			ItemDrop val = shared?.m_appendToolTip;
			if (!((Object)(object)val != (Object)null) || !IsFood(val.m_itemData.m_shared))
			{
				return shared;
			}
			return val.m_itemData.m_shared;
		}

		public static bool IsFood(SharedData shared)
		{
			if (shared != null)
			{
				if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f))
				{
					return shared.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		public static string StatsText(SharedData shared)
		{
			List<string> list = new List<string>();
			if (shared.m_food > 0f)
			{
				list.Add(Colored(shared.m_food, "#ff8080"));
			}
			if (shared.m_foodStamina > 0f)
			{
				list.Add(Colored(shared.m_foodStamina, "#ffff80"));
			}
			if (shared.m_foodEitr > 0f)
			{
				list.Add(Colored(shared.m_foodEitr, "#9090ff"));
			}
			return string.Join("  ", list);
		}

		public static float SortKey(SharedData shared, FoodSort mode)
		{
			if (!IsFood(shared))
			{
				return 0f;
			}
			return mode switch
			{
				FoodSort.Health => shared.m_food, 
				FoodSort.Stamina => shared.m_foodStamina, 
				FoodSort.Eitr => shared.m_foodEitr, 
				FoodSort.Total => shared.m_food + shared.m_foodStamina + shared.m_foodEitr, 
				_ => 0f, 
			};
		}

		private static string Colored(float value, string color)
		{
			return $"<color={color}>{Mathf.RoundToInt(value)}</color>";
		}
	}
	[BepInPlugin("batera.FoodStats", "FoodStats", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "batera.FoodStats";

		public const string PluginName = "FoodStats";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<FoodSort> SortMode;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			_harmony = new Harmony("batera.FoodStats");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"FoodStats 1.0.0 loaded");
		}

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

		private void BindConfig()
		{
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, Desc("Show food stats in the crafting list and the sort button.", 2));
			SortMode = ((BaseUnityPlugin)this).Config.Bind<FoodSort>("1 - General", "SortMode", FoodSort.Default, Desc("How food recipes are sorted. The sort button next to the crafting tabs changes this too.", 1));
		}

		private static ConfigDescription Desc(string text, int order)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new ConfigDescription(text, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = order
				}
			});
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
	internal static class RecipeListPatch
	{
		private const string StatsObjectName = "foodstats";

		private static readonly FieldInfo AvailableRecipesField = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes");

		private static readonly Type PairType = AccessTools.Inner(typeof(InventoryGui), "RecipeDataPair");

		private static readonly PropertyInfo PairRecipe = AccessTools.Property(PairType, "Recipe");

		private static readonly PropertyInfo PairElement = AccessTools.Property(PairType, "InterfaceElement");

		private static void Postfix(InventoryGui __instance)
		{
			if (!(AvailableRecipesField.GetValue(__instance) is IList list))
			{
				return;
			}
			bool flag = false;
			if (Plugin.Enabled.Value)
			{
				foreach (object item in list)
				{
					SharedData shared = Shared(item);
					if (FoodInfo.IsFood(shared))
					{
						flag = true;
						AddStats(Element(item), shared);
					}
				}
			}
			bool flag2 = flag && __instance.InCraftTab();
			SortButton.Refresh(__instance, flag2);
			if (flag2 && Plugin.SortMode.Value != FoodSort.Default)
			{
				Sort(__instance, list, Plugin.SortMode.Value);
			}
		}

		private static void AddStats(GameObject element, SharedData shared)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (!((Object)(object)element != (Object)null))
			{
				obj = null;
			}
			else
			{
				Transform obj2 = element.transform.Find("name");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
			}
			TMP_Text val = (TMP_Text)obj;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)element.transform.Find("foodstats") != (Object)null))
			{
				float num = (val.enableAutoSizing ? val.fontSizeMax : val.fontSize);
				GameObject obj3 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.transform.parent);
				((Object)obj3).name = "foodstats";
				TMP_Text component = obj3.GetComponent<TMP_Text>();
				component.text = FoodInfo.StatsText(shared);
				((Graphic)component).color = Color.white;
				component.enableAutoSizing = false;
				component.fontSize = num * 0.72f;
				component.alignment = (TextAlignmentOptions)4100;
				component.textWrappingMode = (TextWrappingModes)0;
				component.overflowMode = (TextOverflowModes)0;
				((Graphic)component).raycastTarget = false;
				float x = component.GetPreferredValues(component.text).x;
				val.enableAutoSizing = false;
				val.fontSize = num * 0.8f;
				val.textWrappingMode = (TextWrappingModes)0;
				val.overflowMode = (TextOverflowModes)1;
				RectTransform rectTransform = val.rectTransform;
				rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x - x - 8f, rectTransform.offsetMax.y);
			}
		}

		private static void Sort(InventoryGui gui, IList rows, FoodSort mode)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			List<object> list = (from object row in rows
				orderby FoodInfo.SortKey(Shared(row), mode) descending
				select row).ToList();
			rows.Clear();
			foreach (object item in list)
			{
				rows.Add(item);
			}
			for (int num = 0; num < list.Count; num++)
			{
				GameObject obj = Element(list[num]);
				Transform obj2 = ((obj != null) ? obj.transform : null);
				RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
				if (val != null)
				{
					val.anchoredPosition = new Vector2(0f, (float)num * (0f - gui.m_recipeListSpace));
				}
			}
		}

		private static SharedData Shared(object row)
		{
			object? value = PairRecipe.GetValue(row);
			Recipe val = (Recipe)((value is Recipe) ? value : null);
			if (!((Object)(object)val != (Object)null) || !((Object)(object)val.m_item != (Object)null))
			{
				return null;
			}
			return FoodInfo.Displayed(val.m_item.m_itemData.m_shared);
		}

		private static GameObject Element(object row)
		{
			object? value = PairElement.GetValue(row);
			return (GameObject)((value is GameObject) ? value : null);
		}
	}
	internal static class SortButton
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnClick;
		}

		private static readonly MethodInfo UpdateCraftingPanel = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null);

		private static Button s_button;

		private static TMP_Text s_label;

		public static void Refresh(InventoryGui gui, bool visible)
		{
			if ((Object)(object)s_button == (Object)null)
			{
				Create(gui);
			}
			if (!((Object)(object)s_button == (Object)null))
			{
				((Component)s_button).gameObject.SetActive(visible);
				if (visible && (Object)(object)s_label != (Object)null)
				{
					s_label.text = Texts.SortLabel(Plugin.SortMode.Value);
				}
			}
		}

		private static void Create(InventoryGui gui)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00eb: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			Button tabUpgrade = gui.m_tabUpgrade;
			if ((Object)(object)tabUpgrade == (Object)null)
			{
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)tabUpgrade).gameObject, ((Component)tabUpgrade).transform.parent);
			((Object)val).name = "FoodStats_SortButton";
			Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
			foreach (Component val2 in componentsInChildren)
			{
				string name = ((object)val2).GetType().Name;
				if (name == "Localize" || name == "UIGamePad")
				{
					Object.Destroy((Object)(object)val2);
				}
			}
			s_button = val.GetComponent<Button>();
			s_button.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = s_button.onClick;
			object obj = <>O.<0>__OnClick;
			if (obj == null)
			{
				UnityAction val3 = OnClick;
				<>O.<0>__OnClick = val3;
				obj = (object)val3;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			((Selectable)s_button).interactable = true;
			RectTransform val4 = (RectTransform)val.transform;
			RectTransform val5 = (RectTransform)((Component)tabUpgrade).transform;
			Vector2 anchoredPosition = val5.anchoredPosition;
			Rect rect = val5.rect;
			val4.anchoredPosition = anchoredPosition + new Vector2(((Rect)(ref rect)).width + 10f, 0f);
			s_label = val.GetComponentInChildren<TMP_Text>(true);
		}

		private static void OnClick()
		{
			int length = Enum.GetValues(typeof(FoodSort)).Length;
			Plugin.SortMode.Value = (FoodSort)((int)(Plugin.SortMode.Value + 1) % length);
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null)
			{
				UpdateCraftingPanel.Invoke(instance, new object[1] { false });
			}
		}
	}
	internal static class Texts
	{
		private static bool Pt
		{
			get
			{
				if (Localization.instance != null)
				{
					return Localization.instance.GetSelectedLanguage().StartsWith("Portuguese", StringComparison.OrdinalIgnoreCase);
				}
				return false;
			}
		}

		public static string SortLabel(FoodSort mode)
		{
			return (Pt ? "Ordem: " : "Sort: ") + ModeName(mode);
		}

		private static string ModeName(FoodSort mode)
		{
			switch (mode)
			{
			case FoodSort.Health:
				if (!Pt)
				{
					return "Health";
				}
				return "Vida";
			case FoodSort.Stamina:
				return "Stamina";
			case FoodSort.Eitr:
				return "Eitr";
			case FoodSort.Total:
				return "Total";
			default:
				if (!Pt)
				{
					return "Default";
				}
				return "Padrão";
			}
		}
	}
}