Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterChests v0.5.0
BetterChests.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BetterChests.Core; using BetterChests.Deposit; using BetterChests.Duplicates; using BetterChests.Sorting; using BetterChests.UI; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("BetterChests")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Enhances chests with additional features like sorting and auto-depositing!")] [assembly: AssemblyFileVersion("0.5.0.0")] [assembly: AssemblyInformationalVersion("0.5.0+ed72a464728b5e4a3bc1597ab76b4bac85346b4b")] [assembly: AssemblyProduct("BetterChests")] [assembly: AssemblyTitle("BetterChests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.5.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; } } } namespace BetterChests { [BepInPlugin("javidahmed64592.betterchests", "BetterChests", "0.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class BetterChestsPlugin : BaseUnityPlugin { public const string PluginGuid = "javidahmed64592.betterchests"; public const string PluginName = "BetterChests"; public const string PluginVersion = "0.5.0"; internal static ManualLogSource _log; internal static Keybind _takeAllKey; internal static Keybind _placeStacksKey; internal static Keybind _depositAllKey; internal static Keybind _sortKey; internal static Keybind _keepItemKey; private Harmony _harmony; private void Awake() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; _takeAllKey = BindKey("Take All", "TakeAll", (KeyCode)114, "While a chest is open, moves everything in it into your inventory (the same as the \"Take all\" button)."); _placeStacksKey = BindKey("Place Stacks", "PlaceStacks", (KeyCode)116, "While a chest is open, moves items from your inventory onto matching stacks in the chest (the same as the \"Place stacks\" button)."); _depositAllKey = BindKey("Deposit All", "DepositAll", (KeyCode)102, "While a chest is open, moves everything in your inventory into it, except your hotbar and equipped items (the same as the \"Deposit all\" button)."); _sortKey = BindKey("Sort", "Sort", (KeyCode)103, "While a chest is open, sorts its contents (the same as the \"Sort\" button)."); _keepItemKey = BindKey("Keep Item", "KeepItem", (KeyCode)308, "Hold and right-click an item in your inventory to mark it to be kept by \"Deposit all\" and \"Place stacks\", or to unmark it. The left and right versions of Shift, Ctrl and Alt both work."); AutoDeposit.BindConfig(((BaseUnityPlugin)this).Config); ChestDuplicates.BindConfig(((BaseUnityPlugin)this).Config); Translations.Load(); _harmony = new Harmony("javidahmed64592.betterchests"); _harmony.PatchAll(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private Keybind BindKey(string configName, string buttonName, KeyCode defaultKey, string description) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0041: Expected O, but got Unknown ConfigEntry<KeyCode> val = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", configName, defaultKey, description); InputManager.Instance.AddButton("javidahmed64592.betterchests", new ButtonConfig { Name = "BetterChests_" + buttonName, Config = val }); return new Keybind(val); } internal static bool TextInputActive() { if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible()) { return TextInput.IsVisible(); } return true; } } internal sealed class Keybind(ConfigEntry<KeyCode> entry) { public KeyCode Key => entry.Value; public bool Down() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ZInput.GetKeyDown(entry.Value, true); } public bool Held() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_002d: Unknown result type (might be due to invalid IL or missing references) KeyCode value = entry.Value; if (!ZInput.GetKey(value, true)) { KeyCode? val = OtherSide(value); if (val.HasValue) { KeyCode valueOrDefault = val.GetValueOrDefault(); return ZInput.GetKey(valueOrDefault, true); } return false; } return true; } private static KeyCode? OtherSide(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown return (key - 303) switch { 1 => (KeyCode)303, 0 => (KeyCode)304, 3 => (KeyCode)305, 2 => (KeyCode)306, 5 => (KeyCode)307, 4 => (KeyCode)308, _ => null, }; } } } namespace BetterChests.UI { internal static class ChestButtons { [HarmonyPatch(typeof(InventoryGui), "Awake")] private static class InventoryGui_Awake_Patch { [CompilerGenerated] private static class <>O { public static UnityAction <0>__DepositIntoOpenContainer; public static UnityAction <1>__SortOpenContainer; } [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { //IL_0020: 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_002b: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown Button takeAllButton = __instance.m_takeAllButton; object obj = <>O.<0>__DepositIntoOpenContainer; if (obj == null) { UnityAction val = DepositAll.DepositIntoOpenContainer; <>O.<0>__DepositIntoOpenContainer = val; obj = (object)val; } RectTransform val2 = CreateButtonBelow(takeAllButton, "BetterChests_DepositAll", "$betterchests_deposit_all", (UnityAction)obj); Button stackAllButton = __instance.m_stackAllButton; object obj2 = <>O.<1>__SortOpenContainer; if (obj2 == null) { UnityAction val3 = ChestSort.SortOpenContainer; <>O.<1>__SortOpenContainer = val3; obj2 = (object)val3; } RectTransform val4 = CreateButtonBelow(stackAllButton, "BetterChests_Sort", "$betterchests_sort", (UnityAction)obj2); ChestPanelLayout.Setup(__instance, ((IEnumerable<RectTransform>)(object)new RectTransform[2] { val2, val4 }).Where((RectTransform b) => (Object)(object)b != (Object)null).ToArray()); } } [HarmonyPatch(typeof(InventoryGui), "Update")] private static class InventoryGui_Update_Patch { [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { if (InventoryGui.IsVisible() && __instance.IsContainerOpen() && !__instance.m_splitDialog.IsActive && !BetterChestsPlugin.TextInputActive()) { if (BetterChestsPlugin._takeAllKey.Down()) { __instance.OnTakeAll(); } else if (BetterChestsPlugin._depositAllKey.Down()) { DepositAll.DepositIntoOpenContainer(); } else if (BetterChestsPlugin._placeStacksKey.Down()) { __instance.OnStackAll(); } else if (BetterChestsPlugin._sortKey.Down()) { ChestSort.SortOpenContainer(); } } } } private const float ButtonGap = 4f; private static RectTransform CreateButtonBelow(Button template, string name, string text, UnityAction onClick) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_0163: Expected O, but got Unknown if ((Object)(object)template == (Object)null || (Object)(object)((Component)template).transform.parent == (Object)null) { BetterChestsPlugin._log.LogWarning((object)("Vanilla chest panel layout not as expected, not adding the " + text + " button.")); return null; } GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent, false); ((Object)val).name = name; UIGamePad[] componentsInChildren = val.GetComponentsInChildren<UIGamePad>(true); foreach (UIGamePad val2 in componentsInChildren) { if ((Object)(object)val2.m_hint != (Object)null) { Object.DestroyImmediate((Object)(object)val2.m_hint); } Object.DestroyImmediate((Object)(object)val2); } RectTransform val3 = (RectTransform)val.transform; RectTransform val4 = (RectTransform)((Component)template).transform; Vector2 anchoredPosition = val4.anchoredPosition; Rect rect = val4.rect; val3.anchoredPosition = anchoredPosition - new Vector2(0f, ((Rect)(ref rect)).height + 4f); TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { bool flag = !string.IsNullOrEmpty(componentInChildren.text) && !componentInChildren.text.Any(char.IsLower); string text2 = Localization.instance.Localize(text); componentInChildren.text = (flag ? text2.ToUpperInvariant() : text2); } Button component = val.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener(onClick); return val3; } } internal static class ChestPanelLayout { [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] private static class InventoryGui_UpdateContainer_Patch { [HarmonyPrefix] private static void Prefix(InventoryGui __instance) { if (!((Object)(object)_panel == (Object)null) && !((Object)(object)__instance.m_container != (Object)(object)_panel)) { Container currentContainer = __instance.m_currentContainer; if ((Object)(object)currentContainer != (Object)null && currentContainer.GetInventory() != null) { Resize(currentContainer, currentContainer.GetInventory()); } } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class InventoryGrid_UpdateGui_Patch { [HarmonyPostfix] private static void Postfix(InventoryGrid __instance) { if (!((Object)(object)_panel == (Object)null) && !((Object)(object)__instance != (Object)(object)_grid) && __instance.m_inventory != null) { LayOutSlots(__instance); } } } private const float Gap = 4f; private const float GridPadding = 14f; private const float ScreenBottomMargin = 70f; private static readonly Dictionary<string, int> WideLayouts = new Dictionary<string, int> { ["piece_chest_warderobe"] = 10 }; private static RectTransform _panel; private static InventoryGrid _grid; private static float _baseWidth; private static float _baseHeight; private static float _gridTop; private static Vector2 _lastSize = -Vector2.one; private static int _columns; private static (int Count, int Width, int Columns, float GridWidth) _laidOut; public static void Setup(InventoryGui gui, RectTransform[] buttons) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a7: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0198: 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_01e0: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) _panel = gui.m_container; _grid = gui.m_containerGrid; RectTransform val = ((!((Object)(object)_grid != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)_grid).transform)); if ((Object)(object)_panel == (Object)null || (Object)(object)val == (Object)null || (Object)(object)((Transform)val).parent != (Object)(object)_panel) { BetterChestsPlugin._log.LogWarning((object)"Vanilla chest panel layout not as expected, not resizing it."); _panel = null; return; } Rect rect = _panel.rect; _baseWidth = ((Rect)(ref rect)).width; rect = _panel.rect; _baseHeight = ((Rect)(ref rect)).height; _lastSize = -Vector2.one; PinToTop((RectTransform)((Component)gui.m_takeAllButton).transform); PinToTop((RectTransform)((Component)gui.m_stackAllButton).transform); PinToSide((RectTransform)((Component)gui.m_takeAllButton).transform); PinToSide((RectTransform)((Component)gui.m_stackAllButton).transform); float num = (_gridTop = 0f - val.offsetMax.y); foreach (RectTransform val2 in buttons) { PinToTop(val2); PinToSide(val2); float y = val2.anchoredPosition.y; float y2 = val2.pivot.y; rect = val2.rect; float num2 = 0f - (y - y2 * ((Rect)(ref rect)).height); _gridTop = Mathf.Max(_gridTop, num2 + 4f); } val.offsetMax = new Vector2(val.offsetMax.x, 0f - _gridTop); Scrollbar scrollbar = _grid.m_scrollbar; if ((Object)(object)scrollbar != (Object)null && (Object)(object)((Component)scrollbar).transform.parent == (Object)(object)_panel) { RectTransform val3 = (RectTransform)((Component)scrollbar).transform; PinToTop(val3); PinToSide(val3); float y3 = val3.anchoredPosition.y; float num3 = 1f - val3.pivot.y; rect = val3.rect; float num4 = 0f - (y3 + num3 * ((Rect)(ref rect)).height); float num5 = _baseHeight - num4; rect = val3.rect; float num6 = num5 - ((Rect)(ref rect)).height; rect = val3.rect; float width = ((Rect)(ref rect)).width; float x = val3.anchoredPosition.x; val3.anchorMin = new Vector2(val3.anchorMin.x, 0f); val3.anchorMax = new Vector2(val3.anchorMax.x, 1f); val3.pivot = new Vector2(val3.pivot.x, 0.5f); val3.offsetMin = new Vector2(x - width * val3.pivot.x, num6); val3.offsetMax = new Vector2(x + width * (1f - val3.pivot.x), 0f - (num4 + _gridTop - num)); } } private static void PinToTop(RectTransform rect) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Rect rect2 = ((RectTransform)((Transform)rect).parent).rect; float height = ((Rect)(ref rect2)).height; float num = (1f - rect.anchorMin.y) * height; rect.anchorMin = new Vector2(rect.anchorMin.x, 1f); rect.anchorMax = new Vector2(rect.anchorMax.x, 1f); rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - num); } private static void PinToSide(RectTransform rect) { //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_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_002e: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(rect.anchorMin.x, rect.anchorMax.x)) { Rect rect2 = ((RectTransform)((Transform)rect).parent).rect; float width = ((Rect)(ref rect2)).width; float num = rect.anchorMin.x * width + rect.anchoredPosition.x; float num2 = ((num < width / 2f) ? 0f : 1f); rect.anchorMin = new Vector2(num2, rect.anchorMin.y); rect.anchorMax = new Vector2(num2, rect.anchorMax.y); rect.anchoredPosition = new Vector2(num - num2 * width, rect.anchoredPosition.y); } } private static void Resize(Container container, Inventory inventory) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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) int num = inventory.GetWidth() * inventory.GetHeight(); _columns = ((WideLayouts.TryGetValue(Utils.GetPrefabName(((Component)container).gameObject), out var value) && value > inventory.GetWidth()) ? value : inventory.GetWidth()); int num2 = ((_columns > 0) ? ((num + _columns - 1) / _columns) : 0); float elementSpace = _grid.m_elementSpace; float num3 = _baseWidth; if (_columns > inventory.GetWidth() && elementSpace > 0f) { float num4 = _baseWidth - Mathf.Floor(_baseWidth / elementSpace) * elementSpace; num3 = Mathf.Max(_baseWidth, (float)_columns * elementSpace + num4); } float num5 = _gridTop + (float)num2 * elementSpace + 14f; float num6 = Mathf.Min(Mathf.Max(_baseHeight, num5), MaxHeight()); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(num3, num6); if (!(val == _lastSize)) { _lastSize = val; _panel.sizeDelta = val; } } private static void LayOutSlots(InventoryGrid grid) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) int width = grid.m_inventory.GetWidth(); int num = Mathf.Max(_columns, width); float elementSpace = grid.m_elementSpace; Rect rect = ((RectTransform)((Component)grid).transform).rect; float width2 = ((Rect)(ref rect)).width; (int, int, int, float) tuple = (grid.m_elements.Count, width, num, width2); (int, int, int, float) tuple2 = tuple; (int, int, int, float) laidOut = _laidOut; if (tuple2.Item1 != laidOut.Item1 || tuple2.Item2 != laidOut.Item2 || tuple2.Item3 != laidOut.Item3 || tuple2.Item4 != laidOut.Item4) { _laidOut = tuple; float num2 = width2 / 2f - (float)num * elementSpace / 2f; foreach (InventoryElement element in grid.m_elements) { int num3 = element.Position.y * width + element.Position.x; ((RectTransform)((Component)element).transform).anchoredPosition = new Vector2(num2 + (float)(num3 % num) * elementSpace, (float)(-(num3 / num)) * elementSpace); } } if (num != width) { int num4 = (grid.m_elements.Count + num - 1) / num; grid.m_gridRoot.SetSizeWithCurrentAnchors((Axis)1, (float)num4 * elementSpace); } } private static float MaxHeight() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)_panel).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { return _baseHeight; } Vector3[] array = (Vector3[])(object)new Vector3[4]; _panel.GetWorldCorners(array); float y = array[1].y; ((RectTransform)((Component)componentInParent.rootCanvas).transform).GetWorldCorners(array); float y2 = array[0].y; float y3 = ((Transform)_panel).lossyScale.y; if (!(y3 <= 0f)) { return Mathf.Max(_baseHeight, (y - y2) / y3 - 70f); } return _baseHeight; } } internal static class KeyHintUI { private enum HintVisibility { ContainerOnly, SplitDialogOnly, NotSplitting } private sealed class HintDef { public string Label; public Func<Keybind> Key; public HintVisibility Visibility; public bool Scroll; public bool WithRightClick; } private sealed class Row { public RectTransform Keyboard; public GameObject[] Items; public TMP_Text[] KeyTexts; public string[] KeySuffixes; public bool Failed; } [HarmonyPatch(typeof(KeyHints), "UpdateHints")] private static class KeyHints_UpdateHints_Patch { [HarmonyPostfix] private static void Postfix(KeyHints __instance) { RemoveDestroyed(); Update(__instance); } } private const string ItemPrefix = "BetterChests_Hint_"; private static readonly Regex WordBreak = new Regex("(?<=[a-z0-9])(?=[A-Z])"); private static readonly HintDef[] Hints = new HintDef[6] { new HintDef { Label = "$betterchests_hint_take_all", Key = () => BetterChestsPlugin._takeAllKey, Visibility = HintVisibility.ContainerOnly }, new HintDef { Label = "$betterchests_hint_place_stacks", Key = () => BetterChestsPlugin._placeStacksKey, Visibility = HintVisibility.ContainerOnly }, new HintDef { Label = "$betterchests_deposit_all", Key = () => BetterChestsPlugin._depositAllKey, Visibility = HintVisibility.ContainerOnly }, new HintDef { Label = "$betterchests_sort", Key = () => BetterChestsPlugin._sortKey, Visibility = HintVisibility.ContainerOnly }, new HintDef { Label = "$betterchests_hint_split", Scroll = true, Visibility = HintVisibility.SplitDialogOnly }, new HintDef { Label = "$betterchests_hint_keep", Key = () => BetterChestsPlugin._keepItemKey, WithRightClick = true, Visibility = HintVisibility.NotSplitting } }; private static readonly Dictionary<GameObject, Row> Rows = new Dictionary<GameObject, Row>(); private static void Update(KeyHints keyHints) { InventoryGui instance = InventoryGui.instance; if (!((Object)(object)instance == (Object)null) && InventoryGui.IsVisible()) { bool containerOpen = instance.IsContainerOpen(); bool splitting = (Object)(object)instance.m_splitDialog != (Object)null && instance.m_splitDialog.IsActive; UpdateRow(keyHints, keyHints.m_inventoryHints, containerOpen: false, splitting); UpdateRow(keyHints, keyHints.m_inventoryWithContainerHints, containerOpen, splitting); } } private static void UpdateRow(KeyHints keyHints, GameObject root, bool containerOpen, bool splitting) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || !root.activeInHierarchy) { return; } if (!Rows.TryGetValue(root, out var value)) { value = Create(keyHints, root); Rows[root] = value; } if (value.Failed || !((Component)value.Keyboard).gameObject.activeInHierarchy) { return; } bool flag = false; for (int i = 0; i < Hints.Length; i++) { HintDef hintDef = Hints[i]; bool flag2 = hintDef.Visibility switch { HintVisibility.SplitDialogOnly => splitting, HintVisibility.NotSplitting => !splitting, _ => containerOpen && !splitting, }; GameObject val = value.Items[i]; if (val.activeSelf != flag2) { val.SetActive(flag2); flag = true; } if (!flag2) { continue; } TMP_Text val2 = value.KeyTexts[i]; if (hintDef.Key != null && (Object)(object)val2 != (Object)null) { KeyCode key = hintDef.Key().Key; string text = (hintDef.WithRightClick ? ModifierName(key) : KeyName(key)) + value.KeySuffixes[i]; if (val2.text != text) { val2.text = text; flag = true; } } } if (flag) { LayoutRebuilder.ForceRebuildLayoutImmediate(value.Keyboard); } } private static Row Create(KeyHints keyHints, GameObject root) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown Row row = new Row(); Transform val = root.transform.Find("Keyboard"); Transform val2 = (((Object)(object)val != (Object)null) ? FindTemplate(val) : null); if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val).GetComponent<HorizontalLayoutGroup>() == (Object)null) { row.Failed = true; BetterChestsPlugin._log.LogWarning((object)("Vanilla inventory key hints layout not as expected, not adding key hints to " + ((Object)root).name + ".")); return row; } row.Keyboard = (RectTransform)val; row.Items = (GameObject[])(object)new GameObject[Hints.Length]; row.KeyTexts = (TMP_Text[])(object)new TMP_Text[Hints.Length]; row.KeySuffixes = new string[Hints.Length]; Transform scrollTemplate = FindScrollTemplate(keyHints); Transform val3 = FindClickTemplate(val); for (int i = 0; i < Hints.Length; i++) { HintDef hintDef = Hints[i]; row.KeySuffixes[i] = string.Empty; if (hintDef.Scroll) { row.Items[i] = CreateScrollHint(hintDef, val2, scrollTemplate, val); continue; } if (hintDef.WithRightClick && (Object)(object)val3 != (Object)null) { row.Items[i] = CreateClickHint(hintDef, val3, val); row.KeyTexts[i] = ((Component)row.Items[i].transform.Find("key_bkg")).GetComponentInChildren<TMP_Text>(true); continue; } row.Items[i] = CreateItem(hintDef, val2, val); row.KeyTexts[i] = ((Component)row.Items[i].transform.Find("key_bkg")).GetComponentInChildren<TMP_Text>(true); if (hintDef.WithRightClick) { row.KeySuffixes[i] = " + " + RightClickName(); } } return row; } private static GameObject CreateItem(HintDef hint, Transform template, Transform keyboard) { GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, keyboard, false); ((Object)val).name = "BetterChests_Hint_" + hint.Label.TrimStart(new char[1] { '$' }); val.SetActive(false); Transform obj = val.transform.Find("Text"); LayoutElement component = ((Component)obj).GetComponent<LayoutElement>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } ((Component)obj).GetComponent<TMP_Text>().text = Localization.instance.Localize(hint.Label); return val; } private static GameObject CreateScrollHint(HintDef hint, Transform keyTemplate, Transform scrollTemplate, Transform keyboard) { if ((Object)(object)scrollTemplate != (Object)null) { return CreateItem(hint, scrollTemplate, keyboard); } GameObject obj = CreateItem(hint, keyTemplate, keyboard); ((Component)obj.transform.Find("key_bkg")).GetComponentInChildren<TMP_Text>(true).text = Localization.instance.Localize("$betterchests_mouse_wheel"); return obj; } private static Transform FindScrollTemplate(KeyHints keyHints) { if ((Object)(object)keyHints.m_buildHints == (Object)null) { return null; } Transform val = keyHints.m_buildHints.transform.Find("Keyboard/rotate"); if ((Object)(object)val == (Object)null || (Object)(object)val.Find("mousew_icon") == (Object)null) { return null; } Transform val2 = val.Find("Text"); if (!((Object)(object)val2 != (Object)null) || !((Object)(object)((Component)val2).GetComponent<TMP_Text>() != (Object)null)) { return null; } return val; } private static GameObject CreateClickHint(HintDef hint, Transform clickTemplate, Transform keyboard) { GameObject val = CreateItem(hint, clickTemplate, keyboard); string[] array = new string[2] { "key_bkg", "key_bkg (2)" }; foreach (string text in array) { TMP_Text[] componentsInChildren = ((Component)val.transform.Find(text)).GetComponentsInChildren<TMP_Text>(true); for (int j = 0; j < componentsInChildren.Length; j++) { MonoBehaviour[] components = ((Component)componentsInChildren[j]).GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val2 in components) { string text2 = ((object)val2).GetType().Namespace ?? string.Empty; if (!text2.StartsWith("UnityEngine", StringComparison.Ordinal) && !text2.StartsWith("TMPro", StringComparison.Ordinal)) { Object.DestroyImmediate((Object)(object)val2); } } } } ((Component)val.transform.Find("key_bkg (2)")).GetComponentInChildren<TMP_Text>(true).text = RightClickName(); return val; } private static Transform FindClickTemplate(Transform keyboard) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Transform val = keyboard.Find("Drop"); if (IsKeyPlusKeyHint(val)) { return val; } foreach (Transform item in keyboard) { Transform val2 = item; if (IsKeyPlusKeyHint(val2)) { return val2; } } return null; } private static bool IsKeyPlusKeyHint(Transform item) { if (IsSingleKeyHint(item) && (Object)(object)item.Find("plus") != (Object)null) { Transform val = item.Find("key_bkg (2)"); if (val != null) { return (Object)(object)((Component)val).GetComponentInChildren<TMP_Text>(true) != (Object)null; } } return false; } private static string RightClickName() { if (Localization.instance == null) { return "Mouse 1"; } return Localization.instance.Localize("$button_mouse1"); } private static string ModifierName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) string text = KeyName(key); string[] array = new string[2] { "Left ", "Right " }; foreach (string text2 in array) { if (text.StartsWith(text2, StringComparison.Ordinal)) { return text.Substring(text2.Length); } } return text; } private static Transform FindTemplate(Transform keyboard) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Transform val = keyboard.Find("Use"); if (IsSingleKeyHint(val)) { return val; } foreach (Transform item in keyboard) { Transform val2 = item; if (IsSingleKeyHint(val2)) { return val2; } } return null; } private static bool IsSingleKeyHint(Transform item) { if ((Object)(object)item == (Object)null || ((Object)item).name.StartsWith("BetterChests_Hint_", StringComparison.Ordinal)) { return false; } Transform val = item.Find("Text"); Transform val2 = item.Find("key_bkg"); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<TMP_Text>() != (Object)null && (Object)(object)val2 != (Object)null) { return (Object)(object)((Component)val2).GetComponentInChildren<TMP_Text>(true) != (Object)null; } return false; } private unsafe static string KeyName(KeyCode key) { string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Alpha", StringComparison.Ordinal)) { return text.Substring(5); } if (text.StartsWith("Keypad", StringComparison.Ordinal)) { return "Num " + text.Substring(6); } text = text.Replace("Control", "Ctrl"); return WordBreak.Replace(text, " "); } private static void RemoveDestroyed() { List<GameObject> list = null; foreach (GameObject key in Rows.Keys) { if ((Object)(object)key == (Object)null) { (list ?? (list = new List<GameObject>())).Add(key); } } if (list == null) { return; } foreach (GameObject item in list) { Rows.Remove(item); } } } internal static class SlotFrame { private const float Thickness = 2f; private const float Inset = 1f; internal static void Show(InventoryElement element, string name, Color colour, bool show) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)element).transform.Find(name); if ((Object)(object)val != (Object)null) { if (((Component)val).gameObject.activeSelf != show) { ((Component)val).gameObject.SetActive(show); } } else if (show) { Create(element, name, colour); } } private static void Create(InventoryElement element, string name, Color colour) { //IL_0014: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0167: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(((Component)element).transform, false); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = new Vector2(1f, 1f); val.offsetMax = new Vector2(-1f, -1f); AddBar(val, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -2f), Vector2.zero, colour); AddBar(val, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f), colour); AddBar(val, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f), colour); AddBar(val, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-2f, 0f), Vector2.zero, colour); } private static void AddBar(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color colour) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)parent, false); val2.anchorMin = anchorMin; val2.anchorMax = anchorMax; val2.offsetMin = offsetMin; val2.offsetMax = offsetMax; Image component = val.GetComponent<Image>(); ((Graphic)component).color = colour; ((Graphic)component).raycastTarget = false; } } internal static class SplitDialogControls { [HarmonyPatch(typeof(InventoryGui), "Awake")] private static class InventoryGui_Awake_Patch { [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { if ((Object)(object)__instance.m_splitDialog != (Object)null) { CreateButtons(__instance.m_splitDialog); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateSplitDialog")] private static class InventoryGui_UpdateSplitDialog_Patch { [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { if (((Component)__instance.m_splitDialog.m_splitSlider).gameObject.activeInHierarchy) { HandleScroll(__instance.m_splitDialog); } } } private const float ButtonSize = 36f; private const float ButtonGap = 8f; private const float LabelFontSize = 26f; private static void Step(SplitDialog dialog, int delta) { Slider splitSlider = dialog.m_splitSlider; float num = Mathf.Clamp(splitSlider.value + (float)delta, splitSlider.minValue, splitSlider.maxValue); if (!Mathf.Approximately(num, splitSlider.value)) { dialog.SliderValue = num; } } private static void HandleScroll(SplitDialog dialog) { float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if (mouseScrollWheel > 0f) { Step(dialog, 1); } else if (mouseScrollWheel < 0f) { Step(dialog, -1); } } private static void CreateButtons(SplitDialog dialog) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Slider splitSlider = dialog.m_splitSlider; Button splitOkButton = dialog.m_splitOkButton; if ((Object)(object)splitSlider == (Object)null || (Object)(object)splitOkButton == (Object)null || (Object)(object)((Component)splitSlider).transform.parent == (Object)null) { BetterChestsPlugin._log.LogWarning((object)"Vanilla split dialog layout not as expected, not adding the +/- buttons."); return; } RectTransform val = (RectTransform)((Component)splitSlider).transform; val.sizeDelta = new Vector2(val.sizeDelta.x - 88f, val.sizeDelta.y); Rect rect = val.rect; float num = ((Rect)(ref rect)).width / 2f + 8f + 18f; AddButton(dialog, splitOkButton, val, "BetterChests_SplitDecrease", "-", 0f - num, -1); AddButton(dialog, splitOkButton, val, "BetterChests_SplitIncrease", "+", num, 1); } private static void AddButton(SplitDialog dialog, Button template, RectTransform sliderRect, string name, string text, float offset, int delta) { //IL_007a: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Transform)sliderRect).parent, false); ((Object)val).name = name; UIGamePad[] componentsInChildren = val.GetComponentsInChildren<UIGamePad>(true); foreach (UIGamePad val2 in componentsInChildren) { if ((Object)(object)val2.m_hint != (Object)null) { Object.DestroyImmediate((Object)(object)val2.m_hint); } Object.DestroyImmediate((Object)(object)val2); } RectTransform val3 = (RectTransform)val.transform; Vector2 anchorMin = (val3.anchorMax = sliderRect.anchorMin); val3.anchorMin = anchorMin; val3.pivot = new Vector2(0.5f, 0.5f); val3.sizeDelta = new Vector2(36f, 36f); Vector2 anchoredPosition = sliderRect.anchoredPosition; float num = 0.5f - sliderRect.pivot.x; Rect rect = sliderRect.rect; float num2 = num * ((Rect)(ref rect)).width; float num3 = 0.5f - sliderRect.pivot.y; rect = sliderRect.rect; Vector2 val4 = anchoredPosition + new Vector2(num2, num3 * ((Rect)(ref rect)).height); val3.anchoredPosition = val4 + new Vector2(offset, 0f); TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { RectTransform val5 = (RectTransform)componentInChildren.transform; val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.sizeDelta = Vector2.zero; val5.anchoredPosition = Vector2.zero; componentInChildren.enableAutoSizing = false; componentInChildren.fontSize = 26f; componentInChildren.alignment = (TextAlignmentOptions)514; componentInChildren.text = text; } Button component = val.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { Step(dialog, delta); }); } } } namespace BetterChests.Sorting { internal static class ChestSort { internal static void SortOpenContainer() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); if (!((Object)(object)val == (Object)null) && val.IsOwner() && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting()) { instance.SetupDragItem((ItemData)null, (Inventory)null, 1); Sort(val.GetInventory()); instance.m_moveItemEffects.Create(((Component)instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } } private static void Sort(Inventory inventory) { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) List<ItemData> allItems = inventory.GetAllItems(); MergeStacks(allItems); List<ItemData> list = (from e in (from i in allItems select (Item: i, Key: ItemCategories.SortKey(i)) into e orderby e.Key.Group, e.Key.Index select e).ThenBy<(ItemData, (int, int)), string>(((ItemData Item, (int Group, int Index) Key) e) => Localization.instance.Localize(e.Item.m_shared.m_name), StringComparer.CurrentCultureIgnoreCase).ThenBy<(ItemData, (int, int)), string>(((ItemData Item, (int Group, int Index) Key) e) => e.Item.m_shared.m_name, StringComparer.Ordinal).ThenByDescending<(ItemData, (int, int)), int>(((ItemData Item, (int Group, int Index) Key) e) => e.Item.m_quality) .ThenByDescending<(ItemData, (int, int)), int>(((ItemData Item, (int Group, int Index) Key) e) => e.Item.m_stack) select e.Item).ToList(); int width = inventory.GetWidth(); for (int num = 0; num < list.Count; num++) { list[num].m_gridPos = new Vector2i(num % width, num / width); } allItems.Clear(); allItems.AddRange(list); inventory.Changed(false, false); } private static void MergeStacks(List<ItemData> items) { for (int i = 0; i < items.Count; i++) { ItemData val = items[i]; int maxStackSize = val.m_shared.m_maxStackSize; for (int j = i + 1; j < items.Count; j++) { if (val.m_stack >= maxStackSize) { break; } ItemData val2 = items[j]; if (val2.m_stack > 0 && val.IsSameType(val2)) { int num = Mathf.Min(maxStackSize - val.m_stack, val2.m_stack); val.m_stack += num; val2.m_stack -= num; if (val2.m_cheated) { val.m_cheated = true; } } } } items.RemoveAll((ItemData val3) => val3.m_stack <= 0); } } internal static class ItemCategories { private enum Category { Wood, Stone, Ore, Metal, CreatureParts, Valuables, OtherMaterials, Seeds, Crops, RawMeat, Food, Meads, Ammo, Weapons, Shields, Tools, Armour, Utility, Trophies, Misc } private static readonly (Category Category, string[] Prefabs)[] Known = new(Category, string[])[9] { (Category.Wood, new string[6] { "Wood", "FineWood", "RoundLog", "ElderBark", "YggdrasilWood", "Blackwood" }), (Category.Stone, new string[11] { "Stone", "Flint", "Coal", "Obsidian", "Crystal", "Tar", "Sap", "BlackMarble", "Grausten", "SulfurStone", "ProustitePowder" }), (Category.Ore, new string[10] { "CopperOre", "CopperScrap", "TinOre", "BronzeScrap", "IronScrap", "IronOre", "SilverOre", "BlackMetalScrap", "FlametalOre", "FlametalOreNew" }), (Category.Metal, new string[16] { "Copper", "Tin", "Bronze", "BronzeNails", "Iron", "IronNails", "Chain", "Silver", "BlackMetal", "MechanicalSpring", "Eitr", "Flametal", "FlametalNew", "LinenThread", "JuteRed", "JuteBlue" }), (Category.CreatureParts, new string[39] { "LeatherScraps", "DeerHide", "Feathers", "Resin", "GreydwarfEye", "BoneFragments", "TrollHide", "HardAntler", "Guck", "Entrails", "Ooze", "Bloodbag", "Chitin", "SerpentScale", "BjornHide", "WolfPelt", "WolfFang", "WolfClaw", "WolfHairBundle", "FreezeGland", "LoxPelt", "Needle", "ScaleHide", "Carapace", "Mandible", "Softtissue", "RoyalJelly", "GiantBloodSack", "Bilebag", "AskHide", "CharredBone", "CelestialFeather", "MorgenSinew", "MorgenHeart", "BoneMawSerpentScale", "AsksvinCarrionNeck", "AsksvinCarrionPelvic", "AsksvinCarrionSkull", "Ectoplasm" }), (Category.Valuables, new string[18] { "Coins", "Amber", "AmberPearl", "Ruby", "SilverNecklace", "SurtlingCore", "AncientSeed", "Wishbone", "Thunderstone", "DragonTear", "DragonEgg", "YmirRemains", "BlackCore", "QueenBee", "GemstoneBlue", "GemstoneGreen", "GemstoneRed", "MoltenCore" }), (Category.Seeds, new string[9] { "CarrotSeeds", "TurnipSeeds", "OnionSeeds", "VineberrySeeds", "Acorn", "BeechSeeds", "BirchSeeds", "FirCone", "PineCone" }), (Category.Crops, new string[22] { "Barley", "BarleyFlour", "Flax", "Carrot", "Turnip", "Onion", "Vineberry", "Raspberry", "Blueberries", "Cloudberry", "Honey", "Mushroom", "MushroomYellow", "MushroomBlue", "MushroomJotunPuffs", "MushroomMagecap", "MushroomSmokePuff", "Thistle", "Dandelion", "Root", "Fiddleheadfern", "Pukeberries" }), (Category.RawMeat, new string[16] { "RawMeat", "NeckTail", "DeerMeat", "HareMeat", "WolfMeat", "BjornMeat", "SerpentMeat", "LoxMeat", "ChickenMeat", "ChickenEgg", "BugMeat", "AsksvinMeat", "VoltureMeat", "VoltureEgg", "BoneMawSerpentMeat", "FishRaw" }) }; private static readonly (Category Category, string[] Keywords)[] Keywords = new(Category, string[])[5] { (Category.Seeds, new string[3] { "Seed", "Cone", "Acorn" }), (Category.Ore, new string[2] { "Ore", "Scrap" }), (Category.Wood, new string[3] { "Wood", "Log", "Bark" }), (Category.RawMeat, new string[2] { "Meat", "Egg" }), (Category.CreatureParts, new string[10] { "Hide", "Pelt", "Scale", "Bone", "Fang", "Claw", "Feather", "Leather", "Sinew", "Antler" }) }; private static readonly Dictionary<string, (Category Category, int Index)> KnownByPrefab = BuildKnown(); private static Dictionary<string, (Category, int)> BuildKnown() { Dictionary<string, (Category, int)> dictionary = new Dictionary<string, (Category, int)>(); (Category, string[])[] known = Known; for (int i = 0; i < known.Length; i++) { (Category, string[]) tuple = known[i]; Category item = tuple.Item1; string[] item2 = tuple.Item2; for (int j = 0; j < item2.Length; j++) { dictionary[item2[j]] = (item, j); } } return dictionary; } public static (int Group, int Index) SortKey(ItemData item) { string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : null); if (text != null && KnownByPrefab.TryGetValue(text, out (Category, int) value)) { return (Group: (int)value.Item1, Index: value.Item2); } return (Group: (int)Classify(item, text), Index: int.MaxValue); } private static Category Classify(ItemData item, string prefab) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected I4, but got Unknown SharedData shared = item.m_shared; ItemType itemType = shared.m_itemType; switch (itemType - 1) { case 0: return (prefab != null) ? ByKeyword(prefab) : Category.OtherMaterials; case 1: return (shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f) ? Category.Food : Category.Meads; case 20: return Category.RawMeat; case 8: case 22: return Category.Ammo; case 2: case 3: case 13: case 19: case 21: return Category.Weapons; case 4: return Category.Shields; case 14: case 18: return Category.Tools; case 5: case 6: case 10: case 11: case 16: return Category.Armour; case 17: case 23: return Category.Utility; case 12: return Category.Trophies; default: return Category.Misc; } } private static Category ByKeyword(string prefab) { (Category, string[])[] keywords = Keywords; for (int i = 0; i < keywords.Length; i++) { (Category, string[]) tuple = keywords[i]; Category item = tuple.Item1; string[] item2 = tuple.Item2; foreach (string value in item2) { if (prefab.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return item; } } } return Category.OtherMaterials; } } } namespace BetterChests.Duplicates { internal static class ChestDuplicates { [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class InventoryGrid_UpdateGui_Patch { private static readonly MethodInfo Original = AccessTools.Method(typeof(InventoryGrid), "CreateItemTooltip", (Type[])null, (Type[])null); private static readonly MethodInfo Replacement = AccessTools.Method(typeof(ChestDuplicates), "CreateItemTooltip", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, Original)) { replaced++; yield return CodeInstructionExtensions.MoveBlocksFrom(CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)Replacement), instruction), instruction); } else { yield return instruction; } } if (replaced == 0) { BetterChestsPlugin._log.LogWarning((object)"InventoryGrid.UpdateGui not as expected: tooltips will not list nearby chests."); } } [HarmonyPostfix] private static void Postfix(InventoryGrid __instance) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)__instance != (Object)(object)instance.m_containerGrid) { return; } bool value = _enabled.Value; if (value) { Refresh(instance); } foreach (InventoryElement element in __instance.m_elements) { ItemData itemAt = __instance.m_inventory.GetItemAt(element.Position.x, element.Position.y); bool show = value && itemAt != null && GroupItems.Contains(itemAt.m_shared.m_name); SlotFrame.Show(element, "BetterChests_DuplicateFrame", FrameColour, show); } } } [HarmonyPatch(typeof(InventoryGui), "Update")] private static class InventoryGui_Update_Patch { [HarmonyPostfix] private static void Postfix(InventoryGui __instance) { UpdateGlow(__instance); } } private const string FrameName = "BetterChests_DuplicateFrame"; private static readonly Color FrameColour = new Color(0.45f, 0.75f, 1f, 0.95f); private const string TooltipColour = "#73BFFF"; private static readonly Color GlowColour = new Color(0.45f, 0.75f, 1f); private const float GlowMin = 0.2f; private const float GlowMax = 0.6f; private const float GlowPulseSpeed = 4f; private static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor"); private static readonly int ColorId = Shader.PropertyToID("_Color"); private const float RefreshInterval = 0.25f; private static ConfigEntry<bool> _enabled; private static Container _openChest; private static float _refreshAt; private static readonly List<Container> GroupOthers = new List<Container>(); private static readonly HashSet<string> GroupItems = new HashSet<string>(); private static readonly List<Container> Nearby = new List<Container>(); private static InventoryGrid _hoverGrid; private static ItemData _hoverItem; private static int _hoverFrame = -1; private static readonly HashSet<GameObject> Glowing = new HashSet<GameObject>(); private static readonly HashSet<GameObject> GlowTargets = new HashSet<GameObject>(); private static readonly List<Container> Holders = new List<Container>(); public static void BindConfig(ConfigFile config) { _enabled = config.Bind<bool>("Chest Panel", "Show Duplicates", true, "Frames items in an open chest that other chests in its group also hold. Hovering over an item shows how many nearby chests hold it in its tooltip, and makes those chests glow."); } private static void Refresh(InventoryGui gui) { //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) Container open = gui.m_currentContainer; if ((Object)(object)open == (Object)(object)_openChest && Time.time < _refreshAt) { return; } _openChest = open; _refreshAt = Time.time + 0.25f; GroupOthers.Clear(); GroupItems.Clear(); Nearby.Clear(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } List<Chest> list = ChestClusters.AllChests(); int num = (((Object)(object)open != (Object)null) ? list.FindIndex((Chest c) => (Object)(object)c.Container == (Object)(object)open) : (-1)); if (num >= 0) { foreach (Chest item in ChestClusters.TakeCluster(list, num)) { if (!ChestClusters.CanAccess(item.Container)) { continue; } Nearby.Add(item.Container); if (!((Object)(object)item.Container != (Object)(object)open)) { continue; } GroupOthers.Add(item.Container); foreach (ItemData allItem in item.Container.GetInventory().GetAllItems()) { GroupItems.Add(allItem.m_shared.m_name); } } } Vector3 position = ((Component)localPlayer).transform.position; float maxSqr = AutoDeposit.Radius * AutoDeposit.Radius; int anchor; while ((anchor = list.FindIndex(delegate(Chest c) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = c.Bounds; return ((Bounds)(ref bounds)).SqrDistance(position) <= maxSqr; })) >= 0) { foreach (Chest item2 in ChestClusters.TakeCluster(list, anchor)) { if (ChestClusters.CanAccess(item2.Container)) { Nearby.Add(item2.Container); } } } } private static List<Container> ChestsFor(InventoryGui gui, InventoryGrid grid) { List<Container> result = (((Object)(object)grid == (Object)(object)gui.m_playerGrid) ? Nearby : null); if (!((Object)(object)grid == (Object)(object)gui.m_containerGrid)) { return result; } return GroupOthers; } private static int FindHolders(List<Container> chests, string itemName, List<Container> holders) { holders.Clear(); int num = 0; foreach (Container chest in chests) { if ((Object)(object)chest == (Object)null) { continue; } int num2 = 0; foreach (ItemData allItem in chest.GetInventory().GetAllItems()) { if (allItem.m_shared.m_name == itemName) { num2 += allItem.m_stack; } } if (num2 > 0) { holders.Add(chest); num += num2; } } return num; } private static void CreateItemTooltip(InventoryGrid grid, ItemData item, UITooltip tooltip) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) string text = item.GetTooltip(-1); InventoryGui instance = InventoryGui.instance; if (_enabled.Value && (Object)(object)instance != (Object)null) { Refresh(instance); List<Container> list = ChestsFor(instance, grid); if (list != null) { _hoverGrid = grid; _hoverItem = item; _hoverFrame = Time.frameCount; int amount = FindHolders(list, item.m_shared.m_name, Holders); if (Holders.Count > 0) { text = text + "\n<color=#73BFFF>" + HoldersText((Object)(object)grid == (Object)(object)instance.m_containerGrid, Holders.Count, amount) + "</color>"; } } } tooltip.Set(item.m_shared.m_name, text, grid.m_tooltipAnchor, default(Vector2)); } private static string HoldersText(bool inChest, int chests, int amount) { string text = amount.ToString(CultureInfo.InvariantCulture); if (inChest) { if (chests == 1) { return Localization.instance.Localize("$betterchests_also_in_group_one", new string[1] { text }); } return Localization.instance.Localize("$betterchests_also_in_group", new string[2] { chests.ToString(CultureInfo.InvariantCulture), text }); } if (chests == 1) { return Localization.instance.Localize("$betterchests_in_nearby_one", new string[1] { text }); } return Localization.instance.Localize("$betterchests_in_nearby", new string[2] { chests.ToString(CultureInfo.InvariantCulture), text }); } private static void UpdateGlow(InventoryGui gui) { //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) GlowTargets.Clear(); List<Container> list = ((_hoverFrame == Time.frameCount && _hoverItem != null && InventoryGui.IsVisible()) ? ChestsFor(gui, _hoverGrid) : null); if (list != null && _enabled.Value) { FindHolders(list, _hoverItem.m_shared.m_name, Holders); foreach (Container holder in Holders) { GlowTargets.Add(((Component)holder.m_nview).gameObject); } } MaterialMan instance = MaterialMan.instance; if ((Object)(object)instance == (Object)null) { return; } foreach (GameObject item in Glowing) { if ((Object)(object)item != (Object)null && !GlowTargets.Contains(item)) { instance.ResetValue(item, EmissionColorId); instance.ResetValue(item, ColorId); } } Glowing.Clear(); if (GlowTargets.Count == 0) { return; } float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 4f); Color val = GlowColour * Mathf.Lerp(0.2f, 0.6f, num); foreach (GameObject glowTarget in GlowTargets) { instance.SetValue<Color>(glowTarget, EmissionColorId, val, false); instance.SetValue<Color>(glowTarget, ColorId, GlowColour, false); Glowing.Add(glowTarget); } } } } namespace BetterChests.Deposit { internal static class AutoDeposit { private sealed class Deposit { public ItemDrop Drop; public Queue<Container> Targets; public ItemData Look; public Sprite Icon; public Vector3 Position; public Quaternion Rotation; public string ItemName; public int Stored; public float AskedAt; } private sealed class PendingDeposit : MonoBehaviour { private ItemDrop _drop; private Rigidbody _body; private Vector3 _throwFrom; private Vector3 _throwDir; private float _depositAt; public static void Watch(ItemDrop drop, Player thrower) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) PendingDeposit pendingDeposit = ((Component)drop).gameObject.AddComponent<PendingDeposit>(); pendingDeposit._drop = drop; pendingDeposit._body = ((Component)drop).GetComponent<Rigidbody>(); pendingDeposit._throwFrom = ((Component)thrower).transform.position; Vector3 forward = ((Component)thrower).transform.forward; forward.y = 0f; pendingDeposit._throwDir = ((((Vector3)(ref forward)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref forward)).normalized : Vector3.forward); pendingDeposit._depositAt = Time.time + _delay.Value; } private void Update() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (time < _depositAt) { return; } if ((Object)(object)_body != (Object)null && !_body.isKinematic) { Vector3 linearVelocity = _body.linearVelocity; if (((Vector3)(ref linearVelocity)).sqrMagnitude > 0.25f && time < _depositAt + 3f) { return; } } Object.Destroy((Object)(object)this); if ((Object)(object)_drop != (Object)null) { TryDeposit(_drop, _throwFrom, _throwDir); } } } [HarmonyPatch(typeof(Container), "RPC_OpenResponse")] private static class Container_RPC_OpenResponse_Patch { [HarmonyPrefix] private static bool Prefix(Container __instance, bool granted) { return !OnOpenResponse(__instance, granted); } } [HarmonyPatch(typeof(Container), "Interact")] private static class Container_Interact_Patch { [HarmonyPrefix] private static void Prefix(Container __instance, bool hold) { if (!hold && Awaiting.ContainsKey(__instance)) { OpenedByPlayer.Add(__instance); } } } [HarmonyPatch(typeof(Humanoid), "DropItem")] private static class Humanoid_DropItem_Patch { [HarmonyPrefix] private static void Prefix(Humanoid __instance, Inventory inventory, ItemData item, int amount) { _dropper = null; if (_enabled != null && _enabled.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && item != null && amount > 0 && !item.m_shared.m_questItem) { Player localPlayer = Player.m_localPlayer; if (inventory == null) { inventory = ((Humanoid)localPlayer).GetInventory(); } if (inventory == ((Humanoid)localPlayer).GetInventory() && inventory.ContainsItem(item)) { _dropper = localPlayer; } } } [HarmonyFinalizer] private static void Finalizer() { _dropper = null; } } [HarmonyPatch(typeof(ItemDrop), "DropItem")] private static class ItemDrop_DropItem_Patch { [HarmonyPostfix] private static void Postfix(ItemDrop __result) { if ((Object)(object)_dropper != (Object)null && (Object)(object)__result != (Object)null) { PendingDeposit.Watch(__result, _dropper); _dropper = null; } } } private const float MaxSettleTime = 3f; private const float SettledSpeedSqr = 0.25f; private static ConfigEntry<bool> _enabled; private static ConfigEntry<float> _radius; private static ConfigEntry<float> _clusterGap; private static ConfigEntry<float> _throwAngle; private static ConfigEntry<float> _delay; private static Player _dropper; private const float RequestTimeout = 5f; private static readonly Dictionary<Container, List<Deposit>> Awaiting = new Dictionary<Container, List<Deposit>>(); private static readonly HashSet<Container> OpenedByPlayer = new HashSet<Container>(); internal static float Radius => _radius.Value; internal static float ClusterGap => _clusterGap.Value; public static void BindConfig(ConfigFile config) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown _enabled = config.Bind<bool>("Auto Deposit", "Enabled", true, "Dropping an item near chests stores it in them instead of leaving it on the ground."); _radius = config.Bind<float>("Auto Deposit", "Radius", 4f, new ConfigDescription("How close in metres a dropped item must land to a chest for it to be stored. (Synced with server)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f), new object[1] { Synced() })); _clusterGap = config.Bind<float>("Auto Deposit", "Cluster Gap", 1f, new ConfigDescription("Chests at most this far apart in metres (edge to edge) count as one group: an item that lands near one of them can go into any of them. 0 groups only chests that touch. (Synced with server)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), new object[1] { Synced() })); _throwAngle = config.Bind<float>("Auto Deposit", "Throw Angle", 60f, new ConfigDescription("Only chests within this many degrees of the direction you face when dropping an item are used, so items thrown away from a chest stay on the ground. 180 uses chests in every direction.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 180f), Array.Empty<object>())); _delay = config.Bind<float>("Auto Deposit", "Delay", 3f, new ConfigDescription("Seconds a dropped item lies on the ground before it is stored, so other players can pick it up. (Synced with server)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), new object[1] { Synced() })); } private static ConfigurationManagerAttributes Synced() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return new ConfigurationManagerAttributes { IsAdminOnly = true }; } private static void TryDeposit(ItemDrop drop, Vector3 throwFrom, Vector3 throwDir) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) ZNetView nview = drop.m_nview; if (!_enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)nview == (Object)null || !nview.IsValid()) { return; } ItemData itemData = drop.m_itemData; string name = itemData.m_shared.m_name; if (!nview.IsOwner()) { Log(name, "another player now owns it"); } else if (itemData.m_stack > 0) { List<Container> targets = GetTargets(((Component)drop).transform.position, throwFrom, throwDir, itemData); if (targets.Count == 0) { Log(name, "no usable chest within range in the direction it was thrown"); return; } Next(new Deposit { Drop = drop, Targets = new Queue<Container>(targets), Look = itemData.Clone(), Icon = itemData.GetIcon(), Position = ((Component)drop).transform.position, Rotation = ((Component)drop).transform.rotation, ItemName = name }); } } private static void Next(Deposit deposit) { if (!StillOurs(deposit)) { return; } while (deposit.Targets.Count > 0) { Container val = deposit.Targets.Dequeue(); if (!((Object)(object)val == (Object)null) && val.m_nview.IsValid() && CanDepositInto(val) && SpaceFor(val.GetInventory(), deposit.Drop.m_itemData, deposit.Drop.m_itemData.m_stack) > 0) { ForgetStaleRequests(); deposit.AskedAt = Time.time; if (Awaiting.TryGetValue(val, out var value)) { value.Add(deposit); return; } Awaiting[val] = new List<Deposit>(1) { deposit }; val.m_nview.InvokeRPC("RPC_RequestOpen", new object[1] { Game.instance.GetPlayerProfile().GetPlayerID() }); return; } } if (deposit.Stored <= 0) { Log(deposit.ItemName, "the chests near it are full or in use"); } } private static bool OnOpenResponse(Container container, bool granted) { if (!Awaiting.TryGetValue(container, out var value)) { return false; } Awaiting.Remove(container); foreach (Deposit item in value) { if (granted && container.m_nview.IsValid() && container.IsOwner()) { DepositInto(container, item); } Next(item); } return !OpenedByPlayer.Remove(container); } private static void ForgetStaleRequests() { List<Container> list = null; foreach (KeyValuePair<Container, List<Deposit>> item in Awaiting) { if ((Object)(object)item.Key == (Object)null || item.Value.TrueForAll((Deposit d) => Time.time - d.AskedAt > 5f)) { (list ?? (list = new List<Container>())).Add(item.Key); } } if (list == null) { return; } foreach (Container item2 in list) { List<Deposit> list2 = Awaiting[item2]; Awaiting.Remove(item2); OpenedByPlayer.Remove(item2); foreach (Deposit item3 in list2) { Next(item3); } } } private static bool StillOurs(Deposit deposit) { ItemDrop drop = deposit.Drop; if ((Object)(object)drop == (Object)null || (Object)(object)drop.m_nview == (Object)null || !drop.m_nview.IsValid() || drop.m_itemData.m_stack <= 0) { return false; } if (!drop.m_nview.IsOwner()) { Log(deposit.ItemName, "another player now owns it"); return false; } return true; } private static void DepositInto(Container container, Deposit deposit) { //IL_00f7: 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) if (!StillOurs(deposit) || !CanDepositInto(container)) { return; } ItemDrop drop = deposit.Drop; ItemData itemData = drop.m_itemData; int stack = itemData.m_stack; Inventory inventory = container.GetInventory(); int num = SpaceFor(inventory, itemData, stack); if (num <= 0) { return; } ItemData val = itemData.Clone(); val.m_stack = num; int added = (inventory.AddItem(val) ? num : (num - val.m_stack)); if (added > 0) { deposit.Stored += added; if (added >= stack) { drop.m_nview.Destroy(); } else { drop.SetStack(stack - added); } string chestName = container.GetHoverName(); string itemName = deposit.ItemName; Sprite icon = deposit.Icon; DepositEffect.Spawn(deposit.Look, deposit.Position, deposit.Rotation, container, delegate { OnArrive(container, itemName, chestName, added, icon); }); } } private static void Log(string itemName, string reason) { BetterChestsPlugin._log.LogInfo((object)("Auto deposit: left " + itemName + " on the ground: " + reason)); } private static void OnArrive(Container container, string itemName, string chestName, int amount, Sprite icon) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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)container != (Object)null && (Object)(object)InventoryGui.instance != (Object)null) { InventoryGui.instance.m_moveItemEffects.Create(((Component)container).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)1, Localization.instance.Localize("$betterchests_stored", new string[2] { Localization.instance.Localize(itemName), Localization.instance.Localize(chestName) }), amount, icon, false); } } private static List<Container> GetTargets(Vector3 position, Vector3 throwFrom, Vector3 throwDir, ItemData item) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) List<Chest> list = ChestClusters.AllChests(); float num = _radius.Value * _radius.Value; int num2 = -1; float num3 = float.MaxValue; for (int i = 0; i < list.Count; i++) { Bounds bounds = list[i].Bounds; float num4 = ((Bounds)(ref bounds)).SqrDistance(position); if (num4 <= num && num4 < num3) { bounds = list[i].Bounds; if (IsThrownTowards(((Bounds)(ref bounds)).center, throwFrom, throwDir)) { num2 = i; num3 = num4; } } } if (num2 < 0) { return new List<Container>(); } List<Chest> list2 = ChestClusters.TakeCluster(list, num2); list2.RemoveAll((Chest c) => !CanDepositInto(c.Container)); list2.Sort(delegate(Chest a, Chest b) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) Bounds bounds2 = a.Bounds; float num5 = ((Bounds)(ref bounds2)).SqrDistance(position); bounds2 = b.Bounds; return num5.CompareTo(((Bounds)(ref bounds2)).SqrDistance(position)); }); List<Container> list3 = new List<Container>(); List<Container> list4 = new List<Container>(); foreach (Chest item2 in list2) { (item2.Container.GetInventory().ContainsItemByName(item.m_shared.m_name) ? list3 : list4).Add(item2.Container); } list3.AddRange(list4); return list3; } private static bool IsThrownTowards(Vector3 target, Vector3 throwFrom, Vector3 throwDir) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) Vector3 val = target - throwFrom; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { return Vector3.Angle(throwDir, val) <= _throwAngle.Value; } return true; } private static bool CanDepositInto(Container container) { if (((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)container) || (!container.IsInUse() && container.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 1)) { return ChestClusters.CanAccess(container); } return false; } private static int SpaceFor(Inventory inventory, ItemData item, int amount) { if (amount <= 0) { return 0; } if (inventory.HaveEmptySlot()) { return amount; } if (item.m_shared.m_maxStackSize <= 1) { return 0; } int num = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem.m_shared.m_name == item.m_shared.m_name && allItem.m_quality == item.m_quality && allItem.m_worldLevel == item.m_worldLevel) { num += Mathf.Max(0, allItem.m_shared.m_maxStackSize - allItem.m_stack); } } return Mathf.Min(num, amount); } } internal static class DepositAll { internal static void DepositIntoOpenContainer() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null); Player localPlayer = Player.m_localPlayer; if ((Object)(object)val == (Object)null || !val.IsOwner() || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting()) { return; } instance.SetupDragItem((ItemData)null, (Inventory)null, 1); Inventory inventory = ((Humanoid)localPlayer).GetInventory(); Inventory inventory2 = val.GetInventory(); bool flag = false; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (!KeepItems.AlwaysKept(item) && !KeepItems.IsMarked(item) && !item.m_shared.m_questItem) { int stack = item.m_stack; if (inventory2.AddItem(item)) { inventory.RemoveItem(item); flag = true; } else if (item.m_stack != stack) { flag = true; } } } if (flag) { inventory.Changed(false, false); inventory2.Changed(false, false); instance.m_moveItemEffects.Create(((Component)instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } } } internal sealed class DepositEffect : MonoBehaviour { private const float FlyTime = 0.4f; private const float ArcHeight = 0.5f; private const float EndScale = 0.15f; private const float SpinSpeed = 720f; private const float FallbackTargetHeight = 0.5f; private Container _container; private Vector3 _target; private Action _onArrive; private Vector3 _flyFrom; private Vector3 _startScale; private float _time; public static void Spawn(ItemData item, Vector3 position, Quaternion rotation, Container container, Action onArrive) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_002b: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) GameObject dropPrefab = item.m_dropPrefab; if ((Object)(object)dropPrefab == (Object)null) { onArrive(); return; } GameObject val = new GameObject("BetterChests_DepositHolder"); val.SetActive(false); GameObject val2 = Object.Instantiate<GameObject>(dropPrefab, position, rotation, val.transform); ((Object)val2).name = "BetterChests_Deposit"; MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true); for (int num = componentsInChildren.Length - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)componentsInChildren[num]); } Collider[] componentsInChildren2 = val2.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].enabled = false; } Rigidbody component = val2.GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.isKinematic = true; } val2.transform.localScale = item.GetScale(); val2.transform.SetParent((Transform)null, true); Object.Destroy((Object)(object)val); DepositEffect depositEffect = val2.AddComponent<DepositEffect>(); depositEffect._container = container; depositEffect._target = TargetPoint(container); depositEffect._onArrive = onArrive; depositEffect._flyFrom = position; depositEffect._startScale = val2.transform.localScale; } private static Vector3 TargetPoint(Container container) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_002a: Unknown result type (might be due to invalid IL or missing references) Collider componentInChildren = ((Component)container).GetComponentInChildren<Collider>(); if (!((Object)(object)componentInChildren != (Object)null)) { return ((Component)container).transform.position + Vector3.up * 0.5f; } Bounds bounds = componentInChildren.bounds; return ((Bounds)(ref bounds)).center; } private void Update() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) _time += Time.deltaTime; if ((Object)(object)_container != (Object)null) { _target = TargetPoint(_container); } float num = Mathf.Clamp01(_time / 0.4f); float num2 = num * num; ((Component)this).transform.position = Vector3.Lerp(_flyFrom, _target, num2) + Vector3.up * (Mathf.Sin(num * (float)Math.PI) * 0.5f); ((Component)this).transform.localScale = _startScale * Mathf.Lerp(1f, 0.15f, num2); ((Component)this).transform.Rotate(Vector3.up, 720f * Time.deltaTime, (Space)0); if (num >= 1f) { Arrive(); } } private void Arrive() { Object.Destroy((Object)(object)((Component)this).gameObject); _onArrive(); } } internal static class KeepItems { [HarmonyPatch(typeof(InventoryGrid), "OnRightDown")] private static class InventoryGrid_OnRightDown_Patch { [HarmonyPrefix] private static bool Prefix(InventoryGrid __instance, UIInputHandler element) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_002f: Unknown result type (might be due to invalid IL or missing references) if (!BetterChestsPlugin._keepItemKey.Held() || !IsPlayerGrid(__instance)) { return true; } Vector2i buttonPos = __instance.GetButtonPos(((Component)element).gameObject); ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt == null) { return false; } if (AlwaysKept(itemAt)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$betterchests_always_kept", 0, (Sprite)null, false); return false; } Toggle(itemAt); return false; } } [HarmonyPatch(typeof(Inventory), "StackAll")] private static class Inventory_StackAll_Patch { private static readonly MethodInfo GetAllItems = AccessTools.Method(typeof(Inventory), "GetAllItems", (Type[])null, (Type[])null); private static readonly MethodInfo Replacement = AccessTools.Method(typeof(KeepItems), "ItemsToStack", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { bool replaced = false; foreach (CodeInstruction instruction in instructions) { if (!replaced && CodeInstructionExtensions.Calls(instruction, GetAllItems)) { replaced = true; yield return CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)Replacement), instruction); } else { yield return instruction; } } if (!replaced) { BetterChestsPlugin._log.LogWarning((object)"Inventory.StackAll not as expected: Place stacks will not skip kept items."); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class InventoryGrid_UpdateGui_Patch { [HarmonyPostfix] private static void Postfix(InventoryGrid __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) if (!IsPlayerGrid(__instance)) { return; } foreach (InventoryElement element in __instance.m_elements) { ItemData itemAt = __instance.m_inventory.GetItemAt(element.Position.x, element.Position.y); bool show = itemAt != null && IsMarked(itemAt) && !AlwaysKept(itemAt); SlotFrame.Show(element, "BetterChests_KeepFrame", FrameColour, show); } } } private const string DataKey = "BetterChests_Keep"; internal const int HotbarRow = 0; private const string FrameName = "BetterChests_KeepFrame"; private static readonly Color FrameColour = new Color(1f, 0.76f, 0.3f, 0.95f); internal static bool AlwaysKept(ItemData item) { if (item.m_gridPos.y != 0) { return item.m_equipped; } return true; } internal static bool IsMarked(ItemData item) { if (item.m_customData != null) { return item.m_customData.ContainsKey("BetterChests_Keep"); } return false; } private static void Toggle(ItemData item) { if (!item.m_customData.Remove("BetterChests_Keep")) { item.m_customData["BetterChests_Keep"] = "1"; } } private static bool IsPlayerGrid(InventoryGrid grid) { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && (Object)(object)grid == (Object)(object)instance.m_playerGrid && (Object)(object)Player.m_localPlayer != (Object)null) { return grid.m_inventory == ((Humanoid)Player.m_localPlayer).GetInventory(); } return false; } private static List<ItemData> ItemsToStack(Inventory fromInventory) { List<ItemData> allItems = fromInventory.GetAllItems(); if (!((Object)(object)Player.m_localPlayer == (Object)null) && fromInventory ==