Decompiled source of CoolCount v0.1.0

plugins/CoolCount/CoolCount.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CoolCount.Core;
using CoolCount.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CoolCount")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("OmniCC for Valheim: cooldown countdowns drawn on mead and food slots in the inventory and hotbar.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+a503f0d946dd28c746a9cfe6dccf096435664e4d")]
[assembly: AssemblyProduct("CoolCount")]
[assembly: AssemblyTitle("CoolCount")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public int? Order;

	public bool? IsAdvanced;

	public bool? Browsable;

	public bool? ReadOnly;
}
namespace CoolCount
{
	[BepInPlugin("com.jumpingmushroom.coolcount", "CoolCount", "0.1.0")]
	[BepInProcess("valheim.exe")]
	[BepInProcess("valheim.x86_64")]
	public sealed class CoolCountPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.jumpingmushroom.coolcount";

		public const string PluginName = "CoolCount";

		public const string PluginVersion = "0.1.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig.Bind(((BaseUnityPlugin)this).Config);
			ConsoleCommands.Register();
			_harmony = new Harmony("com.jumpingmushroom.coolcount");
			_harmony.PatchAll(typeof(CoolCountPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"CoolCount 0.1.0 loaded.");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	public enum TimeFormat
	{
		Game,
		Compact
	}
	public static class PluginConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> ShowInInventory;

		public static ConfigEntry<bool> ShowInContainers;

		public static ConfigEntry<bool> ShowInHotbar;

		public static ConfigEntry<bool> ShowMeads;

		public static ConfigEntry<bool> ShowFood;

		public static ConfigEntry<bool> FoodSlotsFull;

		public static ConfigEntry<float> MinDuration;

		public static ConfigEntry<int> FontSize;

		public static ConfigEntry<TimeFormat> Format;

		public static ConfigEntry<float> TenthsBelow;

		public static ConfigEntry<float> SoonBelow;

		public static ConfigEntry<Color> SoonColor;

		public static ConfigEntry<Color> SecondsColor;

		public static ConfigEntry<Color> MinutesColor;

		public static ConfigEntry<Color> HoursColor;

		public static ConfigEntry<bool> DimIcon;

		public static ConfigEntry<Color> DimColor;

		public static ConfigEntry<bool> Sweep;

		public static ConfigEntry<Color> SweepColor;

		public static ConfigEntry<bool> Verbose;

		private static ConfigurationManagerAttributes Attr(int order, bool advanced = false)
		{
			return new ConfigurationManagerAttributes
			{
				Order = order,
				IsAdvanced = advanced
			};
		}

		public static void Bind(ConfigFile cfg)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Expected O, but got Unknown
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Expected O, but got Unknown
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Expected O, but got Unknown
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Expected O, but got Unknown
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Expected O, but got Unknown
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0493: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Expected O, but got Unknown
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("General", "Enabled", true, new ConfigDescription("Master switch. Off hides every overlay without unloading the mod.", (AcceptableValueBase)null, new object[1] { Attr(100) }));
			ShowInInventory = cfg.Bind<bool>("General", "ShowInInventory", true, new ConfigDescription("Draw cooldowns on your own inventory grid.", (AcceptableValueBase)null, new object[1] { Attr(95) }));
			ShowInContainers = cfg.Bind<bool>("General", "ShowInContainers", true, new ConfigDescription("Also draw them on the chest, cart and ship grids, measured against your own active effects: a mead in a chest shows when you could drink it.", (AcceptableValueBase)null, new object[1] { Attr(90) }));
			ShowInHotbar = cfg.Bind<bool>("General", "ShowInHotbar", true, new ConfigDescription("Draw cooldowns on the hotbar under the health bar.", (AcceptableValueBase)null, new object[1] { Attr(85) }));
			ShowMeads = cfg.Bind<bool>("General", "Meads", true, new ConfigDescription("Meads and anything else that applies a status effect when consumed. The game blocks these while that effect, or any effect in the same exclusion group, is still running; the countdown is that effect's remaining time.", (AcceptableValueBase)null, new object[1] { Attr(80) }));
			ShowFood = cfg.Bind<bool>("General", "Food", true, new ConfigDescription("Food you are already digesting. It can be eaten again once its timer drops below half; the countdown is the time until then.", (AcceptableValueBase)null, new object[1] { Attr(75) }));
			FoodSlotsFull = cfg.Bind<bool>("General", "FoodSlotsFull", true, new ConfigDescription("When all three food slots are taken and none is past half, every other food in the bag counts down to the moment one frees up.", (AcceptableValueBase)null, new object[1] { Attr(70) }));
			MinDuration = cfg.Bind<float>("General", "MinDuration", 0f, new ConfigDescription("Ignore cooldowns whose full length is shorter than this many seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), new object[1] { Attr(65, advanced: true) }));
			FontSize = cfg.Bind<int>("Text", "FontSize", 22, new ConfigDescription("Size of the countdown.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 48), new object[1] { Attr(60) }));
			Format = cfg.Bind<TimeFormat>("Text", "Format", TimeFormat.Game, new ConfigDescription("Game matches the status-effect icons (1:59). Compact is OmniCC's (2m).", (AcceptableValueBase)null, new object[1] { Attr(58) }));
			TenthsBelow = cfg.Bind<float>("Text", "TenthsBelow", 0f, new ConfigDescription("Show tenths of a second under this many seconds (4.3). 0 turns it off.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1] { Attr(56) }));
			SoonBelow = cfg.Bind<float>("Text", "SoonBelow", 5f, new ConfigDescription("Use the Soon colour under this many seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), new object[1] { Attr(54) }));
			SoonColor = cfg.Bind<Color>("Text", "SoonColor", new Color(1f, 0.35f, 0.35f, 1f), new ConfigDescription("Colour of the last few seconds.", (AcceptableValueBase)null, new object[1] { Attr(52) }));
			SecondsColor = cfg.Bind<Color>("Text", "SecondsColor", new Color(1f, 1f, 0.45f, 1f), new ConfigDescription("Colour under one minute.", (AcceptableValueBase)null, new object[1] { Attr(50) }));
			MinutesColor = cfg.Bind<Color>("Text", "MinutesColor", Color.white, new ConfigDescription("Colour under one hour.", (AcceptableValueBase)null, new object[1] { Attr(48) }));
			HoursColor = cfg.Bind<Color>("Text", "HoursColor", new Color(0.75f, 0.75f, 0.75f, 1f), new ConfigDescription("Colour from one hour up.", (AcceptableValueBase)null, new object[1] { Attr(46) }));
			DimIcon = cfg.Bind<bool>("Icon", "Dim", false, new ConfigDescription("Darken the whole item icon on top of the sweep. Off by default: the sweep already darkens the part of the cooldown still to run, and dimming as well leaves the icon too dark to recognise. An item blocked by an effect with no end is always dimmed, since there is no sweep or countdown to show.", (AcceptableValueBase)null, new object[1] { Attr(40) }));
			DimColor = cfg.Bind<Color>("Icon", "DimColor", new Color(0.45f, 0.45f, 0.45f, 1f), new ConfigDescription("Tint applied to a dimmed icon.", (AcceptableValueBase)null, new object[1] { Attr(38) }));
			Sweep = cfg.Bind<bool>("Icon", "Sweep", true, new ConfigDescription("Draw the radial sweep that shrinks clockwise as the cooldown runs out.", (AcceptableValueBase)null, new object[1] { Attr(36) }));
			SweepColor = cfg.Bind<Color>("Icon", "SweepColor", new Color(0f, 0f, 0f, 0.5f), new ConfigDescription("Colour and opacity of the sweep.", (AcceptableValueBase)null, new object[1] { Attr(34) }));
			Verbose = cfg.Bind<bool>("Logging", "Verbose", false, new ConfigDescription("Log overlay creation and every patch error to the BepInEx log.", (AcceptableValueBase)null, new object[1] { Attr(5, advanced: true) }));
		}
	}
}
namespace CoolCount.UI
{
	public sealed class SlotOverlay : MonoBehaviour
	{
		private const string ObjectName = "CoolCount";

		private static Sprite _white;

		private Image _icon;

		private Image _sweep;

		private TMP_Text _text;

		private bool _dimmed;

		public static SlotOverlay Find(Image icon)
		{
			if ((Object)(object)icon == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)icon).transform;
			if (transform.childCount == 0)
			{
				return null;
			}
			Transform val = transform.Find("CoolCount");
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<SlotOverlay>();
		}

		public static SlotOverlay Ensure(Image icon, TMP_Text textTemplate)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			SlotOverlay slotOverlay = Find(icon);
			if ((Object)(object)slotOverlay != (Object)null)
			{
				return slotOverlay;
			}
			GameObject val = new GameObject("CoolCount", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(((Component)icon).transform, false);
			Stretch(val2);
			slotOverlay = val.AddComponent<SlotOverlay>();
			slotOverlay._icon = icon;
			slotOverlay.Build(textTemplate);
			if (PluginConfig.Verbose.Value)
			{
				CoolCountPlugin.Log.LogDebug((object)("overlay created under " + ((Object)((Component)icon).transform.parent).name + "/" + ((Object)icon).name));
			}
			return slotOverlay;
		}

		public static void HideIfAny(Image icon)
		{
			SlotOverlay slotOverlay = Find(icon);
			if ((Object)(object)slotOverlay != (Object)null)
			{
				slotOverlay.Hide();
			}
		}

		private void Build(TMP_Text template)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			GameObject val = new GameObject("sweep", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(((Component)this).transform, false);
			Stretch(val2);
			_sweep = val.AddComponent<Image>();
			_sweep.sprite = WhiteSprite();
			_sweep.type = (Type)3;
			_sweep.fillMethod = (FillMethod)4;
			_sweep.fillOrigin = 2;
			_sweep.fillClockwise = false;
			((Graphic)_sweep).raycastTarget = false;
			((Graphic)_sweep).color = PluginConfig.SweepColor.Value;
			if ((Object)(object)template != (Object)null)
			{
				GameObject val3 = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)this).transform);
				((Object)val3).name = "time";
				val3.SetActive(true);
				Stretch((RectTransform)val3.transform);
				_text = val3.GetComponent<TMP_Text>();
				if ((Object)(object)_text != (Object)null)
				{
					((Behaviour)_text).enabled = true;
					_text.text = "";
					_text.alignment = (TextAlignmentOptions)514;
					_text.enableAutoSizing = false;
					_text.textWrappingMode = (TextWrappingModes)0;
					_text.overflowMode = (TextOverflowModes)0;
					((Graphic)_text).raycastTarget = false;
					_text.fontSize = PluginConfig.FontSize.Value;
				}
			}
			((Component)this).gameObject.SetActive(false);
		}

		public void Show(Cooldown cd)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(true);
			}
			bool flag = float.IsInfinity(cd.Remaining);
			if ((Object)(object)_sweep != (Object)null)
			{
				bool flag2 = PluginConfig.Sweep.Value && !flag && cd.Total > 0f;
				((Behaviour)_sweep).enabled = flag2;
				if (flag2)
				{
					_sweep.fillAmount = Mathf.Clamp01(cd.Remaining / cd.Total);
					((Graphic)_sweep).color = PluginConfig.SweepColor.Value;
				}
			}
			if ((Object)(object)_text != (Object)null)
			{
				if (flag)
				{
					_text.text = "";
				}
				else
				{
					_text.text = TimeText.Format(cd.Remaining);
					((Graphic)_text).color = TimeText.ColorFor(cd.Remaining);
					_text.fontSize = PluginConfig.FontSize.Value;
				}
			}
			if ((PluginConfig.DimIcon.Value || flag) && (Object)(object)_icon != (Object)null)
			{
				((Graphic)_icon).color = PluginConfig.DimColor.Value;
				_dimmed = true;
			}
			else if (_dimmed)
			{
				Undim();
			}
		}

		public void Hide()
		{
			if (((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(false);
			}
			if (_dimmed)
			{
				Undim();
			}
		}

		private void Undim()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			_dimmed = false;
			if ((Object)(object)_icon != (Object)null)
			{
				((Graphic)_icon).color = Color.white;
			}
		}

		private static void Stretch(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.pivot = new Vector2(0.5f, 0.5f);
			rt.offsetMin = Vector2.zero;
			rt.offsetMax = Vector2.zero;
			((Transform)rt).localScale = Vector3.one;
		}

		private static Sprite WhiteSprite()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_white != (Object)null)
			{
				return _white;
			}
			Texture2D val = new Texture2D(4, 4, (TextureFormat)4, false);
			Color32[] array = (Color32[])(object)new Color32[16];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			}
			val.SetPixels32(array);
			val.Apply();
			((Object)val).hideFlags = (HideFlags)61;
			_white = Sprite.Create(val, new Rect(0f, 0f, 4f, 4f), new Vector2(0.5f, 0.5f), 4f);
			((Object)_white).hideFlags = (HideFlags)61;
			return _white;
		}
	}
}
namespace CoolCount.Patches
{
	internal static class Guard
	{
		private static int _errors;

