Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FoodTracker v1.0.0
FoodTracker.dll
Decompiled 2 days agousing 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"; } }