Decompiled source of ExtraFoodSlots v1.0.1

ExtraFoodSlots.dll

Decompiled 2 weeks ago
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<int> 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<int>("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<int>(1, 3), Array.Empty<object>()));
		_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<SlotUI> _slots = new List<SlotUI>();

	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<RectTransform>();
		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<GameObject>(val, (Transform)(object)val2, false);
			((Object)val3).name = $"EFS_food{3 + i}";
			RectTransform component2 = val3.GetComponent<RectTransform>();
			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>();
			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<Image>();
				}
				if ((Object)(object)val5 == (Object)null)
				{
					val5 = ((Component)val6).GetComponent<TMP_Text>();
				}
			}
			_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<Food> 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<Food> list = (List<Food>)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<Food> list = (List<Food>)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.");
		}
	}
}