Decompiled source of FoodTracker v1.0.0

FoodTracker.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Koendertjh.Shared;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FoodTracker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a45c570d17c512d77d75166ff42bc1dee72ef243")]
[assembly: AssemblyProduct("FoodTracker")]
[assembly: AssemblyTitle("FoodTracker")]
[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 Koendertjh.Shared
{
	internal static class AchievementStats
	{
		private static readonly Dictionary<object, KeyValuePair<int, HashSet<string>>> s_keys = new Dictionary<object, KeyValuePair<int, HashSet<string>>>();

		internal static Achievement Find(string id)
		{
			if ((Object)(object)Achievements.m_instance == (Object)null)
			{
				return null;
			}
			foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists)
			{
				foreach (Achievement achievement in achievementList.m_achievements)
				{
					if ((Object)(object)achievement != (Object)null && achievement.m_id == id)
					{
						return achievement;
					}
				}
			}
			return null;
		}

		internal static PlayerStats StatsFor(Achievement achievement)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Game instance = Game.instance;
			PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null);
			if (val == null || (Object)(object)achievement == (Object)null)
			{
				return null;
			}
			return val.m_playerStats[achievement.m_difficultyRequirement];
		}

		internal static HashSet<string> Keys(List<DictStatRequirement> triggers)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (triggers == null)
			{
				return new HashSet<string>();
			}
			if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count)
			{
				return value.Value;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (DictStatRequirement trigger in triggers)
			{
				hashSet.Add(trigger.m_stat);
			}
			s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet);
			return hashSet;
		}

		internal static HashSet<string> Keys(List<EnemyStatRequirement> triggers)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (triggers == null)
			{
				return new HashSet<string>();
			}
			if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count)
			{
				return value.Value;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (EnemyStatRequirement trigger in triggers)
			{
				hashSet.Add(trigger.m_stat);
			}
			s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet);
			return hashSet;
		}

		internal static bool Has(Dictionary<string, float> stats, string key)
		{
			if (stats != null && stats.TryGetValue(key, out var value))
			{
				return value >= 1f;
			}
			return false;
		}

		internal static int CountDone(HashSet<string> keys, Dictionary<string, float> stats)
		{
			int num = 0;
			foreach (string key in keys)
			{
				if (Has(stats, key))
				{
					num++;
				}
			}
			return num;
		}
	}
}
namespace FoodTracker
{
	internal static class FoodStatus
	{
		internal const string GourmetId = "AllFoodEaten";

		internal const string MasterChefId = "AllFoodCooked";

		private static Achievement s_gourmet;

		private static Achievement s_masterChef;

		internal static Achievement Gourmet
		{
			get
			{
				if (!((Object)(object)s_gourmet != (Object)null))
				{
					return s_gourmet = AchievementStats.Find("AllFoodEaten");
				}
				return s_gourmet;
			}
		}

		internal static Achievement MasterChef
		{
			get
			{
				if (!((Object)(object)s_masterChef != (Object)null))
				{
					return s_masterChef = AchievementStats.Find("AllFoodCooked");
				}
				return s_masterChef;
			}
		}

		internal static HashSet<string> EdibleItems => AchievementStats.Keys(Gourmet?.m_foodEatenTriggers);

		internal static HashSet<string> CookableItems => AchievementStats.Keys(MasterChef?.m_itemCraftTriggers);

		internal static Dictionary<string, float> EatenStats => AchievementStats.StatsFor(Gourmet)?.m_foodEatenStats;

		internal static Dictionary<string, float> CookedStats => AchievementStats.StatsFor(MasterChef)?.m_itemCraftStats;

		internal static bool NotEatenYet(string itemName)
		{
			if (EdibleItems.Contains(itemName))
			{
				return !AchievementStats.Has(EatenStats, itemName);
			}
			return false;
		}

