Decompiled source of Food Bag v1.0.0

FoodBag.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 AzuEPI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("FoodBag")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FoodBag")]
[assembly: AssemblyTitle("FoodBag")]
[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 ValheimLiteni.FoodBag
{
	[BepInPlugin("ValheimLiteni.FoodBag", "Food Bag", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "ValheimLiteni.FoodBag";

		public const string Version = "1.0.0";

		public const string AzuEpiGuid = "Azumatt.AzuExtendedPlayerInventory";

		private const int MaxFoods = 3;

		internal static ManualLogSource Log;

		private ConfigEntry<bool> modEnabled;

		private ConfigEntry<int> slotCount;

		private ConfigEntry<string> slotName;

		private ConfigEntry<bool> autoEat;

		private ConfigEntry<int> refreshAt;

		private ConfigEntry<bool> useOtherFood;

		private ConfigEntry<KeyboardShortcut> quickEatKey;

		private ConfigEntry<bool> messages;

		private readonly List<string> slots = new List<string>();

		private float nextCheck;

		private void Awake()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Turn the whole mod on or off (the bag slots stay).");
			slotCount = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Food bag", "Slots", 3, new ConfigDescription("How many food slots the bag has. Restart the game after changing it - empty the slots you remove first.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>()));
			slotName = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Food bag", "Slot name", "Food", "Label of the bag slots (a number is added).");
			autoEat = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto eat", "Auto eat", true, "Eat from the bag by itself: when a food slot is free, and when a food is about to run out.");
			refreshAt = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Auto eat", "Refresh below %", 5, new ConfigDescription("A food is eaten again when less than this much of its time is left. 0 = only when it has run out (the slot is free). The game only lets you re-eat a food after half of its time.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>()));
			useOtherFood = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Auto eat", "Use another food", true, "When the food that runs out is not in the bag any more, eat another food from the bag instead.");
			quickEatKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("4 - Quick eat", "Quick eat key", new KeyboardShortcut((KeyCode)102, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Eat from the bag now: fills a free food slot, or refreshes the food closest to running out.");
			messages = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Quick eat", "Messages", true, "Show a short message when the bag eats something.");
			if (!API.IsLoaded())
			{
				Log.LogError((object)"AzuExtendedPlayerInventory is not loaded - no food bag");
				return;
			}
			for (int i = 1; i <= slotCount.Value; i++)
			{
				string text = $"{slotName.Value} {i}";
				if (API.AddQuickSlot(text, true, -1))
				{
					slots.Add(text);
				}
			}
			int num = RestrictToFood();
			Log.LogInfo((object)$"food bag: {slots.Count} slots ({num} restricted to food)");
		}

		private int RestrictToFood()
		{
			int num = 0;
			try
			{
				if (!(AccessTools.Property(typeof(API), "CustomSlots")?.GetValue(null) is IEnumerable enumerable))
				{
					Log.LogWarning((object)"AzuEPI changed: the bag slots take any item");
					return 0;
				}
				Func<ItemData, bool> value = IsFood;
				foreach (object item2 in enumerable)
				{
					if (item2 == null)
					{
						continue;
					}
					string item = AccessTools.Field(item2.GetType(), "OriginalName")?.GetValue(item2) as string;
					if (slots.Contains(item))
					{
						FieldInfo fieldInfo = AccessTools.Field(item2.GetType(), "Valid");
						if (!(fieldInfo == null))
						{
							fieldInfo.SetValue(item2, value);
							num++;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("restricting the bag to food: " + ex.Message));
			}
			return num;
		}

		internal static bool IsFood(ItemData item)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			if (item != null && (int)item.m_shared.m_itemType == 2)
			{
				if (!(item.m_shared.m_food > 0f) && !(item.m_shared.m_foodStamina > 0f))
				{
					return item.m_shared.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		private List<ItemData> BagItems(Player player)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			List<ItemData> list = new List<ItemData>();
			Inventory inventory = ((Humanoid)player).GetInventory();
			int num = default(int);
			SlotSnapshot val = default(SlotSnapshot);
			foreach (string slot in slots)
			{
				if (API.TryGetSlotIndexByName(slot, ref num, false) && API.TryGetSlotSnapshot(inventory, num, ref val))
				{
					ItemData itemAt = inventory.GetItemAt(((SlotSnapshot)(ref val)).GridPos.x, ((SlotSnapshot)(ref val)).GridPos.y);
					if (IsFood(itemAt))
					{
						list.Add(itemAt);
					}
				}
			}
			return list;
		}

		private void Update()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!modEnabled.Value || slots.Count == 0)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).IsTeleporting())
			{
				return;
			}
			KeyboardShortcut value = quickEatKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !TextInputActive())
			{
				if (!EatOnce(localPlayer, quick: true) && messages.Value)
				{
					((Character)localPlayer).Message((MessageType)1, "Food bag: nothing to eat right now", 0, (Sprite)null, false);
				}
			}
			else if (autoEat.Value && !(Time.time < nextCheck))
			{
				nextCheck = Time.time + 1f;
				EatOnce(localPlayer, quick: false);
			}
		}

		private static bool TextInputActive()
		{
			if (!Console.IsVisible())
			{
				Chat instance = Chat.instance;
				if (instance == null || !instance.HasFocus())
				{
					return TextInput.IsVisible();
				}
			}
			return true;
		}

		private bool EatOnce(Player player, bool quick)
		{
			List<ItemData> list = BagItems(player);
			if (list.Count == 0)
			{
				return false;
			}
			List<Food> foods = player.GetFoods();
			HashSet<string> active = new HashSet<string>(foods.Select((Food f) => f.m_item.m_shared.m_name));
			if (foods.Count < 3)
			{
				ItemData val = ((IEnumerable<ItemData>)list).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => !active.Contains(i.m_shared.m_name)));
				if (val != null && Eat(player, val))
				{
					return true;
				}
			}
			Food low = null;
			foreach (Food item in foods)
			{
				if (item.CanEatAgain())
				{
					float num = item.m_time / Mathf.Max(1f, item.m_item.m_shared.m_foodBurnTime);
					if ((quick || !(num * 100f > (float)refreshAt.Value)) && (low == null || item.m_time < low.m_time))
					{
						low = item;
					}
				}
			}
			if (low == null)
			{
				return false;
			}
			ItemData val2 = ((IEnumerable<ItemData>)list).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_shared.m_name == low.m_item.m_shared.m_name));
			if (val2 != null)
			{
				return Eat(player, val2);
			}
			if (!useOtherFood.Value)
			{
				return false;
			}
			ItemData val3 = ((IEnumerable<ItemData>)list).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => !active.Contains(i.m_shared.m_name)));
			if (val3 != null)
			{
				return Eat(player, val3);
			}
			return false;
		}

		private bool Eat(Player player, ItemData item)
		{
			if (!player.CanEat(item, false))
			{
				return false;
			}
			string name = item.m_shared.m_name;
			bool num = ((Humanoid)player).ConsumeItem(((Humanoid)player).GetInventory(), item, false);
			if (num && messages.Value)
			{
				((Character)player).Message((MessageType)1, "Food bag: " + Localization.instance.Localize(name), 0, (Sprite)null, false);
			}
			return num;
		}
	}
}