using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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("CDEV.ChestItemsHoverDisplay")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0")]
[assembly: AssemblyProduct("CDEV.ChestItemsHoverDisplay")]
[assembly: AssemblyTitle("CDEV.ChestItemsHoverDisplay")]
[assembly: AssemblyVersion("0.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 CDEV.ChestItemsHoverDisplay
{
internal class HoverInventoryPanel : MonoBehaviour
{
private struct SlotView
{
public GameObject Go;
public Image Icon;
public Text Count;
}
private RectTransform _root;
private RectTransform _gridRoot;
private GridLayoutGroup _grid;
private Text _title;
private List<SlotView> _slots;
private Font _font;
private Container _current;
private Inventory _trackedInventory;
private int _gridW;
private int _gridH;
private bool _dirty = true;
private bool _built;
private static readonly string[] s_stackCache = BuildStackCache(128);
private static string[] BuildStackCache(int n)
{
string[] array = new string[n + 1];
for (int i = 0; i <= n; i++)
{
array[i] = "x" + i;
}
return array;
}
private void Awake()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
_root = (RectTransform)((Component)this).transform;
_slots = new List<SlotView>(32);
Build();
}
private void OnDestroy()
{
UnsubscribeCurrent();
}
private void Build()
{
//IL_002b: 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_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Expected O, but got Unknown
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: 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
if (!_built)
{
_built = true;
_font = FindValheimFont();
_root.anchorMin = new Vector2(0.5f, 0.5f);
_root.anchorMax = new Vector2(0.5f, 0.5f);
_root.pivot = new Vector2(0.5f, 1f);
_root.anchoredPosition = new Vector2(0f, (float)Plugin.CfgVerticalOffset.Value);
Image obj = ((Component)this).gameObject.AddComponent<Image>();
((Graphic)obj).color = new Color(0f, 0f, 0f, 0.66f);
((Graphic)obj).raycastTarget = false;
ContentSizeFitter obj2 = ((Component)this).gameObject.AddComponent<ContentSizeFitter>();
obj2.horizontalFit = (FitMode)2;
obj2.verticalFit = (FitMode)2;
VerticalLayoutGroup obj3 = ((Component)this).gameObject.AddComponent<VerticalLayoutGroup>();
((LayoutGroup)obj3).padding = new RectOffset(6, 6, 5, 6);
((HorizontalOrVerticalLayoutGroup)obj3).spacing = 5f;
((LayoutGroup)obj3).childAlignment = (TextAnchor)0;
((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = false;
((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = false;
((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
GameObject val = new GameObject("Title", new Type[1] { typeof(RectTransform) });
val.transform.SetParent(((Component)this).transform, false);
_title = val.AddComponent<Text>();
_title.font = _font;
_title.fontSize = 16;
_title.fontStyle = (FontStyle)1;
((Graphic)_title).color = Color.white;
_title.alignment = (TextAnchor)3;
_title.horizontalOverflow = (HorizontalWrapMode)1;
_title.verticalOverflow = (VerticalWrapMode)1;
((Graphic)_title).raycastTarget = false;
Outline obj4 = val.AddComponent<Outline>();
((Shadow)obj4).effectColor = Color.black;
((Shadow)obj4).effectDistance = new Vector2(1f, -1f);
LayoutElement obj5 = val.AddComponent<LayoutElement>();
obj5.minHeight = _title.fontSize;
obj5.preferredHeight = _title.fontSize;
GameObject val2 = new GameObject("Grid", new Type[1] { typeof(RectTransform) });
val2.transform.SetParent(((Component)this).transform, false);
_gridRoot = (RectTransform)val2.transform;
ContentSizeFitter obj6 = val2.AddComponent<ContentSizeFitter>();
obj6.horizontalFit = (FitMode)2;
obj6.verticalFit = (FitMode)2;
_grid = val2.AddComponent<GridLayoutGroup>();
ApplyCellSettings();
((Component)this).gameObject.SetActive(false);
}
}
private void ApplyCellSettings()
{
//IL_0015: 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_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
int value = Plugin.CfgCellSize.Value;
_grid.cellSize = new Vector2((float)value, (float)value);
_grid.spacing = new Vector2(2f, 2f);
((LayoutGroup)_grid).padding = new RectOffset(0, 0, 0, 0);
_grid.startCorner = (Corner)0;
_grid.startAxis = (Axis)0;
((LayoutGroup)_grid).childAlignment = (TextAnchor)0;
_grid.constraint = (Constraint)1;
if (_gridW > 0)
{
_grid.constraintCount = _gridW;
}
}
private static Font FindValheimFont()
{
Font[] array = Resources.FindObjectsOfTypeAll<Font>();
Font val = null;
foreach (Font val2 in array)
{
if (!((Object)(object)val2 == (Object)null))
{
if (((Object)val2).name.IndexOf("AveriaSerifLibre-Bold", StringComparison.OrdinalIgnoreCase) >= 0)
{
return val2;
}
if ((Object)(object)val == (Object)null)
{
val = val2;
}
}
}
return val;
}
private SlotView CreateSlot(int idx)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("Slot" + idx, new Type[1] { typeof(RectTransform) });
val.transform.SetParent((Transform)(object)_gridRoot, false);
Image obj = val.AddComponent<Image>();
((Graphic)obj).color = new Color(1f, 1f, 1f, 0.08f);
((Graphic)obj).raycastTarget = false;
GameObject val2 = new GameObject("Icon", new Type[1] { typeof(RectTransform) });
val2.transform.SetParent(val.transform, false);
RectTransform val3 = (RectTransform)val2.transform;
val3.anchorMin = Vector2.zero;
val3.anchorMax = Vector2.one;
val3.offsetMin = Vector2.zero;
val3.offsetMax = Vector2.zero;
Image val4 = val2.AddComponent<Image>();
((Graphic)val4).raycastTarget = false;
val4.preserveAspect = true;
GameObject val5 = new GameObject("Count", new Type[1] { typeof(RectTransform) });
val5.transform.SetParent(val.transform, false);
RectTransform val6 = (RectTransform)val5.transform;
val6.anchorMin = Vector2.zero;
val6.anchorMax = Vector2.one;
val6.offsetMin = new Vector2(0f, 0f);
val6.offsetMax = new Vector2(-2f, 0f);
Text val7 = val5.AddComponent<Text>();
((Graphic)val7).raycastTarget = false;
val7.alignment = (TextAnchor)8;
val7.font = _font;
val7.fontSize = 14;
((Graphic)val7).color = Color.white;
val7.resizeTextForBestFit = false;
val7.horizontalOverflow = (HorizontalWrapMode)1;
val7.verticalOverflow = (VerticalWrapMode)1;
Outline obj2 = val5.AddComponent<Outline>();
((Shadow)obj2).effectColor = Color.black;
((Shadow)obj2).effectDistance = new Vector2(1f, -1f);
SlotView result = default(SlotView);
result.Go = val;
result.Icon = val4;
result.Count = val7;
return result;
}
public void Hide()
{
if (_built)
{
if (((Component)this).gameObject.activeSelf)
{
((Component)this).gameObject.SetActive(false);
}
UnsubscribeCurrent();
}
}
private void UnsubscribeCurrent()
{
if (_trackedInventory != null)
{
Inventory trackedInventory = _trackedInventory;
trackedInventory.m_onChanged = (Action)Delegate.Remove(trackedInventory.m_onChanged, new Action(OnInventoryChanged));
_trackedInventory = null;
}
_current = null;
_dirty = true;
}
private void OnInventoryChanged()
{
_dirty = true;
}
public void Show(Container c)
{
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
if (!_built)
{
Build();
}
if ((Object)(object)c != (Object)(object)_current)
{
UnsubscribeCurrent();
_current = c;
_trackedInventory = c.GetInventory();
if (_trackedInventory != null)
{
Inventory trackedInventory = _trackedInventory;
trackedInventory.m_onChanged = (Action)Delegate.Combine(trackedInventory.m_onChanged, new Action(OnInventoryChanged));
}
if ((Object)(object)_title != (Object)null)
{
string text = c.m_name ?? string.Empty;
_title.text = ((Localization.instance != null) ? Localization.instance.Localize(text) : text);
}
_dirty = true;
}
if (_trackedInventory == null)
{
Hide();
return;
}
if ((int)_grid.cellSize.x != Plugin.CfgCellSize.Value)
{
ApplyCellSettings();
_dirty = true;
}
int num = Mathf.Max(1, _trackedInventory.GetWidth());
int num2 = Mathf.Max(1, _trackedInventory.GetHeight());
if (num != _gridW || num2 != _gridH)
{
_gridW = num;
_gridH = num2;
_grid.constraintCount = num;
_dirty = true;
}
int value = Plugin.CfgVerticalOffset.Value;
if ((int)_root.anchoredPosition.y != value)
{
_root.anchoredPosition = new Vector2(0f, (float)value);
}
bool flag = false;
if (_dirty)
{
Rebuild();
flag = true;
}
if (Plugin.CfgHideWhenEmpty.Value && _trackedInventory.NrOfItems() == 0)
{
if (((Component)this).gameObject.activeSelf)
{
((Component)this).gameObject.SetActive(false);
}
return;
}
if (!((Component)this).gameObject.activeSelf)
{
((Component)this).gameObject.SetActive(true);
}
if (flag)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(_root);
}
}
private void Rebuild()
{
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
_dirty = false;
int num = _gridW * _gridH;
while (_slots.Count < num)
{
_slots.Add(CreateSlot(_slots.Count));
}
for (int i = 0; i < _slots.Count; i++)
{
SlotView slotView = _slots[i];
if (i < num)
{
int num2 = i % _gridW;
int num3 = i / _gridW;
ItemData itemAt = _trackedInventory.GetItemAt(num2, num3);
Sprite val = PickIcon(itemAt);
slotView.Icon.sprite = val;
((Behaviour)slotView.Icon).enabled = (Object)(object)val != (Object)null;
((Graphic)slotView.Icon).color = Color.white;
int num4 = itemAt?.m_stack ?? 0;
if (num4 > 1 || (itemAt != null && itemAt.m_shared != null && itemAt.m_shared.m_maxStackSize > 1))
{
slotView.Count.text = ((num4 >= 0 && num4 < s_stackCache.Length) ? s_stackCache[num4] : ("x" + num4));
((Behaviour)slotView.Count).enabled = true;
}
else
{
((Behaviour)slotView.Count).enabled = false;
}
if (!slotView.Go.activeSelf)
{
slotView.Go.SetActive(true);
}
}
else if (slotView.Go.activeSelf)
{
slotView.Go.SetActive(false);
}
}
}
private static Sprite PickIcon(ItemData it)
{
if (it == null || it.m_shared == null)
{
return null;
}
Sprite[] icons = it.m_shared.m_icons;
if (icons == null || icons.Length == 0)
{
return null;
}
int num = it.m_variant;
if (num < 0)
{
num = 0;
}
if (num >= icons.Length)
{
num = icons.Length - 1;
}
return icons[num];
}
}
[BepInPlugin("cdev.valheim.chestitemshoverdisplay", "CDEV.ChestItemsHoverDisplay", "0.2.0")]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "cdev.valheim.chestitemshoverdisplay";
public const string PluginName = "CDEV.ChestItemsHoverDisplay";
public const string PluginVersion = "0.2.0";
internal static ManualLogSource Log;
internal static Plugin Instance;
internal static HoverInventoryPanel Panel;
internal static ConfigEntry<bool> CfgEnabled;
internal static ConfigEntry<int> CfgCellSize;
internal static ConfigEntry<bool> CfgHideWhenEmpty;
internal static ConfigEntry<bool> CfgRespectPrivateChests;
internal static ConfigEntry<KeyCode> CfgHoldKey;
internal static ConfigEntry<int> CfgVerticalOffset;
private Harmony _harmony;
private void Awake()
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Expected O, but got Unknown
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Expected O, but got Unknown
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Master toggle for the hover inventory panel.");
CfgCellSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "CellSize", 40, new ConfigDescription("Pixel size of each grid cell.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(24, 96), Array.Empty<object>()));
CfgHideWhenEmpty = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HideWhenEmpty", true, "Hide the panel when the hovered container is empty.");
CfgRespectPrivateChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "RespectPrivateChests", true, "Hide preview for private chests the local player cannot access, or chests inside wards the local player is not permitted in.");
CfgHoldKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Display", "HoldKeyToShow", (KeyCode)0, "Optional key that must be held to show the panel. None = always show while hovering.");
CfgVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "VerticalOffset", -80, new ConfigDescription("Vertical pixel offset from screen center (negative = below crosshair).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-400, 400), Array.Empty<object>()));
_harmony = new Harmony("cdev.valheim.chestitemshoverdisplay");
_harmony.PatchAll(typeof(Plugin).Assembly);
Log.LogInfo((object)"CDEV.ChestItemsHoverDisplay 0.2.0 loaded.");
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
if ((Object)(object)Panel != (Object)null)
{
Object.Destroy((Object)(object)((Component)Panel).gameObject);
}
Panel = null;
}
internal static HoverInventoryPanel GetOrCreatePanel()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Panel != (Object)null)
{
return Panel;
}
if ((Object)(object)Hud.instance == (Object)null)
{
return null;
}
GameObject val = new GameObject("CDEV_HoverInventoryPanel", new Type[1] { typeof(RectTransform) });
val.transform.SetParent(((Component)Hud.instance).transform, false);
Panel = val.AddComponent<HoverInventoryPanel>();
return Panel;
}
}
[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
internal static class HudUpdateCrosshairPatch
{
private static readonly Func<Container, long, bool> s_checkAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null), (object)null, true);
private static void Postfix(Player player)
{
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
HoverInventoryPanel panel = Plugin.Panel;
if (!Plugin.CfgEnabled.Value)
{
panel?.Hide();
return;
}
if ((Object)(object)player == (Object)null)
{
panel?.Hide();
return;
}
GameObject hoverObject = ((Humanoid)player).GetHoverObject();
if ((Object)(object)hoverObject == (Object)null)
{
panel?.Hide();
return;
}
Container componentInParent = hoverObject.GetComponentInParent<Container>();
if ((Object)(object)componentInParent == (Object)null)
{
panel?.Hide();
return;
}
ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
if ((Object)(object)component == (Object)null || !component.IsValid())
{
panel?.Hide();
return;
}
if (Plugin.CfgRespectPrivateChests.Value)
{
if (s_checkAccess != null && !s_checkAccess(componentInParent, player.GetPlayerID()))
{
panel?.Hide();
return;
}
if (!PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, false, false))
{
panel?.Hide();
return;
}
}
if ((int)Plugin.CfgHoldKey.Value != 0 && !Input.GetKey(Plugin.CfgHoldKey.Value))
{
panel?.Hide();
}
else
{
Plugin.GetOrCreatePanel()?.Show(componentInParent);
}
}
}
}