		public static void Fail(string where, Exception ex)
		{
			if (_errors++ < 5 || PluginConfig.Verbose.Value)
			{
				CoolCountPlugin.Log.LogWarning((object)(where + " threw: " + ex));
			}
		}
	}
	internal static class SlotPainter
	{
		public static void Paint(Image icon, TMP_Text template, Player who, ItemData item)
		{
			if (!((Object)(object)icon == (Object)null))
			{
				if (Cooldowns.TryGet(who, item, out var cd))
				{
					SlotOverlay.Ensure(icon, template).Show(cd);
				}
				else
				{
					SlotOverlay.HideIfAny(icon);
				}
			}
		}

		public static void PaintGrid(InventoryGrid grid, Player player)
		{
			List<InventoryElement> elements = grid.m_elements;
			if (elements == null)
			{
				return;
			}
			bool num = PluginConfig.Enabled.Value && PluginConfig.ShowInInventory.Value && ((Object)(object)player != (Object)null || PluginConfig.ShowInContainers.Value);
			Player val = (((Object)(object)player != (Object)null) ? player : Player.m_localPlayer);
			Inventory inventory = grid.m_inventory;
			if (!num || (Object)(object)val == (Object)null || inventory == null)
			{
				for (int i = 0; i < elements.Count; i++)
				{
					SlotOverlay.HideIfAny(elements[i].m_icon);
				}
				return;
			}
			for (int j = 0; j < elements.Count; j++)
			{
				if (!elements[j].m_used)
				{
					SlotOverlay.HideIfAny(elements[j].m_icon);
				}
			}
			int width = inventory.GetWidth();
			List<ItemData> allItems = inventory.GetAllItems();
			for (int k = 0; k < allItems.Count; k++)
			{
				ItemData val2 = allItems[k];
				InventoryElement element = grid.GetElement(val2.m_gridPos.x, val2.m_gridPos.y, width);
				if ((Object)(object)element != (Object)null)
				{
					Paint(element.m_icon, element.m_amount, val, val2);
				}
			}
		}