		internal static bool NotCookedYet(string itemName)
		{
			if (CookableItems.Contains(itemName))
			{
				return !AchievementStats.Has(CookedStats, itemName);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	internal static class InventoryMarkers
	{
		private const string MarkerName = "FoodTrackerMarker";

		private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsRef = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements");

		private static readonly Dictionary<InventoryElement, GameObject> s_markers = new Dictionary<InventoryElement, GameObject>();

		private static ItemData[] s_slots = (ItemData[])(object)new ItemData[0];

		private static void Postfix(InventoryGrid __instance)
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = __instance.GetInventory();
			bool flag = FoodTrackerPlugin.InventoryMarkers.Value && inventory != null && (Object)(object)Game.instance != (Object)null;
			if (!flag && s_markers.Count == 0)
			{
				return;
			}
			int num = 0;
			if (flag)
			{
				num = inventory.GetWidth();
				int num2 = num * inventory.GetHeight();
				if (s_slots.Length < num2)
				{
					s_slots = (ItemData[])(object)new ItemData[num2];
				}
				Array.Clear(s_slots, 0, s_slots.Length);
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					int num3 = allItem.m_gridPos.y * num + allItem.m_gridPos.x;
					if (num3 >= 0 && num3 < num2)
					{
						s_slots[num3] = allItem;
					}
				}
			}
			foreach (InventoryElement item in ElementsRef.Invoke(__instance))
			{
				ItemData val = null;
				if (flag && item.m_used)
				{
					int num4 = item.Position.y * num + item.Position.x;
					if (num4 >= 0 && num4 < s_slots.Length)
					{
						val = s_slots[num4];
					}
				}
				bool flag2 = val != null && FoodStatus.NotEatenYet(val.m_shared.m_name);
				if (!s_markers.TryGetValue(item, out var value) || (Object)(object)value == (Object)null)
				{
					if (!flag2)
					{
						continue;
					}
					value = CreateMarker(((Component)item).transform);
					s_markers[item] = value;
					if (s_markers.Count > 256)
					{
						DropDestroyed();
					}
				}
				if (value.activeSelf != flag2)
				{
					value.SetActive(flag2);
				}
			}
		}

		private static void DropDestroyed()
		{
			List<InventoryElement> list = new List<InventoryElement>();
			foreach (KeyValuePair<InventoryElement, GameObject> s_marker in s_markers)
			{
				if ((Object)(object)s_marker.Key == (Object)null || (Object)(object)s_marker.Value == (Object)null)
				{
					list.Add(s_marker.Key);
				}
			}
			foreach (InventoryElement item in list)
			{
				s_markers.Remove(item);
			}
		}

		private static GameObject CreateMarker(Transform slot)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00a8: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			GameObject val = new GameObject("FoodTrackerMarker", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(slot, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = new Vector2(8f, 0f);
			val2.sizeDelta = new Vector2(8f, 8f);
			((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, 45f);
			((Transform)val2).SetAsLastSibling();
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = FoodTrackerPlugin.MarkerColor.Value;
			((Graphic)component).raycastTarget = false;
			Outline component2 = val.GetComponent<Outline>();
			((Shadow)component2).effectColor = new Color(0f, 0f, 0f, 0.9f);
			((Shadow)component2).effectDistance = new Vector2(1.2f, -1.2f);
			val.SetActive(false);
			return val;
		}
	}
	[BepInPlugin("com.koendertjh.foodtracker", "FoodTracker", "1.0.0")]
	public class FoodTrackerPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.koendertjh.foodtracker";

		public const string ModName = "FoodTracker";

		public const string ModVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> TooltipHints;

		internal static ConfigEntry<bool> ShowProgress;

		internal static ConfigEntry<bool> InventoryMarkers;

		internal static ConfigEntry<Color> MarkerColor;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			TooltipHints = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "TooltipHints", true, "Item tooltips say when you haven't eaten or made the item yet.");
			ShowProgress = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "ShowProgress", true, "Tooltips of food also show your progress for The Gourmet and The Master Chef.");
			InventoryMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Inventory", "InventoryMarkers", true, "A small diamond on the left of inventory and chest slots holding food you haven't eaten yet.");
			MarkerColor = ((BaseUnityPlugin)this).Config.Bind<Color>("2 - Inventory", "MarkerColor", new Color(1f, 0.7f, 0.28f), "Colour of the inventory marker.");
			_harmony = new Harmony("com.koendertjh.foodtracker");
			_harmony.PatchAll(typeof(FoodTrackerPlugin).Assembly);
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	internal static class TooltipPatch
	{
		private const string HintColor = "#ffb347";

		private const string ProgressColor = "#a0a0a0";

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

		private static float s_cacheUntil;

		private static void Postfix(ItemData item, ref string __result)
		{
			if (!FoodTrackerPlugin.TooltipHints.Value || item?.m_shared == null || (Object)(object)Game.instance == (Object)null)
			{
				return;
			}
			string name = item.m_shared.m_name;
			if (FoodStatus.EdibleItems.Contains(name) || FoodStatus.CookableItems.Contains(name))
			{
				if (Time.time >= s_cacheUntil)
				{
					s_suffixes.Clear();
					s_cacheUntil = Time.time + 1f;
				}
				if (!s_suffixes.TryGetValue(name, out var value))
				{
					value = (s_suffixes[name] = Suffix(name));
				}
				if (value.Length > 0)
				{
					__result += value;
				}
			}
		}

		private static string Suffix(string name)
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (FoodStatus.NotEatenYet(name))
			{
				stringBuilder.Append("\n\n<color=#ffb347>You haven't eaten this yet. I wonder what it tastes like...</color>");
			}
			if (FoodStatus.NotCookedYet(name))
			{
				stringBuilder.Append("\n<color=#ffb347>You haven't made this yet.</color>");
			}
			if (FoodTrackerPlugin.ShowProgress.Value)
			{
				if (FoodStatus.EdibleItems.Contains(name))
				{
					stringBuilder.Append(Progress(FoodStatus.Gourmet, AchievementStats.CountDone(FoodStatus.EdibleItems, FoodStatus.EatenStats), FoodStatus.EdibleItems.Count));
				}
				if (FoodStatus.CookableItems.Contains(name))
				{
					stringBuilder.Append(Progress(FoodStatus.MasterChef, AchievementStats.CountDone(FoodStatus.CookableItems, FoodStatus.CookedStats), FoodStatus.CookableItems.Count));
				}
			}
			return stringBuilder.ToString();
		}

		private static string Progress(Achievement achievement, int done, int total)
		{
			return string.Format("\n<color={0}>{1}: {2} / {3}</color>", "#a0a0a0", Localization.instance.Localize(achievement.m_name), done, total);
		}
	}
	internal static class PluginInfo
	{
		public const string Version = "1.0.0";
	}
}