Decompiled source of Taschenhaendler v1.1.2
CBra.Taschenhaendler.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CBra.Taschenhaendler")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.2.0")] [assembly: AssemblyInformationalVersion("1.1.2")] [assembly: AssemblyProduct("CBra.Taschenhaendler")] [assembly: AssemblyTitle("CBra.Taschenhaendler")] [assembly: AssemblyVersion("1.1.2.0")] namespace CBra.Erenshor.Taschenhaendler; internal sealed class ExtraInventorySlotMarker : MonoBehaviour { } internal sealed class InventoryScrollView : MonoBehaviour { private Inventory _inventory; private RectTransform _viewport; private RectTransform _content; private ScrollRect _scrollRect; private GameObject _scrollbarObject; private readonly List<float> _columnOffsets = new List<float>(); private readonly HashSet<ItemIcon> _displayedSlots = new HashSet<ItemIcon>(); private float _rowSpacing = 70.5f; private float _slotVisualHeight = 52f; private const float ToolbarHeight = 86f; private RectMask2D _mask; internal static InventoryScrollView Create(Inventory inventory, IReadOnlyList<ItemIcon> usableSlots) { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown if ((Object)(object)inventory == (Object)null || usableSlots == null || usableSlots.Count == 0) { return null; } List<RectTransform> list = (from root in usableSlots.Select(InventoryExpansionController.GetSlotRoot) where (Object)(object)root != (Object)null select root).Distinct().ToList(); if (list.Count == 0) { return null; } RectTransform commonParent = default(RectTransform); ref RectTransform reference = ref commonParent; Transform parent = ((Transform)list[0]).parent; reference = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)commonParent == (Object)null || list.Any((RectTransform root) => (Object)(object)((Transform)root).parent != (Object)(object)commonParent)) { TaschenhaendlerPlugin.ModLog.LogWarning((object)"Inventar-Scrollbereich konnte nicht gebaut werden: Slot-Container haben unterschiedliche Eltern."); return null; } InventoryScrollView componentInChildren = ((Component)commonParent).GetComponentInChildren<InventoryScrollView>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren._inventory = inventory; componentInChildren.LayoutSlots(); return componentInChildren; } GameObject val = new GameObject("Taschenhaendler_ScrollViewport", new Type[5] { typeof(RectTransform), typeof(Image), typeof(RectMask2D), typeof(ScrollRect), typeof(InventoryScrollView) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)commonParent, false); ((Transform)component).SetSiblingIndex(Math.Max(0, list.Min((RectTransform root) => ((Transform)root).GetSiblingIndex()))); InventoryScrollView component2 = val.GetComponent<InventoryScrollView>(); component2._inventory = inventory; component2._viewport = component; component2._scrollRect = val.GetComponent<ScrollRect>(); component2._mask = val.GetComponent<RectMask2D>(); component2.ConfigureGeometry(list); component2.BuildContent(commonParent); component2.BuildScrollbar(commonParent); component2.ConfigureScrollRect(); component2.BuildTools(commonParent); component2.LayoutSlots(); return component2; } internal void LayoutSlots(bool resetScroll = false) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: 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_0264: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_inventory == (Object)null || (Object)(object)_content == (Object)null || (Object)(object)_viewport == (Object)null) { return; } List<ItemIcon> list = _inventory.StoredSlots.Where(InventoryExpansionController.IsScrollableInventorySlot).ToList(); List<ItemIcon> displayedSlots = InventoryToolsState.GetDisplayedSlots(list, _inventory.Empty); _displayedSlots.Clear(); foreach (ItemIcon item in displayedSlots) { _displayedSlots.Add(item); } int num = Math.Max(1, _columnOffsets.Count); int num2 = Math.Max(1, Mathf.CeilToInt((float)displayedSlots.Count / (float)num)); Rect rect = _viewport.rect; float num3 = Math.Max(((Rect)(ref rect)).height, _slotVisualHeight + (float)Math.Max(0, num2 - 1) * _rowSpacing + 4f); _content.SetSizeWithCurrentAnchors((Axis)1, num3); foreach (ItemIcon item2 in list) { RectTransform slotRoot = InventoryExpansionController.GetSlotRoot(item2); if (!((Object)(object)slotRoot == (Object)null)) { ((Transform)slotRoot).SetParent((Transform)(object)_content, false); slotRoot.anchorMin = new Vector2(0.5f, 1f); slotRoot.anchorMax = new Vector2(0.5f, 1f); slotRoot.pivot = new Vector2(0.5f, 0.5f); } } for (int i = 0; i < displayedSlots.Count; i++) { RectTransform slotRoot2 = InventoryExpansionController.GetSlotRoot(displayedSlots[i]); if (!((Object)(object)slotRoot2 == (Object)null)) { int index = i % num; int num4 = i / num; slotRoot2.anchoredPosition = new Vector2(_columnOffsets[index], 0f - (_slotVisualHeight * 0.5f + 2f + (float)num4 * _rowSpacing)); } } rect = _viewport.rect; bool flag = num3 > ((Rect)(ref rect)).height + 1f; if ((Object)(object)_scrollbarObject != (Object)null) { _scrollbarObject.SetActive(flag); } if (resetScroll) { ScrollRect scrollRect = _scrollRect; if (scrollRect != null) { scrollRect.StopMovement(); } _content.anchoredPosition = Vector2.zero; } else if (!flag) { _content.anchoredPosition = Vector2.zero; } Canvas.ForceUpdateCanvases(); UpdateVisibility(); } private void ConfigureGeometry(IReadOnlyList<RectTransform> roots) { //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) List<float> list = (from root in roots select root.anchoredPosition.x into value orderby value select value).ToList(); List<float> list2 = new List<float>(); foreach (float x in list) { if (list2.All((float existing) => Mathf.Abs(existing - x) > 5f)) { list2.Add(x); } } if (list2.Count == 0) { list2.AddRange(new float[3] { -67f, 0f, 67f }); } float num = (list2.First() + list2.Last()) * 0.5f; _columnOffsets.Clear(); foreach (float item in list2) { _columnOffsets.Add(item - num); } List<float> list3 = (from value in roots.Select((RectTransform root) => root.anchoredPosition.y).Distinct() orderby value descending select value).ToList(); if (list3.Count > 1) { List<float> list4 = new List<float>(); for (int num2 = 1; num2 < list3.Count; num2++) { float num3 = list3[num2 - 1] - list3[num2]; if (num3 > 10f) { list4.Add(num3); } } if (list4.Count > 0) { _rowSpacing = list4.OrderBy((float value) => value).ElementAt(list4.Count / 2); } } RectTransform val = roots[0]; Rect rect = val.rect; _slotVisualHeight = Math.Max(40f, ((Rect)(ref rect)).height * Math.Abs(((Transform)val).localScale.y)); float num4 = roots.Min((RectTransform root) => root.anchoredPosition.x); float num5 = roots.Max((RectTransform root) => root.anchoredPosition.x); float num6 = roots.Min((RectTransform root) => root.anchoredPosition.y); float num7 = roots.Max((RectTransform root) => root.anchoredPosition.y); rect = val.rect; float num8 = ((Rect)(ref rect)).width * Math.Abs(((Transform)val).localScale.x); float num9 = num5 - num4 + num8 + 12f; float num10 = num7 - num6 + _slotVisualHeight + 8f; float num11 = Math.Max(_slotVisualHeight * 3f, num10 - 86f); float num12 = (num6 + num7) * 0.5f; _viewport.anchorMin = val.anchorMin; _viewport.anchorMax = val.anchorMax; _viewport.pivot = new Vector2(0.5f, 0.5f); _viewport.anchoredPosition = new Vector2((num4 + num5) * 0.5f, num12 - 43f); _viewport.sizeDelta = new Vector2(num9, num11); Image component = ((Component)_viewport).GetComponent<Image>(); ((Graphic)component).color = new Color(0f, 0f, 0f, 0.001f); ((Graphic)component).raycastTarget = true; } private void BuildContent(RectTransform commonParent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_004c: 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_0080: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Content", new Type[1] { typeof(RectTransform) }); _content = val.GetComponent<RectTransform>(); ((Transform)_content).SetParent((Transform)(object)_viewport, false); _content.anchorMin = new Vector2(0f, 1f); _content.anchorMax = new Vector2(1f, 1f); _content.pivot = new Vector2(0.5f, 1f); _content.anchoredPosition = Vector2.zero; RectTransform content = _content; Rect rect = _viewport.rect; content.sizeDelta = new Vector2(0f, ((Rect)(ref rect)).height); } private void BuildScrollbar(RectTransform commonParent) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0058: 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_007e: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0147: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) _scrollbarObject = new GameObject("Taschenhaendler_Scrollbar", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Scrollbar) }); RectTransform component = _scrollbarObject.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)commonParent, false); component.anchorMin = _viewport.anchorMin; component.anchorMax = _viewport.anchorMax; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = _viewport.anchoredPosition + new Vector2(_viewport.sizeDelta.x * 0.5f - 5f, 0f); component.sizeDelta = new Vector2(9f, _viewport.sizeDelta.y); ((Graphic)_scrollbarObject.GetComponent<Image>()).color = new Color(0.02f, 0.02f, 0.02f, 0.7f); GameObject val = new GameObject("Handle", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component2 = val.GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = new Vector2(1f, 1f); component2.offsetMax = new Vector2(-1f, -1f); Image component3 = val.GetComponent<Image>(); ((Graphic)component3).color = new Color(0.72f, 0.55f, 0.22f, 0.95f); Scrollbar component4 = _scrollbarObject.GetComponent<Scrollbar>(); component4.handleRect = component2; ((Selectable)component4).targetGraphic = (Graphic)(object)component3; component4.direction = (Direction)2; component4.numberOfSteps = 0; _scrollRect.verticalScrollbar = component4; } private void BuildTools(RectTransform commonParent) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) Vector2 anchoredPosition = default(Vector2); ((Vector2)(ref anchoredPosition))..ctor(_viewport.anchoredPosition.x, _viewport.anchoredPosition.y + _viewport.sizeDelta.y * 0.5f + 43f); InventoryToolsPanel.Create(_inventory, this, commonParent, _viewport.anchorMin, _viewport.anchorMax, anchoredPosition, new Vector2(_viewport.sizeDelta.x, 82f)); } private void ConfigureScrollRect() { _scrollRect.content = _content; _scrollRect.viewport = _viewport; _scrollRect.horizontal = false; _scrollRect.vertical = true; _scrollRect.movementType = (MovementType)2; _scrollRect.inertia = true; _scrollRect.decelerationRate = 0.135f; _scrollRect.scrollSensitivity = TaschenhaendlerPlugin.Instance.ScrollSensitivity.Value; _scrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)0; ((UnityEvent<Vector2>)(object)_scrollRect.onValueChanged).AddListener((UnityAction<Vector2>)delegate { UpdateVisibility(); }); } private void UpdateVisibility() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) if ((Object)(object)_inventory == (Object)null || (Object)(object)_viewport == (Object)null) { return; } Rect worldRect = GetWorldRect(_viewport); foreach (ItemIcon item in _inventory.StoredSlots.Where(InventoryExpansionController.IsScrollableInventorySlot)) { RectTransform slotRoot = InventoryExpansionController.GetSlotRoot(item); bool num = _displayedSlots.Contains(item); bool flag = num && (Object)(object)slotRoot != (Object)null && ((Rect)(ref worldRect)).Overlaps(GetWorldRect(slotRoot), true); bool flag2 = num && (flag || item.dragging); BoxCollider2D component = ((Component)item).GetComponent<BoxCollider2D>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = flag2; } Image component2 = ((Component)item).GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).raycastTarget = flag2; } if ((Object)(object)slotRoot != (Object)null) { CanvasGroup obj = ((Component)slotRoot).GetComponent<CanvasGroup>() ?? ((Component)slotRoot).gameObject.AddComponent<CanvasGroup>(); obj.alpha = (flag2 ? 1f : 0f); obj.blocksRaycasts = flag2; } } } private void LateUpdate() { if (!((Object)(object)_inventory == (Object)null) && !((Object)(object)_mask == (Object)null)) { bool flag = _inventory.StoredSlots.Where(InventoryExpansionController.IsScrollableInventorySlot).Any((ItemIcon slot) => slot.dragging); if (((Behaviour)_mask).enabled == flag) { ((Behaviour)_mask).enabled = !flag; UpdateVisibility(); } } } private static Rect GetWorldRect(RectTransform rectTransform) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4]; rectTransform.GetWorldCorners(array); return Rect.MinMaxRect(array[0].x, array[0].y, array[2].x, array[2].y); } } internal sealed class SaveIsolationState { internal bool CanProceed = true; internal bool Prepared; internal List<ItemIcon> Extras; internal List<HiddenExpansionItemState> HiddenExpansionItems; internal Dictionary<Hotkeys, int> HotkeyIndices = new Dictionary<Hotkeys, int>(); } internal sealed class HiddenExpansionItemState { internal ItemIcon Slot; internal Item Item; internal int Quantity; } internal static class InventoryExpansionController { private sealed class IOExceptionLikeException : Exception { } private static Inventory _inventory; private static ItemIcon _trashSlot; private static readonly List<ItemIcon> ExtraSlots = new List<ItemIcon>(); private static InventoryScrollView _scrollView; private static CharacterProgress _loadedProgress; private static readonly HashSet<int> UnresolvedOverflowIndices = new HashSet<int>(); private static bool _sidecarAlreadyCommittedForSave; private static bool _nativeSaveProbeActive; private static bool _nativeSaveSucceeded; private static bool _restoringPendingExpansionItems; private static bool _pendingRecoveryNoticeShown; internal static RectTransform GetSlotRoot(ItemIcon slot) { object obj; if (slot == null) { obj = null; } else { Transform transform = ((Component)slot).transform; obj = ((transform != null) ? transform.parent : null); } return (RectTransform)((obj is RectTransform) ? obj : null); } internal static bool IsReservedUnresolvedSlot(ItemIcon slot) { int num = ExtraSlots.IndexOf(slot); if (num >= 0) { return UnresolvedOverflowIndices.Contains(num); } return false; } internal static bool IsScrollableInventorySlot(ItemIcon slot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)slot != (Object)null && (int)slot.ThisSlotType == 0 && !slot.TrashSlot && !slot.VendorSlot && !slot.LootSlot && !slot.BankSlot && !slot.DisplayOnly && !slot.NotInInventory) { return !slot.CosmeticOnly; } return false; } internal static void RefreshLayout() { _scrollView?.LayoutSlots(); } internal static void RestorePendingExpansionItems() { if (_restoringPendingExpansionItems || (Object)(object)_inventory == (Object)null || _loadedProgress == null || (Object)(object)MerchantController.ExpansionItem == (Object)null) { return; } long num = Math.Max(0L, _loadedProgress.PurchasedCount - _loadedProgress.AppliedCount); long num2 = 0L; foreach (ItemIcon storedSlot in _inventory.StoredSlots) { if ((Object)(object)storedSlot != (Object)null && TaschenhaendlerPlugin.IsExpansion(storedSlot.MyItem)) { num2 = checked(num2 + Math.Max(1L, storedSlot.Quantity)); } } long num3 = Math.Max(0L, num - num2); if (num3 == 0L) { _pendingRecoveryNoticeShown = false; return; } _restoringPendingExpansionItems = true; long num4 = 0L; try { foreach (ItemIcon item in _inventory.StoredSlots.Where((ItemIcon entry) => (Object)(object)entry != (Object)null && TaschenhaendlerPlugin.IsExpansion(entry.MyItem))) { if (num3 <= 0) { break; } long val = int.MaxValue - Math.Max(0, item.Quantity); int num5 = (int)Math.Min(num3, val); if (num5 > 0) { item.Quantity += num5; num3 -= num5; num4 += num5; item.UpdateSlotImage(); } } foreach (ItemIcon item2 in _inventory.StoredSlots.Where((ItemIcon entry) => IsUsableEmptyInventorySlot(entry)).ToList()) { if (num3 <= 0) { break; } int num6 = (int)((num3 > int.MaxValue) ? int.MaxValue : num3); item2.MyItem = MerchantController.ExpansionItem; item2.Quantity = num6; num3 -= num6; num4 += num6; item2.UpdateSlotImage(); } if (num4 > 0) { _inventory.UpdatePlayerInventory(); TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Format("{0} bereits bezahlte Inventarerweiterung(en) wurden aus dem geschützten Kaufstand wiederhergestellt.", "{0} previously purchased inventory expansion(s) were restored from protected progress.", num4)); } if (num3 > 0 && !_pendingRecoveryNoticeShown) { _pendingRecoveryNoticeShown = true; TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Format("Für {0} bezahlte Erweiterung(en) ist noch kein freier Inventarplatz vorhanden. Räume einen Platz frei; die Wiederherstellung wird beim nächsten Laden erneut versucht.", "There is no free inventory slot yet for {0} purchased expansion(s). Free one slot; restoration will be retried on the next load.", num3)); } } finally { _restoringPendingExpansionItems = false; } } internal static bool SaveNativeAfterSidecarCommit() { _sidecarAlreadyCommittedForSave = true; _nativeSaveProbeActive = true; _nativeSaveSucceeded = false; try { if ((Object)(object)GameData.GM == (Object)null) { return false; } try { GameData.GM.SaveGameData(false); } catch (Exception ex) { if (!_nativeSaveSucceeded) { throw; } TaschenhaendlerPlugin.ModLog.LogWarning((object)("Der Charakterstand wurde gespeichert, aber ein nachgelagerter Erenshor-Speicherschritt meldete einen Fehler: " + ex.Message)); } return _nativeSaveSucceeded; } finally { _nativeSaveProbeActive = false; _sidecarAlreadyCommittedForSave = false; } } internal static void ReportNativeSaveResult(bool succeeded) { if (_nativeSaveProbeActive) { _nativeSaveSucceeded = succeeded; } } internal static void Initialize(Inventory inventory) { if ((Object)(object)inventory == (Object)null || !inventory.isPlayer) { return; } if ((Object)(object)_inventory != (Object)(object)inventory) { _inventory = inventory; _trashSlot = ((IEnumerable<ItemIcon>)inventory.StoredSlots).FirstOrDefault((Func<ItemIcon, bool>)((ItemIcon slot) => (Object)(object)slot != (Object)null && slot.TrashSlot)); ExtraSlots.Clear(); ExtraSlots.AddRange(inventory.StoredSlots.Where(delegate(ItemIcon slot) { RectTransform slotRoot = GetSlotRoot(slot); return (Object)(object)slotRoot != (Object)null && (Object)(object)((Component)slotRoot).GetComponent<ExtraInventorySlotMarker>() != (Object)null; })); _scrollView = null; _loadedProgress = null; _pendingRecoveryNoticeShown = false; } List<ItemIcon> usableSlots = inventory.StoredSlots.Where(IsScrollableInventorySlot).ToList(); if (_scrollView == null) { _scrollView = InventoryScrollView.Create(inventory, usableSlots); } RebuildAllSlots(); } internal static bool CaptureCurrentBeforeCharacterSwitch() { if (_loadedProgress == null || (Object)(object)_inventory == (Object)null) { return true; } CaptureOverflow(_loadedProgress); bool num = ProgressStore.Save(); if (!num) { TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Charakterwechsel abgebrochen: Das Zusatzinventar konnte nicht gespeichert werden.", "Character switch cancelled: the extra inventory could not be saved.")); } return num; } internal static void ClearLoadedCharacter() { if ((Object)(object)_inventory != (Object)null) { EnsureExtraSlotCount(0); } _loadedProgress = null; UnresolvedOverflowIndices.Clear(); _pendingRecoveryNoticeShown = false; } internal static void LoadCharacter(CharacterProgress progress) { if ((Object)(object)GameData.PlayerInv == (Object)null || progress == null) { return; } Initialize(GameData.PlayerInv); _loadedProgress = progress; UnresolvedOverflowIndices.Clear(); foreach (ItemIcon extraSlot in ExtraSlots) { if ((Object)(object)extraSlot != (Object)null) { extraSlot.assignedHotkey = null; } } EnsureExtraSlotCount(GetDesiredExtraSlotCount(progress)); MerchantController.RefreshOffer(); } internal static void FinishCharacterLoad(CharacterProgress progress) { if ((Object)(object)_inventory == (Object)null || progress == null) { return; } for (int i = 0; i < ExtraSlots.Count; i++) { StoredItem storedItem = ((i < progress.Overflow.Count) ? progress.Overflow[i] : null); ItemIcon slot = ExtraSlots[i]; if (storedItem == null || string.IsNullOrEmpty(storedItem.Id)) { SetSlot(slot, _inventory.Empty, 0); continue; } ItemDatabase itemDB = GameData.ItemDB; Item val = ((itemDB != null) ? itemDB.GetItemByID(storedItem.Id) : null); if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_inventory.Empty) { TaschenhaendlerPlugin.ModLog.LogWarning((object)$"Zusatzslot {i} verweist auf unbekanntes Item '{storedItem.Id}'. Der Eintrag bleibt in der Sidecar-Datei erhalten."); UnresolvedOverflowIndices.Add(i); SetSlot(slot, _inventory.Empty, 0); } else { SetSlot(slot, val, Math.Max(1, storedItem.Quantity)); } } _inventory.UpdatePlayerInventory(); RestorePendingExpansionItems(); _scrollView?.LayoutSlots(); } internal static void FinishHotkeyLoad(CharacterProgress progress) { if (progress != null && !((Object)(object)GameData.GM?.HKManager == (Object)null)) { RestoreHotkeyList(GameData.GM.HKManager.FirstHotkeys, progress.FirstExtraHotkeys); RestoreHotkeyList(GameData.GM.HKManager.SecondHotkeys, progress.SecondExtraHotkeys); } } internal static bool TryUseExpansion(ItemIcon sourceSlot) { CharacterProgress current = ProgressStore.Current; if ((Object)(object)_inventory == (Object)null || current == null || (Object)(object)sourceSlot == (Object)null) { TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Kein aktiver Charakterfortschritt gefunden.", "No active character progress was found.")); return false; } if (sourceSlot.VendorSlot || !_inventory.StoredSlots.Contains(sourceSlot) || !TaschenhaendlerPlugin.IsExpansion(sourceSlot.MyItem)) { TaschenhaendlerPlugin.ModLog.LogWarning((object)"Benutzung eines Erweiterungsitems außerhalb des Spielerinventars wurde blockiert."); return false; } if (current.AppliedCount >= current.PurchasedCount) { TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Dieses Erweiterungsitem gehört nicht zum gespeicherten Kaufstand und wurde nicht verbraucht.", "This expansion item is not part of the saved purchase progress and was not consumed.")); return false; } long appliedCount = current.AppliedCount; long grantedSlots = current.GrantedSlots; Item myItem = sourceSlot.MyItem; int quantity = sourceSlot.Quantity; int count = ExtraSlots.Count; bool flag = false; try { current.AppliedCount++; checked { current.GrantedSlots += TaschenhaendlerPlugin.Instance.SlotsPerExpansion.Value; EnsureExtraSlotCount(GetDesiredExtraSlotCount(current)); } if (quantity > 1) { sourceSlot.Quantity = quantity - 1; } else { sourceSlot.MyItem = _inventory.Empty; sourceSlot.Quantity = 0; } sourceSlot.UpdateSlotImage(); CaptureOverflow(current); if (!ProgressStore.Save()) { throw new IOExceptionLikeException(); } flag = true; _inventory.UpdatePlayerInventory(); if (!SaveNativeAfterSidecarCommit()) { throw new InvalidOperationException("Erenshor hat den nativen Charakterstand nicht gespeichert."); } int value = TaschenhaendlerPlugin.Instance.SlotsPerExpansion.Value; TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Format("Inventar dauerhaft um {0} Plätze erweitert. Insgesamt: {1} Zusatzplätze.", "Inventory permanently expanded by {0} slots. Total: {1} extra slots.", value, current.GrantedSlots)); return true; } catch (Exception ex) { current.AppliedCount = appliedCount; current.GrantedSlots = grantedSlots; EnsureExtraSlotCount(count); sourceSlot.MyItem = myItem; sourceSlot.Quantity = quantity; sourceSlot.UpdateSlotImage(); CaptureOverflow(current); if (!(ex is IOExceptionLikeException)) { TaschenhaendlerPlugin.ModLog.LogError((object)$"Inventarerweiterung wurde zurückgerollt: {ex}"); TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Die Inventarerweiterung ist fehlgeschlagen und wurde nicht verbraucht.", "The inventory expansion failed and was not consumed.")); } if (flag) { CaptureOverflow(current); ProgressStore.Save(); } return false; } } internal static SaveIsolationState PrepareVanillaSave() { SaveIsolationState saveIsolationState = new SaveIsolationState { CanProceed = true, Prepared = false, Extras = new List<ItemIcon>(), HiddenExpansionItems = new List<HiddenExpansionItemState>() }; if ((Object)(object)_inventory == (Object)null) { return saveIsolationState; } if (ProgressStore.Current == null) { saveIsolationState.CanProceed = ExtraSlots.Count == 0; if (!saveIsolationState.CanProceed) { TaschenhaendlerPlugin.ModLog.LogError((object)"Vanilla-Speichern wurde abgebrochen, weil Zusatzslots ohne aktiven Charakterzustand vorhanden sind."); } return saveIsolationState; } if (!_sidecarAlreadyCommittedForSave) { CaptureOverflow(ProgressStore.Current); if (!ProgressStore.Save()) { saveIsolationState.CanProceed = false; return saveIsolationState; } } saveIsolationState.Prepared = true; try { saveIsolationState.Extras.AddRange(ExtraSlots.Where((ItemIcon slot) => (Object)(object)slot != (Object)null)); foreach (ItemIcon extra in saveIsolationState.Extras) { _inventory.StoredSlots.Remove(extra); } foreach (ItemIcon item in _inventory.StoredSlots.Where((ItemIcon entry) => (Object)(object)entry != (Object)null && TaschenhaendlerPlugin.IsExpansion(entry.MyItem)).ToList()) { saveIsolationState.HiddenExpansionItems.Add(new HiddenExpansionItemState { Slot = item, Item = item.MyItem, Quantity = item.Quantity }); item.MyItem = _inventory.Empty; item.Quantity = 0; item.UpdateSlotImage(); } MaskUnsafeHotkeys(saveIsolationState); RebuildAllSlots(); saveIsolationState.Prepared = saveIsolationState.Extras.Count > 0 || saveIsolationState.HiddenExpansionItems.Count > 0 || saveIsolationState.HotkeyIndices.Count > 0; return saveIsolationState; } catch (Exception arg) { saveIsolationState.CanProceed = false; TaschenhaendlerPlugin.ModLog.LogError((object)$"Vorbereitung des sicheren Vanilla-Speicherns ist fehlgeschlagen; Teilzustand wird wiederhergestellt: {arg}"); try { RestoreAfterVanillaSave(saveIsolationState); } catch (Exception arg2) { TaschenhaendlerPlugin.ModLog.LogError((object)$"Wiederherstellung nach fehlgeschlagener Save-Vorbereitung ist ebenfalls fehlgeschlagen: {arg2}"); } TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Speichern wurde abgebrochen, weil die Zusatzslots nicht sicher isoliert werden konnten.", "Saving was cancelled because the extra slots could not be isolated safely.")); return saveIsolationState; } } internal static void RestoreAfterVanillaSave(SaveIsolationState state) { if (state == null || !state.Prepared || (Object)(object)_inventory == (Object)null) { return; } int num = (((Object)(object)_trashSlot != (Object)null) ? _inventory.StoredSlots.IndexOf(_trashSlot) : _inventory.StoredSlots.Count); if (num < 0) { num = _inventory.StoredSlots.Count; } foreach (ItemIcon extra in state.Extras) { if ((Object)(object)extra != (Object)null && !_inventory.StoredSlots.Contains(extra)) { _inventory.StoredSlots.Insert(num++, extra); } } foreach (HiddenExpansionItemState hiddenExpansionItem in state.HiddenExpansionItems) { if (!((Object)(object)hiddenExpansionItem?.Slot == (Object)null)) { hiddenExpansionItem.Slot.MyItem = hiddenExpansionItem.Item; hiddenExpansionItem.Slot.Quantity = hiddenExpansionItem.Quantity; hiddenExpansionItem.Slot.UpdateSlotImage(); } } RebuildAllSlots(); foreach (KeyValuePair<Hotkeys, int> hotkeyIndex in state.HotkeyIndices) { if ((Object)(object)hotkeyIndex.Key != (Object)null) { hotkeyIndex.Key.InvSlotIndex = hotkeyIndex.Value; } } state.Prepared = false; _scrollView?.LayoutSlots(); } internal static void CaptureOverflow(CharacterProgress progress) { if (progress == null || (Object)(object)_inventory == (Object)null) { return; } List<StoredItem> list = new List<StoredItem>(ExtraSlots.Count); for (int i = 0; i < ExtraSlots.Count; i++) { ItemIcon val = ExtraSlots[i]; if ((Object)(object)val == (Object)null || (Object)(object)val.MyItem == (Object)null || (Object)(object)val.MyItem == (Object)(object)_inventory.Empty) { if (UnresolvedOverflowIndices.Contains(i) && i < progress.Overflow.Count && !string.IsNullOrEmpty(progress.Overflow[i]?.Id)) { StoredItem storedItem = progress.Overflow[i]; list.Add(new StoredItem { Id = storedItem.Id, Quantity = storedItem.Quantity }); } else { list.Add(new StoredItem()); } } else { UnresolvedOverflowIndices.Remove(i); list.Add(new StoredItem { Id = (((BaseScriptableObject)val.MyItem).Id ?? string.Empty), Quantity = Math.Max(1, val.Quantity) }); } } progress.Overflow = list; CaptureExtraHotkeys(progress); } private static int GetDesiredExtraSlotCount(CharacterProgress progress) { long grantedSlots = progress.GrantedSlots; if (grantedSlots > int.MaxValue) { throw new InvalidOperationException("Die Anzahl der Zusatzplätze überschreitet die technische Listengrenze von Unity."); } return (int)grantedSlots; } private static void EnsureExtraSlotCount(int desired) { if ((Object)(object)_inventory == (Object)null) { throw new InvalidOperationException("Spielerinventar ist nicht initialisiert."); } while (ExtraSlots.Count > desired) { ItemIcon val = ExtraSlots[ExtraSlots.Count - 1]; ExtraSlots.RemoveAt(ExtraSlots.Count - 1); _inventory.StoredSlots.Remove(val); RectTransform slotRoot = GetSlotRoot(val); if ((Object)(object)slotRoot != (Object)null) { ((Component)slotRoot).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)slotRoot).gameObject); } } while (ExtraSlots.Count < desired) { AddExtraSlot(); } RebuildAllSlots(); _scrollView?.LayoutSlots(); } private static void AddExtraSlot() { RectTransform slotRoot = GetSlotRoot(((IEnumerable<ItemIcon>)_inventory.StoredSlots).FirstOrDefault((Func<ItemIcon, bool>)delegate(ItemIcon slot) { if ((Object)(object)slot != (Object)null && !slot.TrashSlot) { RectTransform slotRoot2 = GetSlotRoot(slot); return (Object)(object)((slotRoot2 != null) ? ((Component)slotRoot2).GetComponent<ExtraInventorySlotMarker>() : null) == (Object)null; } return false; })); if ((Object)(object)slotRoot == (Object)null) { throw new InvalidOperationException("Kein normaler Inventarslot als Vorlage gefunden."); } Transform parent = ((Transform)slotRoot).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); GameObject val2 = Object.Instantiate<GameObject>(((Component)slotRoot).gameObject, (Transform)(object)val, false); ((Object)val2).name = $"Taschenhaendler_ExtraSlot_{ExtraSlots.Count + 1:D4}"; val2.AddComponent<ExtraInventorySlotMarker>(); ItemIcon componentInChildren = val2.GetComponentInChildren<ItemIcon>(true); if ((Object)(object)componentInChildren == (Object)null) { Object.Destroy((Object)(object)val2); throw new InvalidOperationException("Die Slot-Vorlage enthält kein ItemIcon."); } if ((Object)(object)componentInChildren.MySparkler != (Object)null) { GameObject gameObject = ((Component)componentInChildren.MySparkler).gameObject; componentInChildren.MySparkler = null; Object.Destroy((Object)(object)gameObject); } componentInChildren.TrashSlot = false; componentInChildren.VendorSlot = false; componentInChildren.LootSlot = false; componentInChildren.BankSlot = false; componentInChildren.NotInInventory = false; componentInChildren.dragging = false; componentInChildren.assignedHotkey = null; Traverse obj = Traverse.Create((object)componentInChildren); obj.Field("hotkey").SetValue((object)null); obj.Field("MouseHomeSlot").SetValue((object)null); obj.Field("SwapWith").SetValue((object)null); obj.Field("rButton").SetValue((object)false); obj.Field("lButton").SetValue((object)false); obj.Field("doHotkey").SetValue((object)false); componentInChildren.MyItem = _inventory.Empty; componentInChildren.Quantity = 0; componentInChildren.ForceInitInv(); int num = (((Object)(object)_trashSlot != (Object)null) ? _inventory.StoredSlots.IndexOf(_trashSlot) : _inventory.StoredSlots.Count); if (num < 0) { num = _inventory.StoredSlots.Count; } _inventory.StoredSlots.Insert(num, componentInChildren); ExtraSlots.Add(componentInChildren); } private static void SetSlot(ItemIcon slot, Item item, int quantity) { slot.MyItem = item; slot.Quantity = quantity; slot.UpdateSlotImage(); } private static void RebuildAllSlots() { if (!((Object)(object)_inventory == (Object)null)) { _inventory.ALLSLOTS.Clear(); _inventory.ALLSLOTS.AddRange(_inventory.EquipmentSlots.Where((ItemIcon slot) => (Object)(object)slot != (Object)null)); _inventory.ALLSLOTS.AddRange(_inventory.StoredSlots.Where((ItemIcon slot) => (Object)(object)slot != (Object)null)); _inventory.ALLSLOTS.AddRange(_inventory.TransmogSlots.Where((ItemIcon slot) => (Object)(object)slot != (Object)null)); for (int num = 0; num < _inventory.ALLSLOTS.Count; num++) { _inventory.ALLSLOTS[num].ALLSLOTSINDEX = num; } } } private static void CaptureExtraHotkeys(CharacterProgress progress) { if (!((Object)(object)GameData.GM?.HKManager == (Object)null)) { progress.FirstExtraHotkeys = CaptureHotkeyList(GameData.GM.HKManager.FirstHotkeys); progress.SecondExtraHotkeys = CaptureHotkeyList(GameData.GM.HKManager.SecondHotkeys); } } private static List<int> CaptureHotkeyList(List<Hotkeys> hotkeys) { List<int> list = new List<int>(); if (hotkeys == null) { return list; } foreach (Hotkeys hotkey in hotkeys) { int item = (((Object)(object)hotkey?.AssignedItem != (Object)null) ? ExtraSlots.IndexOf(hotkey.AssignedItem) : (-1)); list.Add(item); } return list; } private static void RestoreHotkeyList(List<Hotkeys> hotkeys, List<int> mappings) { if (hotkeys == null || mappings == null) { return; } int num = Math.Min(hotkeys.Count, mappings.Count); for (int i = 0; i < num; i++) { int num2 = mappings[i]; if (num2 >= 0 && num2 < ExtraSlots.Count && !((Object)(object)hotkeys[i] == (Object)null) && !((Object)(object)ExtraSlots[num2] == (Object)null)) { hotkeys[i].ClearMe(); hotkeys[i].AssignItemFrominv(ExtraSlots[num2]); ExtraSlots[num2].assignedHotkey = hotkeys[i]; } } } private static void MaskUnsafeHotkeys(SaveIsolationState state) { if (GameData.GM?.HKManager?.AllHotkeys == null) { return; } foreach (Hotkeys hotkey in GameData.GM.HKManager.AllHotkeys) { if ((Object)(object)hotkey != (Object)null && (Object)(object)hotkey.AssignedItem != (Object)null && (ExtraSlots.Contains(hotkey.AssignedItem) || state.HiddenExpansionItems.Any((HiddenExpansionItemState hidden) => hidden != null && (Object)(object)hidden.Slot == (Object)(object)hotkey.AssignedItem))) { state.HotkeyIndices[hotkey] = hotkey.InvSlotIndex; hotkey.InvSlotIndex = -1; } } } private static bool IsUsableEmptyInventorySlot(ItemIcon slot) { if (IsScrollableInventorySlot(slot) && (Object)(object)slot.MyItem == (Object)(object)_inventory.Empty) { return !IsReservedUnresolvedSlot(slot); } return false; } } [HarmonyPatch(typeof(CharSelectManager), "LoadHotkeys")] internal static class ExtraHotkeyLoadPatch { [HarmonyPostfix] private static void Postfix() { InventoryExpansionController.FinishHotkeyLoad(ProgressStore.Current); } } [HarmonyPatch(typeof(Inventory), "Start")] internal static class InventoryStartPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Inventory __instance) { try { InventoryExpansionController.Initialize(__instance); } catch (Exception arg) { TaschenhaendlerPlugin.ModLog.LogError((object)$"Inventarinitialisierung fehlgeschlagen: {arg}"); } } } [HarmonyPatch(typeof(CharSelectManager), "LoadEquipment")] internal static class CharacterLoadPatch { [HarmonyPrefix] private static void Prefix() { InventoryExpansionController.LoadCharacter(ProgressStore.SelectCurrentCharacter()); } [HarmonyPostfix] private static void Postfix() { InventoryExpansionController.FinishCharacterLoad(ProgressStore.Current); } } [HarmonyPatch(typeof(CharSelectManager), "SelectSlot")] internal static class CharacterSelectionPatch { [HarmonyPrefix] private static bool Prefix() { return InventoryExpansionController.CaptureCurrentBeforeCharacterSwitch(); } [HarmonyPostfix] private static void Postfix() { if (GameData.CurrentCharacterSlot != null && string.IsNullOrEmpty(GameData.CurrentCharacterSlot.CharName)) { InventoryExpansionController.ClearLoadedCharacter(); ProgressStore.ClearCurrent(); } } } [HarmonyPatch(typeof(CharSelectManager), "SelectBackupSlot")] internal static class BackupCharacterSelectionPatch { [HarmonyPrefix] private static bool Prefix() { return InventoryExpansionController.CaptureCurrentBeforeCharacterSwitch(); } } [HarmonyPatch(typeof(ItemIcon), "UseConsumable")] internal static class UseExpansionPatch { [HarmonyPrefix] private static bool Prefix(ItemIcon __instance) { if (!TaschenhaendlerPlugin.IsExpansion(__instance?.MyItem)) { return true; } InventoryExpansionController.TryUseExpansion(__instance); return false; } } [HarmonyPatch(typeof(GameManager), "SaveGameData")] internal static class SafeInventorySavePatch { [HarmonyPrefix] private static bool Prefix(out SaveIsolationState __state) { __state = InventoryExpansionController.PrepareVanillaSave(); return __state.CanProceed; } [HarmonyPostfix] private static void Postfix(SaveIsolationState __state) { InventoryExpansionController.RestoreAfterVanillaSave(__state); } [HarmonyFinalizer] private static Exception Finalizer(Exception __exception, SaveIsolationState __state) { InventoryExpansionController.RestoreAfterVanillaSave(__state); return __exception; } } [HarmonyPatch(typeof(GameData), "SaveData")] internal static class NativeCharacterSaveResultPatch { [HarmonyPostfix] private static void Postfix(bool __result) { InventoryExpansionController.ReportNativeSaveResult(__result); } } internal sealed class DeletedCharacterKey { internal int SlotIndex; internal string Name; } [HarmonyPatch(typeof(CharSelectManager), "EraseCharacter")] internal static class CharacterErasePatch { [HarmonyPrefix] private static void Prefix(CharSelectManager __instance, out DeletedCharacterKey __state) { __state = null; SaveGameData val = GameData.CurrentCharacterSlot; if (val == null) { int value = Traverse.Create((object)__instance).Field("curIndex").GetValue<int>(); if (GameData.SaveSlots != null && value >= 0 && value < GameData.SaveSlots.Count) { val = GameData.SaveSlots[value]; } } if (val != null) { __state = new DeletedCharacterKey { SlotIndex = val.index, Name = (val.CharName ?? string.Empty) }; } } [HarmonyPostfix] private static void Postfix(DeletedCharacterKey __state) { if (__state != null) { InventoryExpansionController.ClearLoadedCharacter(); ProgressStore.Remove(__state.SlotIndex, __state.Name); } } } internal enum InventoryFilterMode { All, Weapons, ArmorAndJewelry, Consumables, Crafting, QuestAndBooks, Rare, Other } internal enum InventorySortMode { Name, Type, Level, Value, Quantity } internal static class InventoryToolsState { private static readonly string[] StableSortModes = new string[5] { "Name", "Type", "Level", "Value", "Quantity" }; private static string _searchText = string.Empty; private static InventoryFilterMode _filter = InventoryFilterMode.All; internal static string SearchText => _searchText; internal static InventoryFilterMode Filter => _filter; internal static InventorySortMode PendingSortMode { get { if (!TryParseSortMode(TaschenhaendlerPlugin.Instance?.PreferredSortMode?.Value, out var mode)) { return InventorySortMode.Type; } return mode; } } internal static bool PendingDescending => TaschenhaendlerPlugin.Instance?.SortDescending?.Value == true; internal static IReadOnlyList<string> FilterLabels { get { if (ModLocalization.IsGerman) { return new string[8] { "Alle", "Waffen", "Rüst./Schm.", "Verbrauch", "Handwerk", "Quest/Buch", "Selten", "Sonstiges" }; } return new string[8] { "All", "Weapons", "Armor/Jewel.", "Consume", "Crafting", "Quest/Book", "Rare", "Other" }; } } internal static IReadOnlyList<string> SortLabels { get { if (ModLocalization.IsGerman) { return new string[5] { "Name", "Typ", "Stufe", "Wert", "Menge" }; } return new string[5] { "Name", "Type", "Level", "Value", "Quantity" }; } } internal static void SetSearch(string value) { _searchText = value?.Trim() ?? string.Empty; } internal static void SetFilter(int index) { _filter = (InventoryFilterMode)Mathf.Clamp(index, 0, Enum.GetValues(typeof(InventoryFilterMode)).Length - 1); } internal static void SetPendingSortMode(int index) { index = Mathf.Clamp(index, 0, StableSortModes.Length - 1); if (TaschenhaendlerPlugin.Instance?.PreferredSortMode != null) { TaschenhaendlerPlugin.Instance.PreferredSortMode.Value = StableSortModes[index]; } } internal static void TogglePendingDirection() { if (TaschenhaendlerPlugin.Instance?.SortDescending != null) { TaschenhaendlerPlugin.Instance.SortDescending.Value = !TaschenhaendlerPlugin.Instance.SortDescending.Value; } } internal static bool TryParseSortMode(string value, out InventorySortMode mode) { for (int i = 0; i < StableSortModes.Length; i++) { if (string.Equals(value, StableSortModes[i], StringComparison.OrdinalIgnoreCase)) { mode = (InventorySortMode)i; return true; } } mode = InventorySortMode.Type; return false; } internal static List<ItemIcon> GetDisplayedSlots(IEnumerable<ItemIcon> source, Item empty) { return (from slot in source where (Object)(object)slot != (Object)null && !slot.TrashSlot where Matches(slot, empty) select slot).ToList(); } private static bool Matches(ItemIcon slot, Item empty) { Item val = slot?.MyItem; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)empty) { if (_filter == InventoryFilterMode.All) { return string.IsNullOrEmpty(_searchText); } return false; } if (!string.IsNullOrEmpty(_searchText)) { bool num = (val.ItemName ?? string.Empty).IndexOf(_searchText, StringComparison.CurrentCultureIgnoreCase) >= 0; bool flag = (val.Lore ?? string.Empty).IndexOf(_searchText, StringComparison.CurrentCultureIgnoreCase) >= 0; if (!num && !flag) { return false; } } if (_filter != InventoryFilterMode.All && GetFilterCategory(val) != _filter) { if (_filter == InventoryFilterMode.Rare) { if (!val.RareItem && !val.Relic) { return val.Unique; } return true; } return false; } return true; } private static InventoryFilterMode GetFilterCategory(Item item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return InventoryFilterMode.Other; } if ((int)item.RequiredSlot == 13 || (int)item.RequiredSlot == 14 || (int)item.RequiredSlot == 15 || item.WeaponDmg != 0 || (int)item.ThisWeaponType != 0 || item.IsBow || item.IsWand) { return InventoryFilterMode.Weapons; } if ((int)item.RequiredSlot != 0) { return InventoryFilterMode.ArmorAndJewelry; } if ((Object)(object)item.AssignQuestOnRead != (Object)null || (Object)(object)item.CompleteOnRead != (Object)null || !string.IsNullOrWhiteSpace(item.BookTitle) || (Object)(object)item.TeachSpell != (Object)null || (Object)(object)item.TeachSkill != (Object)null) { return InventoryFilterMode.QuestAndBooks; } if ((Object)(object)item.ItemEffectOnClick != (Object)null || (Object)(object)item.ItemSkillUse != (Object)null || item.Disposable) { return InventoryFilterMode.Consumables; } if (item.Template || item.FuelSource || item.Mining > 0 || item.FurnitureSet) { return InventoryFilterMode.Crafting; } return InventoryFilterMode.Other; } } internal sealed class InventoryToolsPanel : MonoBehaviour { private static readonly HashSet<InventoryToolsPanel> LivePanels = new HashSet<InventoryToolsPanel>(); private Inventory _inventory; private InventoryScrollView _scrollView; private TMP_InputField _search; private TextMeshProUGUI _searchPlaceholder; private InventoryChoiceDropdown _language; private InventoryChoiceDropdown _filter; private InventoryChoiceDropdown _sortMode; private Button _directionButton; private TextMeshProUGUI _directionText; private Button _sortButton; private TextMeshProUGUI _sortButtonText; private TMP_FontAsset _font; private float _autoSortGuard; internal static InventoryToolsPanel Create(Inventory inventory, InventoryScrollView scrollView, RectTransform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, Vector2 size) { //IL_0066: 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_007b: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00ed: 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) //IL_0141: Unknown result type (might be due to invalid IL or missing references) InventoryToolsPanel componentInChildren = ((Component)parent).GetComponentInChildren<InventoryToolsPanel>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren._inventory = inventory; componentInChildren._scrollView = scrollView; componentInChildren.RefreshLocalization(); return componentInChildren; } GameObject val = new GameObject("CBra_InventoryTools", new Type[4] { typeof(RectTransform), typeof(Image), typeof(Outline), typeof(InventoryToolsPanel) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = anchoredPosition; component.sizeDelta = size; ((Graphic)val.GetComponent<Image>()).color = new Color(0.035f, 0.12f, 0.16f, 0.94f); Outline component2 = val.GetComponent<Outline>(); ((Shadow)component2).effectColor = new Color(0.35f, 0.75f, 0.78f, 0.9f); ((Shadow)component2).effectDistance = new Vector2(1f, -1f); InventoryToolsPanel component3 = val.GetComponent<InventoryToolsPanel>(); component3._inventory = inventory; component3._scrollView = scrollView; component3._font = (((Object)(object)inventory.GoldTXT != (Object)null) ? ((TMP_Text)inventory.GoldTXT).font : null); component3.Build(size); component3.RefreshLocalization(); ((Transform)component).SetAsLastSibling(); component3.DisableExternalAutoSortButtons(); return component3; } internal static void RefreshAllLocalization() { InventoryToolsPanel[] array = LivePanels.Where((InventoryToolsPanel panel) => (Object)(object)panel != (Object)null).ToArray(); for (int num = 0; num < array.Length; num++) { array[num].RefreshLocalization(); } } private void OnEnable() { LivePanels.Add(this); } private void OnDisable() { if ((Object)(object)_search != (Object)null && _search.isFocused) { GameData.PlayerTyping = false; } } private void OnDestroy() { LivePanels.Remove(this); if ((Object)(object)_search != (Object)null && _search.isFocused) { GameData.PlayerTyping = false; } } private void Update() { _autoSortGuard -= Time.unscaledDeltaTime; if (_autoSortGuard <= 0f) { _autoSortGuard = 2f; DisableExternalAutoSortButtons(); } } private void Build(Vector2 size) { //IL_0011: 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_003b: 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) //IL_0087: 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_00bc: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Expected O, but got Unknown Transform transform = ((Component)this).transform; RectTransform parent = (RectTransform)(object)((transform is RectTransform) ? transform : null); float num = Math.Max(1f, size.x - 8f); _search = CreateSearch(parent, new Vector2(0f, 31f), new Vector2(num, 23f)); float num2 = Math.Min(82f, num * 0.43f); float num3 = num - num2 - 4f; _language = InventoryChoiceDropdown.Create(parent, "CBra_LanguageDropdown", new Vector2((0f - (num - num2)) * 0.5f, 3f), new Vector2(num2, 23f), _font); _filter = InventoryChoiceDropdown.Create(parent, "CBra_FilterDropdown", new Vector2((num - num3) * 0.5f, 3f), new Vector2(num3, 23f), _font); float num4 = 28f; float num5 = 52f; float num6 = 6f; float num7 = num - num4 - num5 - num6; float num8 = (0f - num) * 0.5f; _sortMode = InventoryChoiceDropdown.Create(parent, "CBra_SortModeDropdown", new Vector2(num8 + num7 * 0.5f, -25f), new Vector2(num7, 23f), _font); _directionButton = CreateButton(parent, "CBra_SortDirection", new Vector2(num8 + num7 + 3f + num4 * 0.5f, -25f), new Vector2(num4, 23f), out _directionText); ((UnityEvent)_directionButton.onClick).AddListener((UnityAction)delegate { InventoryToolsState.TogglePendingDirection(); RefreshLocalization(); }); _sortButton = CreateButton(parent, "CBra_SortButton", new Vector2(num * 0.5f - num5 * 0.5f, -25f), new Vector2(num5, 23f), out _sortButtonText); ((UnityEvent)_sortButton.onClick).AddListener(new UnityAction(SortNow)); _language.SetSelectionHandler(delegate(int index) { ModLocalization.SetModeByIndex(index); }); _filter.SetSelectionHandler(delegate(int index) { InventoryToolsState.SetFilter(index); _scrollView?.LayoutSlots(resetScroll: true); RefreshLocalization(); }); _sortMode.SetSelectionHandler(delegate(int index) { InventoryToolsState.SetPendingSortMode(index); RefreshLocalization(); }); } private TMP_InputField CreateSearch(RectTransform parent, Vector2 position, Vector2 size) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0034: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0208: 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_021d: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Expected O, but got Unknown GameObject val = new GameObject("CBra_InventorySearch", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ConfigureRect(component, parent, position, size); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.015f, 0.035f, 0.045f, 0.96f); RectTransform component3 = new GameObject("Text Area", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }).GetComponent<RectTransform>(); ((Transform)component3).SetParent((Transform)(object)component, false); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = new Vector2(7f, 1f); component3.offsetMax = new Vector2(-7f, -1f); TextMeshProUGUI val2 = CreateText(component3, "Text", string.Empty, 13f, (TextAlignmentOptions)4097); RectTransform rectTransform = ((TMP_Text)val2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; _searchPlaceholder = CreateText(component3, "Placeholder", string.Empty, 13f, (TextAlignmentOptions)4097); ((Graphic)_searchPlaceholder).color = new Color(0.72f, 0.78f, 0.8f, 0.72f); RectTransform rectTransform2 = ((TMP_Text)_searchPlaceholder).rectTransform; rectTransform2.anchorMin = Vector2.zero; rectTransform2.anchorMax = Vector2.one; rectTransform2.offsetMin = Vector2.zero; rectTransform2.offsetMax = Vector2.zero; TMP_InputField obj = val.AddComponent<TMP_InputField>(); obj.textViewport = component3; obj.textComponent = (TMP_Text)(object)val2; obj.placeholder = (Graphic)(object)_searchPlaceholder; ((Selectable)obj).targetGraphic = (Graphic)(object)component2; obj.lineType = (LineType)0; obj.contentType = (ContentType)0; obj.characterLimit = 80; obj.customCaretColor = true; obj.caretColor = Color.white; obj.selectionColor = new Color(0.25f, 0.7f, 0.8f, 0.45f); obj.onValueChanged = new OnChangeEvent(); obj.onSelect = new SelectionEvent(); obj.onDeselect = new SelectionEvent(); ((UnityEvent<string>)(object)obj.onValueChanged).AddListener((UnityAction<string>)delegate(string value) { InventoryToolsState.SetSearch(value); _scrollView?.LayoutSlots(resetScroll: true); }); ((UnityEvent<string>)(object)obj.onSelect).AddListener((UnityAction<string>)delegate { GameData.PlayerTyping = true; }); ((UnityEvent<string>)(object)obj.onDeselect).AddListener((UnityAction<string>)delegate { GameData.PlayerTyping = false; }); obj.SetTextWithoutNotify(InventoryToolsState.SearchText); return obj; } private Button CreateButton(RectTransform parent, string name, Vector2 position, Vector2 size, out TextMeshProUGUI label) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); RectTransform component = val.GetComponent<RectTransform>(); ConfigureRect(component, parent, position, size); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.08f, 0.26f, 0.31f, 0.98f); Button component3 = val.GetComponent<Button>(); ((Selectable)component3).targetGraphic = (Graphic)(object)component2; ColorBlock colors = ((Selectable)component3).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(0.16f, 0.46f, 0.5f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.72f, 0.55f, 0.22f, 1f); ((Selectable)component3).colors = colors; label = CreateText(component, "Label", string.Empty, 12f, (TextAlignmentOptions)514); ((Graphic)label).raycastTarget = false; RectTransform rectTransform = ((TMP_Text)label).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(2f, 0f); rectTransform.offsetMax = new Vector2(-2f, 0f); return component3; } private TextMeshProUGUI CreateText(RectTransform parent, string name, string value, float size, TextAlignmentOptions alignment) { //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_0049: 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) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); ((Transform)val.GetComponent<RectTransform>()).SetParent((Transform)(object)parent, false); TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).text = value; ((TMP_Text)component).fontSize = size; ((TMP_Text)component).alignment = alignment; ((Graphic)component).color = Color.white; ((TMP_Text)component).enableWordWrapping = false; if ((Object)(object)_font != (Object)null) { ((TMP_Text)component).font = _font; } return component; } private static void ConfigureRect(RectTransform rect, RectTransform parent, Vector2 position, Vector2 size) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) ((Transform)rect).SetParent((Transform)(object)parent, false); rect.anchorMin = new Vector2(0.5f, 0.5f); rect.anchorMax = new Vector2(0.5f, 0.5f); rect.pivot = new Vector2(0.5f, 0.5f); rect.anchoredPosition = position; rect.sizeDelta = size; } private void SortNow() { if (InventorySorter.TrySort(_inventory)) { _scrollView?.LayoutSlots(resetScroll: true); } RefreshLocalization(); } private void RefreshLocalization() { if ((Object)(object)_searchPlaceholder != (Object)null) { ((TMP_Text)_searchPlaceholder).text = ModLocalization.Text("Suchen …", "Search …"); } _language?.SetOptions(ModLocalization.Text("Spr.", "Lang."), ModLocalization.LanguageOptionLabels, ModLocalization.CurrentModeIndex); _filter?.SetOptions(ModLocalization.Text("Filter", "Filter"), InventoryToolsState.FilterLabels, (int)InventoryToolsState.Filter); _sortMode?.SetOptions(ModLocalization.Text("Sort.", "Sort"), InventoryToolsState.SortLabels, (int)InventoryToolsState.PendingSortMode); if ((Object)(object)_directionText != (Object)null) { ((TMP_Text)_directionText).text = (InventoryToolsState.PendingDescending ? "↓" : "↑"); } if ((Object)(object)_sortButtonText != (Object)null) { ((TMP_Text)_sortButtonText).text = ModLocalization.Text("Sort.", "Sort"); } _scrollView?.LayoutSlots(); } private void DisableExternalAutoSortButtons() { Transform val = (((Object)(object)_inventory?.InvWindow != (Object)null) ? _inventory.InvWindow.transform : ((Component)this).transform.parent); if ((Object)(object)val == (Object)null) { return; } Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)(object)((Component)this).gameObject && string.Equals(((Object)val2).name, "AutoSortButton", StringComparison.Ordinal)) { ((Component)val2).gameObject.SetActive(false); } } } } internal sealed class InventoryChoiceDropdown : MonoBehaviour { private TextMeshProUGUI _caption; private RectTransform _optionsPanel; private TMP_FontAsset _font; private string _prefix = string.Empty; private IReadOnlyList<string> _options = Array.Empty<string>(); private int _selected; private Action<int> _selectionHandler; internal static InventoryChoiceDropdown Create(RectTransform parent, string name, Vector2 position, Vector2 size, TMP_FontAsset font) { //IL_003b: 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_005a: 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_0084: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[4] { typeof(RectTransform), typeof(Image), typeof(Button), typeof(InventoryChoiceDropdown) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = position; component.sizeDelta = size; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.055f, 0.18f, 0.22f, 0.98f); Button component3 = val.GetComponent<Button>(); ((Selectable)component3).targetGraphic = (Graphic)(object)component2; InventoryChoiceDropdown component4 = val.GetComponent<InventoryChoiceDropdown>(); component4._font = font; component4._caption = component4.CreateText(component, "Caption", 11.5f); ((TMP_Text)component4._caption).rectTransform.anchorMin = Vector2.zero; ((TMP_Text)component4._caption).rectTransform.anchorMax = Vector2.one; ((TMP_Text)component4._caption).rectTransform.offsetMin = new Vector2(3f, 0f); ((TMP_Text)component4._caption).rectTransform.offsetMax = new Vector2(-3f, 0f); ((UnityEvent)component3.onClick).AddListener(new UnityAction(component4.Toggle)); return component4; } internal void SetSelectionHandler(Action<int> handler) { _selectionHandler = handler; } internal void SetOptions(string prefix, IReadOnlyList<string> options, int selected) { _prefix = prefix ?? string.Empty; _options = options ?? Array.Empty<string>(); _selected = Mathf.Clamp(selected, 0, Math.Max(0, _options.Count - 1)); if ((Object)(object)_caption != (Object)null) { string text = ((_options.Count > 0) ? _options[_selected] : string.Empty); ((TMP_Text)_caption).text = _prefix + ": " + text + " ▼"; } if ((Object)(object)_optionsPanel != (Object)null && ((Component)_optionsPanel).gameObject.activeSelf) { BuildOptions(); } } private void Toggle() { bool flag = (Object)(object)_optionsPanel == (Object)null || !((Component)_optionsPanel).gameObject.activeSelf; InventoryChoiceDropdown[] componentsInChildren = ((Component)((Component)this).transform.parent).GetComponentsInChildren<InventoryChoiceDropdown>(true); foreach (InventoryChoiceDropdown inventoryChoiceDropdown in componentsInChildren) { if ((Object)(object)inventoryChoiceDropdown != (Object)(object)this) { inventoryChoiceDropdown.Close(); } } if (!flag) { Close(); return; } BuildOptions(); ((Component)_optionsPanel).gameObject.SetActive(true); ((Component)this).transform.SetAsLastSibling(); } private void Close() { if ((Object)(object)_optionsPanel != (Object)null) { ((Component)_optionsPanel).gameObject.SetActive(false); } } private void BuildOptions() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Expected O, but got Unknown if ((Object)(object)_optionsPanel == (Object)null) { GameObject val = new GameObject("Options", new Type[2] { typeof(RectTransform), typeof(Image) }); _optionsPanel = val.GetComponent<RectTransform>(); ((Transform)_optionsPanel).SetParent(((Component)this).transform, false); _optionsPanel.anchorMin = new Vector2(0f, 0f); _optionsPanel.anchorMax = new Vector2(1f, 0f); _optionsPanel.pivot = new Vector2(0.5f, 1f); _optionsPanel.anchoredPosition = new Vector2(0f, -1f); ((Graphic)val.GetComponent<Image>()).color = new Color(0.015f, 0.05f, 0.065f, 0.99f); } Transform[] array = ((IEnumerable)_optionsPanel).Cast<Transform>().ToArray(); for (int i = 0; i < array.Length; i++) { Object.DestroyImmediate((Object)(object)((Component)array[i]).gameObject); } _optionsPanel.sizeDelta = new Vector2(0f, 22f * (float)_options.Count + 2f); for (int j = 0; j < _options.Count; j++) { int captured = j; GameObject val2 = new GameObject($"Option_{j}", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); RectTransform component = val2.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)_optionsPanel, false); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -1f - (float)j * 22f); component.sizeDelta = new Vector2(0f, 22f); Image component2 = val2.GetComponent<Image>(); ((Graphic)component2).color = ((j == _selected) ? new Color(0.55f, 0.4f, 0.12f, 0.98f) : new Color(0.055f, 0.18f, 0.22f, 0.98f)); Button component3 = val2.GetComponent<Button>(); ((Selectable)component3).targetGraphic = (Graphic)(object)component2; TextMeshProUGUI obj = CreateText(component, "Label", 11.5f); ((TMP_Text)obj).text = _options[j]; ((TMP_Text)obj).rectTransform.anchorMin = Vector2.zero; ((TMP_Text)obj).rectTransform.anchorMax = Vector2.one; ((TMP_Text)obj).rectTransform.offsetMin = new Vector2(3f, 0f); ((TMP_Text)obj).rectTransform.offsetMax = new Vector2(-3f, 0f); ((UnityEvent)component3.onClick).AddListener((UnityAction)delegate { _selected = captured; Close(); _selectionHandler?.Invoke(captured); }); } } private TextMeshProUGUI CreateText(RectTransform parent, string name, float size) { //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_004c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); ((Transform)val.GetComponent<RectTransform>()).SetParent((Transform)(object)parent, false); TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).alignment = (TextAlignmentOptions)514; ((TMP_Text)component).fontSize = size; ((Graphic)component).color = Color.white; ((TMP_Text)component).enableWordWrapping = false; ((Graphic)component).raycastTarget = false; if ((Object)(object)_font != (Object)null) { ((TMP_Text)component).font = _font; } return component; } } internal static class InventorySorter { private sealed class SlotSnapshot { internal readonly ItemIcon Slot; internal readonly Item Item; internal readonly int Quantity; internal readonly int OriginalIndex; internal SlotSnapshot(ItemIcon slot, Item item, int quantity, int originalIndex) { Slot = slot; Item = item; Quantity = quantity; OriginalIndex = originalIndex; } } private sealed class HotkeySnapshot { internal readonly Hotkeys Hotkey; internal readonly ItemIcon OriginalSlot; internal readonly int OriginalInvSlotIndex; internal HotkeySnapshot(Hotkeys hotkey, ItemIcon originalSlot, int originalInvSlotIndex) { Hotkey = hotkey; OriginalSlot = originalSlot; OriginalInvSlotIndex = originalInvSlotIndex; } } private sealed class SortEntry { internal readonly Item Item; internal readonly int Quantity; internal readonly int OriginalIndex; internal readonly List<Hotkeys> Hotkeys; internal SortEntry(Item item, int quantity, int originalIndex, List<Hotkeys> hotkeys) { Item = item; Quantity = quantity; OriginalIndex = originalIndex; Hotkeys = hotkeys; } } private sealed class StackGroup { internal readonly Item Item; internal readonly int OriginalIndex; internal readonly List<Hotkeys> Hotkeys = new List<Hotkeys>(); internal long Total; internal StackGroup(Item item, int originalIndex) { Item = item; OriginalIndex = originalIndex; } } private readonly struct ComparisonSlot { internal readonly Item Item; internal readonly int Quantity; internal ComparisonSlot(Item item, int quantity) { Item = item; Quantity = quantity; } } private sealed class ReferenceComparer<T> : IEqualityComparer<T> where T : class { internal static readonly ReferenceComparer<T> Instance = new ReferenceComparer<T>(); public bool Equals(T left, T right) { return left == right; } public int GetHashCode(T value) { return RuntimeHelpers.GetHashCode(value); } } internal static bool TrySort(Inventory inventory) { if (!CanSort(inventory, out var reason)) { TaschenhaendlerPlugin.NotifyPlayer(reason); return false; } CharacterProgress current = ProgressStore.Current; List<ItemIcon> list = inventory.StoredSlots.Where((ItemIcon slot) => IsSortableSlot(inventory, slot)).ToList(); List<SlotSnapshot> snapshot = list.Select((ItemIcon slot, int index) => new SlotSnapshot(slot, slot.MyItem, slot.Quantity, index)).ToList(); List<HotkeySnapshot> hotkeys = CaptureHotkeys(list); bool flag = false; try { List<SortEntry> list2 = BuildEntries(snapshot, hotkeys, inventory.Empty, TaschenhaendlerPlugin.Instance.MergeStacksOnSort.Value); InventorySortMode mode = InventoryToolsState.PendingSortMode; bool descending = InventoryToolsState.PendingDescending; list2.Sort((SortEntry left, SortEntry right) => CompareEntries(left, right, mode, descending)); foreach (ItemIcon item in list) { item.MyItem = inventory.Empty; item.Quantity = 0; item.assignedHotkey = null; } for (int num = 0; num < list2.Count; num++) { SortEntry sortEntry = list2[num]; ItemIcon val = list[num]; val.MyItem = sortEntry.Item; val.Quantity = sortEntry.Quantity; foreach (Hotkeys hotkey in sortEntry.Hotkeys) { if (!((Object)(object)hotkey == (Object)null)) { hotkey.AssignItemFrominv(val); hotkey.UpdateImg(); val.assignedHotkey = hotkey; } } } foreach (ItemIcon item2 in list) { item2.UpdateSlotImage(); } inventory.UpdatePlayerInventory(); InventoryExpansionController.CaptureOverflow(current); if (!ProgressStore.Save()) { throw new InvalidOperationException("Sidecar save failed"); } flag = true; if (!InventoryExpansionController.SaveNativeAfterSidecarCommit()) { throw new InvalidOperationException("Native character save failed"); } TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Inventar sortiert; Hotkeys und Zusatzplätze wurden beibehalten.", "Inventory sorted; hotkeys and extra slots were preserved.")); return true; } catch (Exception arg) { RestoreSnapshot(inventory, snapshot, hotkeys); InventoryExpansionController.CaptureOverflow(current); if (flag) { ProgressStore.Save(); } TaschenhaendlerPlugin.ModLog.LogError((object)$"Inventarsortierung wurde zurückgerollt: {arg}"); TaschenhaendlerPlugin.NotifyPlayer(ModLocalization.Text("Sortierung fehlgeschlagen; das Inventar wurde vollständig zurückgesetzt.", "Sorting failed; the inventory was fully restored.")); return false; } } internal static int CompareItemSlots(ItemIcon left, ItemIcon right, InventorySortMode mode) { Item myItem = left.MyItem; Item myItem2 = right.MyItem; return mode switch { InventorySortMode.Name => CultureInfo.InvariantCulture.CompareInfo.Compare(myItem.ItemName ?? string.Empty, myItem2.ItemName ?? string.Empty, CompareOptions.IgnoreCase), InventorySortMode.Type => CompareType(myItem, myItem2), InventorySortMode.Level => myItem.ItemLevel.CompareTo(myItem2.ItemLevel), InventorySortMode.Value => myItem.ItemValue.CompareTo(myItem2.ItemValue), InventorySortMode.Quantity => GetQuantityKey(left).CompareTo(GetQuantityKey(right)), _ => 0, }; } private static bool CanSort(Inventory inventory, out string reason) { if ((Object)(object)inventory == (Object)null || !inventory.isPlayer || (Object)(object)inventory.InvWindow == (Object)null || !inventory.InvWindow.activeSelf) { reason = ModLocalization.Text("Öffne zuerst dein Inventar.", "Open your inventory first."); return false; } if (ProgressStore.Current == null) { reason = ModLocalization.Text("Kein aktiver Charakterfortschritt gefunden.", "No active character progress was found."); return false; } if (GameData.InCharSelect || GameData.VendorWindowOpen || GameData.AuctionWindowOpen || GameData.Trading) { reason = ModLocalization.Text("Während eines anderen Inventarvorgangs kann nicht sortiert werden.", "Sorting is unavailable during another inventory transaction."); return false; } if ((Object)(object)GameData.ItemOnCursor != (Object)null && (Object)(object)GameData.ItemOnCursor != (Object)(object)inventory.Empty) { reason = ModLocalization.Text("Lege zuerst das Item am Mauszeiger ab.", "Place the item on your cursor first."); return false; } if (inventory.StoredSlots.Any((ItemIcon slot) => (Object)(object)slot != (Object)null && slot.dragging)) { reason = ModLocalization.Text("Beende zuerst das Ziehen eines Items.", "Finish dragging the item first."); return false; } reason = string.Empty; return true; } private static bool IsSortableSlot(Inventory inventory, ItemIcon slot) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)slot != (Object)null && (int)slot.ThisSlotType == 0 && !slot.TrashSlot && !slot.VendorSlot && !slot.LootSlot && !slot.BankSlot && !slot.DisplayOnly && !slot.NotInInventory && !slot.CosmeticOnly && !slot.NoStackables && (inventory.CosmeticSlots == null || !inventory.CosmeticSlots.Contains(slot))) { return !InventoryExpansionController.IsReservedUnresolvedSlot(slot); } return false; } private static List<HotkeySnapshot> CaptureHotkeys(List<ItemIcon> targets) { List<HotkeySnapshot> list = new List<HotkeySnapshot>(); if (GameData.GM?.HKManager?.AllHotkeys == null) { return list; } HashSet<ItemIcon> hashSet = new HashSet<ItemIcon>(targets); foreach (Hotkeys allHotkey in GameData.GM.HKManager.AllHotkeys) { if ((Object)(object)allHotkey?.AssignedItem != (Object)null && hashSet.Contains(allHotkey.AssignedItem)) { list.Add(new HotkeySnapshot(allHotkey, allHotkey.AssignedItem, allHotkey.InvSlotIndex)); } } return list; } private static List<SortEntry> BuildEntries(List<SlotSnapshot> snapshot, List<HotkeySnapshot> hotkeys, Item empty, bool mergeStacks) { List<SortEntry> list = new List<SortEntry>(); Dictionary<ItemIcon, List<Hotkeys>> dictionary = (from binding in hotkeys group binding by binding.OriginalSlot).ToDictionary((IGrouping<ItemIcon, HotkeySnapshot> group) => group.Key, (IGrouping<ItemIcon, HotkeySnapshot> group) => group.Select((HotkeySnapshot binding) => binding.Hotkey).ToList()); Dictionary<Item, StackGroup> dictionary2 = new Dictionary<Item, StackGroup>(ReferenceComparer<Item>.Instance); Dictionary<Item, int> dictionary3 = new Dictionary<Item, int>(ReferenceComparer<Item>.Instance); foreach (SlotSnapshot item in snapshot) { if (!((Object)(object)item.Item == (Object)null) && !((Object)(object)item.Item == (Object)(object)empty) && item.Item.Stackable) { List<Hotkeys> value; int num = (dictionary.TryGetValue(item.Slot, out value) ? value.Count : 0); dictionary3.TryGetValue(item.Item, out var value2); dictionary3[item.Item] = value2 + num; } } foreach (SlotSnapshot item2 in snapshot) { if ((Object)(object)item2.Item == (Object)null || (Object)(object)item2.Item == (Object)(object)empty) { continue; } List<Hotkeys> value3; List<Hotkeys> list2 = (dictionary.TryGetValue(item2.Slot, out value3) ? value3 : new List<Hotkeys>()); int value4; bool flag = !dictionary3.TryGetValue(item2.Item, out value4) || value4 <= 1; if (mergeStacks && item2.Item.Stackable && flag) { if (!dictionary2.TryGetValue(item2.Item, out var value5)) { value5 = new StackGroup(item2.Item, item2.OriginalIndex); dictionary2.Add(item2.Item, value5); } value5.Total += Math.Max(1L, item2.Quantity); value5.Hotkeys.AddRange(list2); } else { list.Add(new SortEntry(item2.Item, item2.Quantity, item2.OriginalIndex, list2)); } } foreach (StackGroup value6 in dictionary2.Values) { long num2 = value6.Total; bool flag2 = true; while (num2 > 0) { int num3 = (int)((num2 > int.MaxValue) ? int.MaxValue : num2); list.Add(new SortEntry(value6.Item, num3, value6.OriginalIndex, flag2 ? value6.Hotkeys : new List<Hotkeys>())); num2 -= num3; flag2 = false; } } return list; } private static int CompareEntries(SortEntry left, SortEntry right, InventorySortMode mode, bool descending) { ComparisonSlot left2 = new ComparisonSlot(left.Item, left.Quantity); ComparisonSlot right2 = new ComparisonSlot(right.Item, right.Quantity); int num = CompareValues(left2, right2, mode); if (descending) { num = -num; } if (num != 0) { return num; } int num2 = CultureInfo.InvariantCulture.CompareInfo.Compare(left.Item.ItemName ?? string.Empty, right.Item.ItemName ?? string.Empty, CompareOptions.IgnoreCase); if (num2 != 0) { return num2; } int num3 = string.Compare(((BaseScriptableObject)left.Item).Id, ((BaseScriptableObject)right.Item).Id, StringComparison.Ordinal); if (num3 == 0) { return left.OriginalIndex.CompareTo(right.OriginalIndex); } return num3; } private static int CompareValues(ComparisonSlot left, ComparisonSlot right, InventorySortMode mode) { return mode switch { InventorySortMode.Name => CultureInfo.InvariantCulture.CompareInfo.Compare(left.Item.ItemName ?? string.Empty, right.Item.ItemName ?? string.Empty, CompareOptions.IgnoreCase), InventorySortMode.Type => CompareType(left.Item, right.Item), InventorySortMode.Level => left.Item.ItemLevel.CompareTo(right.Item.ItemLevel), InventorySortMode.Value => left.Item.ItemValue.CompareTo(right.Item.ItemValue), InventorySortMode.Quantity => ((!left.Item.Stackable) ? 1 : left.Quantity).CompareTo((!right.Item.Stackable) ? 1 : right.Quantity), _ => 0, }; } private static int CompareType(Item left, Item right) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected I4, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected I4, but got Unknown int num = GetTypeRank(left).CompareTo(GetTypeRank(right)); if (num == 0) { return ((int)left.RequiredSlot).CompareTo((int)right.RequiredSlot); } return num; } private static int GetTypeRank(Item item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0027: 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) if ((int)item.RequiredSlot == 13 || (int)item.RequiredSlot == 14 || (int)item.RequiredSlot == 15 || item.WeaponDmg != 0 || (int)item.ThisWeaponType != 0) { return 0; } if ((int)item.RequiredSlot != 0) { return 1; } if ((Object)(object)item.ItemEffectOnClick != (Object)null || (Object)(object)item.ItemSkillUse != (Object)null || item.Disposable) { return 2; } if (item.Template || item.FuelSource || item.Mining > 0 || item.FurnitureSet) { return 3; } if ((Object)(object)item.AssignQuestOnRead != (Object)null || (Object)(object)item.CompleteOnRead != (Object)null || !string.IsNullOrWhiteSpace(item.BookTitle)) { return 4; } return 5; } private static int GetQuantityKey(ItemIcon slot) { if (!((Object)(object)slot.MyItem != (Object)null) || !slot.MyItem.Stackable) { return 1; } return slot.Quantity; } private static void RestoreSnapshot(Inventory inventory, List<SlotSnapshot> snapshot, List<HotkeySnapshot> hotkeys) { foreach (SlotSnapshot item in snapshot) { item.Slot.MyItem = item.Item; item.Slot.Quantity = item.Quantity; item.Slot.assignedHotkey = null; item.Slot.UpdateSlotImage(); } foreach (HotkeySnapshot hotkey in hotkeys) { if (!((Object)(object)hotkey.Hotkey == (Object)null) && !((Object)(object)hotkey.OriginalSlot == (Object)null)) { hotkey.Hotkey.AssignItemFrominv(hotkey.OriginalSlot); hotkey.Hotkey.InvSlotIndex = hotkey.OriginalInvSlotIndex; hotkey.Hotkey.UpdateImg(); hotkey.OriginalSlot.assignedHotkey = hotkey.Hotkey; } } inventory.UpdatePlayerInventory(); } } [HarmonyPatch(typeof(Inventory), "UpdatePlayerInventory")] internal static class InventoryToolsRefreshPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Inventory __instance) { if ((Object)(object)__instance != (Object)null && __instance.isPlayer) { InventoryExpansionController.RefreshLayout(); } } } internal enum ModLanguageMode { Auto, German, English } internal static class ModLocalization { private static readonly string[] StableModes = new string[3] { "Auto", "German", "English" }; internal static bool IsGerman { get { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 switch (CurrentMode) { case ModLanguageMode.Auto: if ((int)Application.systemLanguage != 15) { return string.Equals(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, "de", StringComparison.OrdinalIgnoreCase); } return true; default: return false; case ModLanguageMode.German: return true; } } } internal static ModLanguageMode CurrentMode { get { if (!TryParseMode(TaschenhaendlerPlugin.Instance?.LanguageMode?.Value, out var mode)) { return ModLanguageMode.Auto; } return mode; } } internal static int CurrentModeIndex => (int)CurrentMode; internal static IReadOnlyList<string> LanguageOptionLabels { get { if (IsGerman) { return new string[3] { "Auto", "Deutsch", "Englisch" }; } return new string[3] { "Auto", "German", "English" }; } } internal static string MerchantRole => Text("Taschen-Händlerin", "Bag Merchant"); internal static string MessagePrefix => Text("Taschen-Händlerin", "Bag Merchant"); internal static string Text(string german, string english) { if (!IsGerman) { return english; } return german; } internal static string Format(string german, string english, params object[] arguments) { return string.Format(Text(german, english), arguments); } internal static void SetModeByIndex(int index) { index = Mathf.Clamp(index, 0, StableModes.Length - 1); if (TaschenhaendlerPlugin.Instance?.LanguageMode != null) { TaschenhaendlerPlugin.Instance.LanguageMode.Value = StableModes[index]; } } internal static bool TryParseMode(string value, out ModLanguageMode mode) { if (string.Equals(value, "German", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "Deutsch", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "de", StringComparison.OrdinalIgnoreCase)) { mode = ModLanguageMode.German; return true; } if (string.Equals(value, "English", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "Englisch", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "en", StringComparison.OrdinalIgnoreCase)) { mode = ModLanguageMode.English; return true; } if (string.IsNullOrWhiteSpace(value) || string.Equals(value, "Auto", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "Automatic", StringComparison.OrdinalIgnoreCase) || string.Equals(value, "Automatisch", StringComparison.OrdinalIgnoreCase)) { mode = ModLanguageMode.Auto; return true; } mode = ModLanguageMode.Auto; return false; } } internal sealed class BagVendorMarker : MonoBehaviour { internal string SceneName; internal Vector3 AnchorPosition; internal int SourceVendorInstanceId; internal int NameIndex; private IEnumerator Start() { yield return null; MerchantController.RefreshVendorPresentation(this); } } internal static class MerchantController { private sealed class ProgressWriteException : Exception { } private static readonly string[] GermanVendorNames = new string[12] { "Mara – Taschen-Händlerin", "Borin – Gepäckmeister", "Lina – Hüterin der Taschen", "Taro – Taschen-Händler", "Selma – Reiseausstatterin", "Oren – Gepäckhändler", "Nira – Taschen-Händlerin", "Fenn – Meister der Beutel", "Kara – Reisehändlerin", "Jorin – Taschen-Händler", "Alva – Gepäckmeisterin", "Rumo – Reiseausstatter" }; private static readonly string[] EnglishVendorNames = new string[12] { "Mara – Bag Merchant", "Borin – Luggage Master", "Lina – Keeper of Bags", "Taro – Bag Merchant", "Selma – Travel Outfitter", "Oren – Luggage Merchant", "Nira – Bag Merchant", "Fenn – Master of Pouches", "Kara – Travel Merchant", "Jorin – Bag Merchant", "Alva – Luggage Expert", "Rumo – Travel Outfitter" }; private static TaschenhaendlerPlugin _plugin; private static readonly HashSet<int> PendingSources = new HashSet<int>(); internal static Item ExpansionItem { get; private set; } internal static void Initialize(TaschenhaendlerPlugin plugin) { _plugin = plugin; PendingSources.Clear(); } internal static void Shutdown() { PendingSources.Clear(); _plugin = null; } internal static void OnSceneLoaded(Scene scene) { PendingSources.Clear(); } internal static void OnSceneUnloaded(Scene scene) { PendingSources.Clear(); } internal static void RegisterExpansionItem(ItemDatabase database) { //IL_0153: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)database == (Object)null) { return; } try { Dictionary<string, Item> dictionary = Traverse.Create((object)database).Field("itemDict").GetValue<Dictionary<string, Item>>(); if (dictionary != null && dictionary.TryGetValue("CBRA_TASCHENHAENDLER_INVENTARERWEITERUNG_V1", out var value) && (Object)(object)value != (Object)null) { ExpansionItem = value; RefreshOffer(); RebindExistingExpansionItems(); InventoryExpansionController.RestorePendingExpansionItems(); return; } Item value2 = null; dictionary?.TryGetValue("315843", out value2); value2 = value2 ?? database.ItemDB?.FirstOrDefault((Func<Item, bool>)((Item val2) => (Object)(object)val2 != (Object)null && (Object)(object)val2.ItemIcon != (Object)null)); value2 = value2 ?? database.ItemDBList?.FirstOrDefault((Func<Item, bool>)((Item val2) => (Object)(object)val2 != (Object)null && (Object)(object)val2.ItemIcon != (Object)null)); if ((Object)(object)value2 == (Object)null) { TaschenhaendlerPlugin.ModLog.LogError((object)"Inventarerweiterungsitem konnte nicht erzeugt werden: Keine Item-Vorlage gefunden."); return; } Item item = Object.Instantiate<Item>(value2); ((Object)item).name = "CBra Inventory Expansion"; ((BaseScriptableObject)item).Id = "CBRA_TASCHENHAENDLER_INVENTARERWEITERUNG_V1"; item.ItemName = ModLocalization.Text("Inventarerweiterung (+10 Plätze)", "Inventory Expansion (+10 slots)"); item.ItemLevel = 1; item.RequiredSlot = (SlotType)0; item.Classes = new List<Class> { GameData.ClassDB?.Paladin, GameData.ClassDB?.Arcanist, GameData.ClassDB?.Duelist, GameData.ClassDB?.Druid, GameData.ClassDB?.Stormcaller, GameData.ClassDB?.Reaver }.Where((Class characterClass) => (Object)(object)characterClass != (Object)null).Distinct().ToList(); item.Stackable = true; item.Disposable = true; item.Unique = false; item.PlayerCannotSe