		public static void PaintHotbar(HotkeyBar bar, Player player)
		{
			List<ElementData> elements = bar.m_elements;
			if (elements == null || elements.Count == 0)
			{
				return;
			}
			if (!PluginConfig.Enabled.Value || !PluginConfig.ShowInHotbar.Value || !((Object)(object)player != (Object)null))
			{
				for (int i = 0; i < elements.Count; i++)
				{
					SlotOverlay.HideIfAny(elements[i].m_icon);
				}
				return;
			}
			for (int j = 0; j < elements.Count; j++)
			{
				if (!elements[j].m_used)
				{
					SlotOverlay.HideIfAny(elements[j].m_icon);
				}
			}
			List<ItemData> items = bar.m_items;
			for (int k = 0; k < items.Count; k++)
			{
				ItemData val = items[k];
				int x = val.m_gridPos.x;
				if (x >= 0 && x < elements.Count)
				{
					ElementData val2 = elements[x];
					Paint(val2.m_icon, val2.m_amount, player, val);
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	internal static class InventoryGrid_UpdateGui_Patch
	{
		private static void Postfix(InventoryGrid __instance, Player player)
		{
			try
			{
				SlotPainter.PaintGrid(__instance, player);
			}
			catch (Exception ex)
			{
				Guard.Fail("InventoryGrid.UpdateGui postfix", ex);
			}
		}
	}
	[HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")]
	internal static class HotkeyBar_UpdateIcons_Patch
	{
		private static void Postfix(HotkeyBar __instance, Player player)
		{
			try
			{
				SlotPainter.PaintHotbar(__instance, player);
			}
			catch (Exception ex)
			{
				Guard.Fail("HotkeyBar.UpdateIcons postfix", ex);
			}
		}
	}
}
namespace CoolCount.Core
{
	public static class ConsoleCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			internal void <Register>b__0_0(ConsoleEventArgs args)
			{
				string text = ((args.Length > 1) ? args[1].ToLowerInvariant() : "");
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					Say(args.Context, "CoolCount: no local player.");
				}
				else if (!(text == "effects"))
				{
					if (text == "foods")
					{
						Foods(args.Context, localPlayer);
					}
					else
					{
						Items(args.Context, localPlayer);
					}
				}
				else
				{
					Effects(args.Context, localPlayer);
				}
			}
		}

		public static void Register()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					string text = ((args.Length > 1) ? args[1].ToLowerInvariant() : "");
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer == (Object)null)
					{
						Say(args.Context, "CoolCount: no local player.");
					}
					else if (!(text == "effects"))
					{
						if (text == "foods")
						{
							Foods(args.Context, localPlayer);
						}
						else
						{
							Items(args.Context, localPlayer);
						}
					}
					else
					{
						Effects(args.Context, localPlayer);
					}
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("coolcount", "CoolCount: list cooldowns (effects | foods)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static void Say(Terminal ctx, string line)
		{
			ctx.AddString(line);
			CoolCountPlugin.Log.LogInfo((object)line);
		}

		private static void Items(Terminal ctx, Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (Cooldowns.TryGet(player, allItem, out var cd))
				{
					num++;
					Say(ctx, string.Format("CoolCount: [{0},{1}] {2}: {3} left of {4} ({5})", allItem.m_gridPos.x, allItem.m_gridPos.y, Localization.instance.Localize(allItem.m_shared.m_name), float.IsInfinity(cd.Remaining) ? "forever" : (cd.Remaining.ToString("0.0") + "s"), cd.Total.ToString("0"), Localization.instance.Localize(cd.Source ?? "")));
				}
			}
			Say(ctx, "CoolCount: " + num + " item(s) on cooldown.");
		}

		private static void Effects(Terminal ctx, Player player)
		{
			List<StatusEffect> statusEffects = ((Character)player).GetSEMan().GetStatusEffects();
			foreach (StatusEffect item in statusEffects)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Say(ctx, string.Format("CoolCount: effect {0} category=\"{1}\" ttl={2} left={3} hidden={4}", item.m_name, item.m_category, item.m_ttl.ToString("0"), (item.m_ttl > 0f) ? item.GetRemaningTime().ToString("0.0") : "inf", item.m_hidden));
				}
			}
			Say(ctx, "CoolCount: " + statusEffects.Count + " status effect(s).");
		}

