using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ExtraFoodSlots")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HP")] [assembly: AssemblyProduct("ExtraFoodSlots")] [assembly: AssemblyCopyright("Copyright © HP 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("83294e72-4c43-4a61-8792-54257419a120")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace ExtraFoodSlots; [BepInPlugin("youdied.extrafoodslots", "Extra Food Slots", "1.0.1")] [BepInProcess("valheim.exe")] public class ExtraFoodSlotsPlugin : BaseUnityPlugin { public const string PluginGUID = "youdied.extrafoodslots"; public const string PluginName = "Extra Food Slots"; public const string PluginVersion = "1.0.1"; public static ManualLogSource Log; public static ConfigEntry ExtraSlotCount; private readonly Harmony _harmony = new Harmony("youdied.extrafoodslots"); private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ExtraSlotCount = ((BaseUnityPlugin)this).Config.Bind("General", "ExtraSlotCount", 1, new ConfigDescription("How many extra food slots to add (1-3). Can be changed in-game via the Config Manager.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 3), Array.Empty())); _harmony.PatchAll(); Log.LogInfo((object)string.Format("[EFS] Extra Food Slots v{0} loaded (build 19). ExtraSlots={1}", "1.0.1", ExtraSlotCount.Value)); } private void OnDestroy() { _harmony.UnpatchSelf(); } } public static class ExtraFoodSlotsHUD { private class SlotUI { public RectTransform Root; public Image TimerBar; public Image Icon; public TMP_Text Time; } private static readonly List _slots = new List(); private static Hud _builtFor = null; private static bool _gaveUp = false; private static int _builtCount = 0; private const float SlotX = -67.15259f; private const float SlotY0 = 57.998566f; private const float SlotStep = 46f; private const float SlotSize = 45f; public static bool IsBuiltFor(Hud hud) { int value = ExtraFoodSlotsPlugin.ExtraSlotCount.Value; if (_builtCount != value) { _gaveUp = false; _builtFor = null; } return (Object)(object)_builtFor == (Object)(object)hud && _slots.Count == value; } public static void MarkDirty() { _builtFor = null; _gaveUp = false; } public static void BuildSlots(Hud hud) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown if (_gaveUp) { return; } foreach (SlotUI slot in _slots) { if ((Object)(object)slot.Root != (Object)null) { Object.Destroy((Object)(object)((Component)slot.Root).gameObject); } } _slots.Clear(); int value = ExtraFoodSlotsPlugin.ExtraSlotCount.Value; GameObject val = FindInChildren(((Component)hud).transform, "food0"); if ((Object)(object)val == (Object)null) { ExtraFoodSlotsPlugin.Log.LogWarning((object)"[EFS] Could not find 'food0' in HUD hierarchy."); _gaveUp = true; _builtFor = hud; return; } RectTransform component = val.GetComponent(); Transform parent = ((Transform)component).parent; RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); for (int i = 0; i < value; i++) { GameObject val3 = Object.Instantiate(val, (Transform)(object)val2, false); ((Object)val3).name = $"EFS_food{3 + i}"; RectTransform component2 = val3.GetComponent(); component2.anchorMin = component.anchorMin; component2.anchorMax = component.anchorMax; component2.pivot = component.pivot; component2.sizeDelta = new Vector2(45f, 45f); component2.anchoredPosition = new Vector2(-67.15259f, 57.998566f + 46f * (float)(3 + i)); ((Transform)component2).SetAsLastSibling(); val3.SetActive(true); Image component3 = val3.GetComponent(); Image val4 = null; TMP_Text val5 = null; foreach (Transform item in val3.transform) { Transform val6 = item; if ((Object)(object)val4 == (Object)null) { val4 = ((Component)val6).GetComponent(); } if ((Object)(object)val5 == (Object)null) { val5 = ((Component)val6).GetComponent(); } } _slots.Add(new SlotUI { Root = component2, TimerBar = component3, Icon = val4, Time = val5 }); } _builtFor = hud; _builtCount = value; ExtraFoodSlotsPlugin.Log.LogInfo((object)$"[EFS] Built {value} extra slot(s)."); } public static void UpdateSlots(Player player) { //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) if (_slots.Count == 0 || (Object)(object)player == (Object)null) { return; } List foods = player.GetFoods(); for (int i = 0; i < _slots.Count; i++) { SlotUI slotUI = _slots[i]; if ((Object)(object)slotUI.Root == (Object)null) { continue; } int num = 3 + i; bool flag = num < foods.Count; ((Component)slotUI.Root).gameObject.SetActive(true); if (flag) { Food val = foods[num]; float fillAmount = Mathf.Clamp01(val.m_time / val.m_item.m_shared.m_foodBurnTime); if ((Object)(object)slotUI.TimerBar != (Object)null) { slotUI.TimerBar.fillAmount = fillAmount; ((Graphic)slotUI.TimerBar).color = new Color(0f, 0f, 0f, 0.503f); } if ((Object)(object)slotUI.Icon != (Object)null) { ((Component)slotUI.Icon).gameObject.SetActive(true); slotUI.Icon.sprite = val.m_item.GetIcon(); ((Graphic)slotUI.Icon).color = (Color)(val.CanEatAgain() ? new Color(1f, 1f, 1f, 0.7f + Mathf.Sin(Time.time * 5f) * 0.3f) : Color.white); } if ((Object)(object)slotUI.Time != (Object)null) { ((Component)slotUI.Time).gameObject.SetActive(true); if (val.m_time >= 60f) { slotUI.Time.text = Mathf.CeilToInt(val.m_time / 60f) + "m"; ((Graphic)slotUI.Time).color = Color.white; } else { slotUI.Time.text = Mathf.FloorToInt(val.m_time) + "s"; ((Graphic)slotUI.Time).color = new Color(1f, 1f, 1f, 0.4f + Mathf.Sin(Time.time * 10f) * 0.6f); } } } else { if ((Object)(object)slotUI.TimerBar != (Object)null) { slotUI.TimerBar.fillAmount = 1f; ((Graphic)slotUI.TimerBar).color = new Color(0f, 0f, 0f, 0.2f); } if ((Object)(object)slotUI.Icon != (Object)null) { ((Component)slotUI.Icon).gameObject.SetActive(false); } if ((Object)(object)slotUI.Time != (Object)null) { ((Component)slotUI.Time).gameObject.SetActive(true); slotUI.Time.text = ""; } } } } private static GameObject FindInChildren(Transform parent, string name) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown foreach (Transform item in parent) { Transform val = item; if (((Object)val).name == name) { return ((Component)val).gameObject; } GameObject val2 = FindInChildren(val, name); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } } [HarmonyPatch(typeof(Player), "CanEat")] public static class Patch_Player_CanEat { private static readonly FieldInfo FFoods = typeof(Player).GetField("m_foods", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); [HarmonyPrefix] public static bool Prefix(Player __instance, ItemData item, bool showMessages, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (FFoods == null) { return true; } List list = (List)FFoods.GetValue(__instance); int count = list.Count; int num = 3 + ExtraFoodSlotsPlugin.ExtraSlotCount.Value; if (count < 3 || count >= num) { return true; } foreach (Food item2 in list) { if (item2.m_item.m_shared.m_name == item.m_shared.m_name) { if (item2.CanEatAgain()) { __result = true; return false; } if (showMessages) { ((Character)__instance).Message((MessageType)2, Localization.instance.Localize("$msg_nomore", new string[1] { item.m_shared.m_name }), 0, (Sprite)null); } __result = false; return false; } } foreach (Food item3 in list) { if (item3.CanEatAgain()) { __result = true; return false; } } __result = true; return false; } } [HarmonyPatch(typeof(Player), "EatFood")] public static class Patch_Player_EatFood { private static readonly FieldInfo FFoods = typeof(Player).GetField("m_foods", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); [HarmonyPrefix] public static bool Prefix(Player __instance, ItemData item, ref bool __result) { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (FFoods == null) { return true; } List list = (List)FFoods.GetValue(__instance); int count = list.Count; if (count < 3) { return true; } foreach (Food item2 in list) { if (item2.m_item.m_shared.m_name == item.m_shared.m_name) { return true; } } int num = 3 + ExtraFoodSlotsPlugin.ExtraSlotCount.Value; if (count < num) { string text = ""; if (item.m_shared.m_food > 0f) { text += $" +{item.m_shared.m_food} $item_food_health "; } if (item.m_shared.m_foodStamina > 0f) { text += $" +{item.m_shared.m_foodStamina} $item_food_stamina "; } if (item.m_shared.m_foodEitr > 0f) { text += $" +{item.m_shared.m_foodEitr} $item_food_eitr "; } ((Character)__instance).Message((MessageType)2, text, 0, (Sprite)null); Food val = new Food(); val.m_name = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : item.m_shared.m_name); val.m_item = item; val.m_time = item.m_shared.m_foodBurnTime; val.m_health = item.m_shared.m_food; val.m_stamina = item.m_shared.m_foodStamina; val.m_eitr = item.m_shared.m_foodEitr; list.Add(val); typeof(Player).GetMethod("UpdateFood", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(__instance, new object[2] { 0f, true }); __result = true; return false; } return true; } } [HarmonyPatch(typeof(Hud), "UpdateFood")] public static class Patch_Hud_UpdateFood { [HarmonyPostfix] public static void Postfix(Hud __instance) { if (!ExtraFoodSlotsHUD.IsBuiltFor(__instance)) { ExtraFoodSlotsHUD.BuildSlots(__instance); } ExtraFoodSlotsHUD.UpdateSlots(Player.m_localPlayer); } } [HarmonyPatch(typeof(Hud), "LateUpdate")] public static class Patch_Hud_LateUpdate { [HarmonyPostfix] public static void Postfix(Hud __instance) { if (!ExtraFoodSlotsHUD.IsBuiltFor(__instance)) { ExtraFoodSlotsHUD.BuildSlots(__instance); ExtraFoodSlotsPlugin.Log.LogInfo((object)"[EFS] HUD built via LateUpdate fallback."); } } }