Decompiled source of Cook Book v1.0.5

BepInEx/plugins/CookBook.dll

Decompiled a day 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 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: AssemblyTitle("Cook Book")]
[assembly: AssemblyCompany("Daxtillion")]
[assembly: AssemblyProduct("Cook Book")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.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 CookBook
{
	[BepInPlugin("com.codex.valheim.cookbook", "Cook Book", "1.0.3")]
	public sealed class FoodStatsPlugin : BaseUnityPlugin
	{
		private enum StatKind
		{
			None,
			Health,
			Stamina,
			Eitr
		}

		private sealed class Row
		{
			public readonly object Pair;

			public readonly GameObject Element;

			public readonly float Health;

			public readonly float Stamina;

			public readonly float Eitr;

			public readonly float PrimaryValue;

			public readonly StatKind PrimaryKind;

			public Row(object pair, GameObject element, float health, float stamina, float eitr)
			{
				Pair = pair;
				Element = element;
				Health = health;
				Stamina = stamina;
				Eitr = eitr;
				PrimaryValue = Mathf.Max(new float[3] { health, stamina, eitr });
				PrimaryKind = ((PrimaryValue == health) ? StatKind.Health : ((PrimaryValue == stamina) ? StatKind.Stamina : StatKind.Eitr));
			}

			public float GetValue(StatKind kind)
			{
				return kind switch
				{
					StatKind.Eitr => Eitr, 
					StatKind.Stamina => Stamina, 
					StatKind.Health => Health, 
					_ => 0f, 
				};
			}
		}

		private const string StatObjectName = "FoodStatsValue";

		private static readonly Color HealthColor = new Color(1f, 0.43f, 0.43f, 1f);

		private static readonly Color StaminaColor = new Color(1f, 0.88f, 0.38f, 1f);

		private static readonly Color EitrColor = new Color(0.83f, 0.68f, 1f, 1f);

		private static readonly BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private readonly List<Row> _baseline = new List<Row>();

		private readonly Dictionary<ItemDrop, ItemDrop> _cookedResults = new Dictionary<ItemDrop, ItemDrop>();

		private InventoryGui _gui;

		private readonly Button[] _statButtons = (Button[])(object)new Button[3];

		private readonly TMP_Text[] _buttonLabels = (TMP_Text[])(object)new TMP_Text[3];

		private StatKind _sortMode;

		private float _nextRefresh;

		private void Update()
		{
			if (!(Time.unscaledTime < _nextRefresh))
			{
				_nextRefresh = Time.unscaledTime + 0.15f;
				Refresh();
			}
		}

		private static T Field<T>(object target, string name) where T : class
		{
			return target?.GetType().GetField(name, PrivateInstance)?.GetValue(target) as T;
		}

		private void Refresh()
		{
			InventoryGui instance = InventoryGui.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			RectTransform val = Field<RectTransform>(instance, "m_crafting");
			if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy)
			{
				Button[] statButtons = _statButtons;
				foreach (Button val2 in statButtons)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						((Component)val2).gameObject.SetActive(false);
					}
				}
				return;
			}
			if ((Object)(object)_gui != (Object)(object)instance)
			{
				_gui = instance;
				_baseline.Clear();
				for (int j = 0; j < _statButtons.Length; j++)
				{
					_statButtons[j] = null;
				}
			}
			IList list = Field<IList>(instance, "m_availableRecipes");
			RectTransform val3 = Field<RectTransform>(instance, "m_recipeListRoot");
			if (list == null || !Object.op_Implicit((Object)(object)val3))
			{
				return;
			}
			List<Row> list2 = new List<Row>(list.Count);
			foreach (object item in list)
			{
				Type type = item.GetType();
				object? obj = type.GetProperty("InterfaceElement")?.GetValue(item, null);
				GameObject val4 = (GameObject)((obj is GameObject) ? obj : null);
				object? obj2 = type.GetProperty("ItemData")?.GetValue(item, null);
				ItemData val5 = (ItemData)((obj2 is ItemData) ? obj2 : null);
				object? obj3 = type.GetProperty("Recipe")?.GetValue(item, null);
				Recipe val6 = (Recipe)((obj3 is Recipe) ? obj3 : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					(float, float, float) stats = GetStats(val5 ?? val6?.m_item?.m_itemData);
					list2.Add(new Row(item, val4, stats.Item1, stats.Item2, stats.Item3));
				}
			}
			if (list2.Count != _baseline.Count || list2.Any((Row r) => !_baseline.Any((Row b) => (Object)(object)b.Element == (Object)(object)r.Element)))
			{
				_baseline.Clear();
				_baseline.AddRange(list2);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Recipe rows: " + list2.Count + "; food stats found: " + list2.Count((Row r) => r.PrimaryValue > 0f)));
			}
			bool flag = false;
			foreach (Row item2 in list2)
			{
				if (!(item2.PrimaryValue <= 0f))
				{
					flag = true;
					SetStatLabel(item2);
				}
			}
			EnsureButtons(instance, val);
			for (int num = 0; num < _statButtons.Length; num++)
			{
				if (Object.op_Implicit((Object)(object)_statButtons[num]))
				{
					((Component)_statButtons[num]).gameObject.SetActive(flag);
				}
			}
			if (!flag)
			{
				return;
			}
			UpdateButtonStyles();
			if (_sortMode == StatKind.None)
			{
				return;
			}
			ApplyOrder(list, (from r in list2
				orderby r.GetValue(_sortMode) descending, _baseline.FindIndex((Row b) => (Object)(object)b.Element == (Object)(object)r.Element)
				select r).ToList());
		}

		private (float health, float stamina, float eitr) GetStats(ItemData data)
		{
			if (data == null || data.m_shared == null)
			{
				return (health: 0f, stamina: 0f, eitr: 0f);
			}
			SharedData shared = data.m_shared;
			if (shared.m_food <= 0f && shared.m_foodStamina <= 0f && shared.m_foodEitr <= 0f)
			{
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(shared) : null);
				ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 != (Object)null && TryCookedResult(val2, out var result))
				{
					shared = result.m_itemData.m_shared;
				}
			}
			return (health: shared.m_food, stamina: shared.m_foodStamina, eitr: shared.m_foodEitr);
		}

		private bool TryCookedResult(ItemDrop ingredient, out ItemDrop result)
		{
			if (_cookedResults.TryGetValue(ingredient, out result))
			{
				return (Object)(object)result != (Object)null;
			}
			result = null;
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance != (Object)null)
			{
				foreach (GameObject prefab in instance.m_prefabs)
				{
					if (!Object.op_Implicit((Object)(object)prefab))
					{
						continue;
					}
					CookingStation component = prefab.GetComponent<CookingStation>();
					if (!Object.op_Implicit((Object)(object)component))
					{
						continue;
					}
					foreach (ItemConversion item in component.m_conversion)
					{
						if ((Object)(object)item.m_from == (Object)(object)ingredient && Object.op_Implicit((Object)(object)item.m_to))
						{
							result = item.m_to;
							break;
						}
					}
					if (Object.op_Implicit((Object)(object)result))
					{
						break;
					}
				}
			}
			_cookedResults[ingredient] = result;
			return (Object)(object)result != (Object)null;
		}

		private static void SetStatLabel(Row row)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			Transform val = row.Element.transform.Find("FoodStatsValue");
			TMP_Text component;
			if (Object.op_Implicit((Object)(object)val))
			{
				component = ((Component)val).GetComponent<TMP_Text>();
			}
			else
			{
				TMP_Text componentInChildren = row.Element.GetComponentInChildren<TMP_Text>(true);
				if (!Object.op_Implicit((Object)(object)componentInChildren))
				{
					return;
				}
				GameObject val2 = new GameObject("FoodStatsValue", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				val2.transform.SetParent(row.Element.transform, false);
				RectTransform val3 = (RectTransform)val2.transform;
				val3.anchorMin = new Vector2(1f, 0f);
				val3.anchorMax = new Vector2(1f, 1f);
				val3.pivot = new Vector2(1f, 0.5f);
				val3.anchoredPosition = new Vector2(-8f, 0f);
				val3.sizeDelta = new Vector2(56f, 0f);
				component = (TMP_Text)(object)val2.GetComponent<TextMeshProUGUI>();
				component.font = componentInChildren.font;
				component.fontSize = componentInChildren.fontSize * 0.85f;
				component.alignment = (TextAlignmentOptions)516;
				((Graphic)component).raycastTarget = false;
				component.enableWordWrapping = false;
				componentInChildren.overflowMode = (TextOverflowModes)1;
				RectTransform rectTransform = componentInChildren.rectTransform;
				Rect rect = componentInChildren.rectTransform.rect;
				rectTransform.SetSizeWithCurrentAnchors((Axis)0, Mathf.Max(40f, ((Rect)(ref rect)).width - 60f));
			}
			if (Object.op_Implicit((Object)(object)component))
			{
				component.text = Mathf.RoundToInt(row.PrimaryValue).ToString();
				((Graphic)component).color = GetColor(row.PrimaryKind);
			}
		}

		private static Color GetColor(StatKind kind)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(kind switch
			{
				StatKind.Stamina => StaminaColor, 
				StatKind.Health => HealthColor, 
				_ => EitrColor, 
			});
		}

		private void EnsureButtons(InventoryGui gui, RectTransform crafting)
		{
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			Button val = Field<Button>(gui, "m_repairButton");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Transform parent = ((Component)val).transform.parent;
			RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				val2 = crafting;
			}
			for (int i = 0; i < _statButtons.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)_statButtons[i]))
				{
					StatKind kind = (StatKind)(i + 1);
					GameObject val3 = new GameObject("CookBook" + kind.ToString() + "Sort", new Type[3]
					{
						typeof(RectTransform),
						typeof(Image),
						typeof(Button)
					});
					val3.transform.SetParent((Transform)(object)val2, false);
					RectTransform val4 = (RectTransform)val3.transform;
					val4.anchorMin = Vector2.zero;
					val4.anchorMax = Vector2.zero;
					val4.pivot = new Vector2(0f, 1f);
					val4.sizeDelta = new Vector2(60f, 32f);
					Button component = val3.GetComponent<Button>();
					((Selectable)component).targetGraphic = (Graphic)(object)val3.GetComponent<Image>();
					((UnityEvent)component.onClick).AddListener((UnityAction)delegate
					{
						ToggleSort(kind);
					});
					_statButtons[i] = component;
					GameObject val5 = new GameObject("Label", new Type[2]
					{
						typeof(RectTransform),
						typeof(TextMeshProUGUI)
					});
					val5.transform.SetParent(val3.transform, false);
					RectTransform val6 = (RectTransform)val5.transform;
					val6.anchorMin = Vector2.zero;
					val6.anchorMax = Vector2.one;
					val6.offsetMin = Vector2.zero;
					val6.offsetMax = Vector2.zero;
					TextMeshProUGUI component2 = val5.GetComponent<TextMeshProUGUI>();
					TMP_Text componentInChildren = ((Component)crafting).GetComponentInChildren<TMP_Text>(true);
					if (Object.op_Implicit((Object)(object)componentInChildren))
					{
						((TMP_Text)component2).font = componentInChildren.font;
					}
					((TMP_Text)component2).fontSize = 15f;
					((TMP_Text)component2).alignment = (TextAlignmentOptions)514;
					((Graphic)component2).raycastTarget = false;
					((TMP_Text)component2).text = ((kind == StatKind.Health) ? "HP" : ((kind == StatKind.Stamina) ? "STA" : "EIT"));
					_buttonLabels[i] = (TMP_Text)(object)component2;
				}
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			((RectTransform)((Component)val).transform).GetWorldCorners(array);
			Vector3 val7 = ((Transform)val2).InverseTransformPoint(array[0]);
			Vector3 val8 = ((Transform)val2).InverseTransformPoint(array[3]);
			float num = (val7.x + val8.x) * 0.5f;
			Rect rect = val2.rect;
			float num2 = num - ((Rect)(ref rect)).xMin - 30f;
			float y = val7.y;
			rect = val2.rect;
			float num3 = y - ((Rect)(ref rect)).yMin - 8f;
			for (int num4 = 0; num4 < _statButtons.Length; num4++)
			{
				((RectTransform)((Component)_statButtons[num4]).transform).anchoredPosition = new Vector2(num2, num3 - (float)num4 * 38f);
			}
		}

		private void UpdateButtonStyles()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _statButtons.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)_statButtons[i]))
				{
					StatKind statKind = (StatKind)(i + 1);
					Color color = GetColor(statKind);
					bool flag = _sortMode == statKind;
					((Graphic)((Component)_statButtons[i]).GetComponent<Image>()).color = (flag ? new Color(color.r * 0.45f, color.g * 0.45f, color.b * 0.45f, 0.98f) : new Color(0.13f, 0.15f, 0.16f, 0.95f));
					((Graphic)_buttonLabels[i]).color = color;
				}
			}
		}

		private void ToggleSort(StatKind kind)
		{
			_sortMode = ((_sortMode != kind) ? kind : StatKind.None);
			IList list = Field<IList>(_gui, "m_availableRecipes");
			if (list == null)
			{
				return;
			}
			List<Row> list2 = _baseline.Where((Row r) => Object.op_Implicit((Object)(object)r.Element)).ToList();
			if (_sortMode != StatKind.None)
			{
				list2 = list2.OrderByDescending((Row r) => r.GetValue(_sortMode)).ToList();
			}
			ApplyOrder(list, list2);
			_nextRefresh = 0f;
		}

		private static void ApplyOrder(IList pairs, List<Row> ordered)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (ordered.Count != pairs.Count)
			{
				return;
			}
			List<Vector2> list = new List<Vector2>(pairs.Count);
			foreach (object pair in pairs)
			{
				object? obj = pair.GetType().GetProperty("InterfaceElement")?.GetValue(pair, null);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return;
				}
				list.Add(((RectTransform)val.transform).anchoredPosition);
			}
			for (int i = 0; i < ordered.Count; i++)
			{
				pairs[i] = ordered[i].Pair;
				((RectTransform)ordered[i].Element.transform).anchoredPosition = list[i];
				ordered[i].Element.transform.SetSiblingIndex(i);
			}
		}
	}
}