		private static void Foods(Terminal ctx, Player player)
		{
			List<Food> foods = player.m_foods;
			foreach (Food item in foods)
			{
				if (item != null && item.m_item != null)
				{
					float foodBurnTime = item.m_item.m_shared.m_foodBurnTime;
					Say(ctx, string.Format("CoolCount: food {0} time={1}/{2} again in {3}", Localization.instance.Localize(item.m_item.m_shared.m_name), item.m_time.ToString("0"), foodBurnTime.ToString("0"), item.CanEatAgain() ? "now" : ((item.m_time - foodBurnTime * 0.5f).ToString("0.0") + "s")));
				}
			}
			Say(ctx, "CoolCount: " + foods.Count + " food(s) active.");
		}
	}
	public struct Cooldown
	{
		public float Remaining;

		public float Total;

		public string Source;
	}
	public static class Cooldowns
	{
		public static bool TryGet(Player player, ItemData item, out Cooldown cd)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			cd = default(Cooldown);
			if ((Object)(object)player == (Object)null || item == null || item.m_shared == null)
			{
				return false;
			}
			SharedData shared = item.m_shared;
			if ((int)shared.m_itemType != 2)
			{
				return false;
			}
			if ((Object)(object)shared.m_consumeStatusEffect != (Object)null && PluginConfig.ShowMeads.Value && FromStatusEffect(player, shared.m_consumeStatusEffect, out cd))
			{
				return Accept(ref cd);
			}
			if (IsFood(shared) && PluginConfig.ShowFood.Value && FromFood(player, item, out cd))
			{
				return Accept(ref cd);
			}
			return false;
		}

		public static bool IsFood(SharedData shared)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)shared.m_itemType == 2)
			{
				if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f))
				{
					return shared.m_foodEitr > 0f;
				}
				return true;
			}
			return false;
		}

		private static bool Accept(ref Cooldown cd)
		{
			if (cd.Remaining <= 0f)
			{
				return false;
			}
			float value = PluginConfig.MinDuration.Value;
			if (!(value <= 0f) && !(cd.Total <= 0f))
			{
				return cd.Total >= value;
			}
			return true;
		}

		private static bool FromStatusEffect(Player player, StatusEffect gate, out Cooldown cd)
		{
			cd = default(Cooldown);
			SEMan sEMan = ((Character)player).GetSEMan();
			if (sEMan == null)
			{
				return false;
			}
			int num = gate.NameHash();
			string category = gate.m_category;
			bool flag = !string.IsNullOrEmpty(category);
			List<StatusEffect> statusEffects = sEMan.GetStatusEffects();
			bool flag2 = false;
			for (int i = 0; i < statusEffects.Count; i++)
			{
				StatusEffect val = statusEffects[i];
				if (!((Object)(object)val == (Object)null) && (val.NameHash() == num || (flag && val.m_category == category)))
				{
					float num2 = ((val.m_ttl > 0f) ? val.GetRemaningTime() : float.PositiveInfinity);
					if (!flag2 || num2 > cd.Remaining)
					{
						cd.Remaining = num2;
						cd.Total = val.m_ttl;
						cd.Source = val.m_name;
						flag2 = true;
					}
				}
			}
			return flag2;
		}

		private static bool FromFood(Player player, ItemData item, out Cooldown cd)
		{
			cd = default(Cooldown);
			List<Food> foods = player.m_foods;
			if (foods == null || foods.Count == 0)
			{
				return false;
			}
			string name = item.m_shared.m_name;
			Food val = null;
			Food val2 = null;
			float num = float.MaxValue;
			bool flag = false;
			for (int i = 0; i < foods.Count; i++)
			{
				Food val3 = foods[i];
				if (val3 != null && val3.m_item != null && val3.m_item.m_shared != null)
				{
					if (val3.m_item.m_shared.m_name == name)
					{
						val = val3;
					}
					float num2 = val3.m_time - val3.m_item.m_shared.m_foodBurnTime * 0.5f;
					if (num2 <= 0f)
					{
						flag = true;
					}
					else if (num2 < num)
					{
						num = num2;
						val2 = val3;
					}
				}
			}
			if (val != null)
			{
				float num3 = val.m_item.m_shared.m_foodBurnTime * 0.5f;
				cd.Remaining = val.m_time - num3;
				cd.Total = num3;
				cd.Source = val.m_item.m_shared.m_name;
				return cd.Remaining > 0f;
			}
			if (PluginConfig.FoodSlotsFull.Value && foods.Count >= 3 && !flag && val2 != null)
			{
				cd.Remaining = num;
				cd.Total = val2.m_item.m_shared.m_foodBurnTime * 0.5f;
				cd.Source = "$msg_isfull";
				return true;
			}
			return false;
		}
	}
	public static class TimeText
	{
		public static string Format(float seconds)
		{
			if (seconds <= 0f)
			{
				return "";
			}
			float value = PluginConfig.TenthsBelow.Value;
			if (value > 0f && seconds < value)
			{
				return seconds.ToString("0.0");
			}
			if (PluginConfig.Format.Value == TimeFormat.Game)
			{
				return StatusEffect.GetTimeString(seconds, false, false);
			}
			int num = Mathf.CeilToInt(seconds);
			if (num >= 3600)
			{
				return Mathf.RoundToInt(seconds / 3600f) + "h";
			}
			if (num >= 60)
			{
				return Mathf.RoundToInt(seconds / 60f) + "m";
			}
			return num.ToString();
		}

		public static Color ColorFor(float seconds)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (seconds < PluginConfig.SoonBelow.Value)
			{
				return PluginConfig.SoonColor.Value;
			}
			if (seconds < 60f)
			{
				return PluginConfig.SecondsColor.Value;
			}
			if (seconds < 3600f)
			{
				return PluginConfig.MinutesColor.Value;
			}
			return PluginConfig.HoursColor.Value;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}