Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of InputTweaks v1.1.2
InputTweaks.dll
Decompiled a year agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("InputTweaks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Riintouge")] [assembly: AssemblyProduct("InputTweaks")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("cbd7a961-cdeb-4db5-af2c-ada574c3197f")] [assembly: AssemblyFileVersion("1.1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.1.2.0")] namespace InputTweaks; [BepInPlugin("com.riintouge.inputtweaks", "Input Tweaks", "1.1.2")] [BepInProcess("valheim.exe")] public class InputTweaks : BaseUnityPlugin { [HarmonyPatch(typeof(ArmorStand))] public class ArmorStandPatch { public static bool CanAttach(ArmorStand armorStand, ArmorStandSlot slot, ItemData item) { return Traverse.Create((object)armorStand).Method("CanAttach", new Type[2] { typeof(ArmorStandSlot), typeof(ItemData) }, (object[])null).GetValue<bool>(new object[2] { slot, item }); } public static void RPC_DropItem(ArmorStand armorStand, int index) { Traverse.Create((object)armorStand).Field("m_nview").GetValue<ZNetView>() .InvokeRPC(ZNetView.Everybody, "RPC_DropItem", new object[1] { index }); } } internal class ButtonRightClickComponent : MonoBehaviour { public ButtonClickedEvent OnRightClick = new ButtonClickedEvent(); } [HarmonyPatch(typeof(Button))] private class ButtonPatch { [HarmonyPatch("OnPointerClick")] [HarmonyPostfix] private static void OnPointerClickPostfix(Button __instance, PointerEventData eventData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)eventData.button == 1 && ((UIBehaviour)__instance).IsActive() && ((Selectable)__instance).IsInteractable()) { ButtonRightClickComponent component = ((Component)__instance).GetComponent<ButtonRightClickComponent>(); if ((Object)(object)component != (Object)null) { Common.DebugMessage("RCLK: Activating RightClickButtonComponent"); ((UnityEvent)component.OnRightClick).Invoke(); } } } } [HarmonyPatch(typeof(Hud))] public class HudPatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(Hud __instance) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_001b: Unknown result type (might be due to invalid IL or missing references) KeyCode value = ToggleHudKey.Value; if ((Object)(object)Player.m_localPlayer != (Object)null && (int)value != 0 && ZInput.GetKeyDown(value, true)) { __instance.m_userHidden = !__instance.m_userHidden; } } } [HarmonyPatch(typeof(Inventory))] public class InventoryPatch { public static void Changed(Inventory inv) { Traverse.Create((object)inv).Method("Changed", Array.Empty<object>()).GetValue(); } } [HarmonyPatch(typeof(InventoryGrid))] public class InventoryGridPatch { public static Vector2i GetButtonPos(InventoryGrid grid, UIInputHandler element) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return GetButtonPos(grid, ((Component)element).gameObject); } public static Vector2i GetButtonPos(InventoryGrid grid, GameObject go) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) return Traverse.Create((object)grid).Method("GetButtonPos", new Type[1] { typeof(GameObject) }, (object[])null).GetValue<Vector2i>(new object[1] { go }); } public static void OnRightClick(InventoryGrid grid, UIInputHandler element) { Traverse.Create((object)grid).Method("OnRightClick", new Type[1] { typeof(UIInputHandler) }, (object[])null).GetValue(new object[1] { element }); } public static int Width(InventoryGrid grid) { return Traverse.Create((object)grid).Field("m_width").GetValue<int>(); } [HarmonyPatch("OnLeftClick")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> OnLeftClickTranspiler(IEnumerable<CodeInstruction> instructionsIn) { if (!InitialSwapMoveAndSplit) { return instructionsIn; } return Common.SwapShiftAndCtrl(instructionsIn); } } [HarmonyPatch(typeof(InventoryGui))] public class InventoryGuiPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<InventoryButton, bool> <>9__14_0; public static Func<InventoryButton, bool> <>9__14_1; public static Action<InventoryButton> <>9__16_0; public static Action<InventoryButton> <>9__16_1; public static UnityAction <>9__36_0; public static Func<bool> <>9__41_1; public static Func<bool> <>9__41_0; public static Func<bool> <>9__42_0; internal bool <GetHoveredButton>b__14_0(InventoryButton x) { return Common.IsCursorOver(((Component)x.inputHandler).gameObject); } internal bool <GetHoveredButton>b__14_1(InventoryButton x) { return Common.IsCursorOver(((Component)x.inputHandler).gameObject); } internal void <EndDrag>b__16_0(InventoryButton x) { x.considerForDrag = false; } internal void <EndDrag>b__16_1(InventoryButton x) { x.considerForDrag = false; } internal void <AwakePostfix>b__36_0() { if (!IsEnabled.Value) { return; } if (!AllowRightClickDrop.Value) { VanillaDragState.ClearDrag(); return; } VanillaDragState vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid && PlayerDropFromInv(vanillaDragState.dragInventory, vanillaDragState.dragItem, 1) && vanillaDragState.Decrement()) { vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid) { vanillaDragState.UpdateTooltip(); } else { VanillaDragState.ClearDrag(); } } } internal bool <OnRightClickItemPrefix>b__41_1() { return Common.CheckModifier(ModifierKeyEnum.Move); } internal bool <OnRightClickItemPrefix>b__41_0() { return Common.CheckModifier(ModifierKeyEnum.Split); } internal bool <OnSelectedItemPrefix>b__42_0() { return Common.CheckModifier(ModifierKeyEnum.Split); } } private static bool IgnoreUpdateItemDragRightMouseReset = false; private static bool SkipNextUpdate = false; private static bool SingleDropCoolDown = false; private static AbstractInventoryGuiCursorContext MouseContext = null; private static VanillaDragState CurrentDragState = new VanillaDragState(); private static List<InventoryButton> PlayerButtons = new List<InventoryButton>(); private static bool ForceContainerButtonUpdate = false; private static List<InventoryButton> ContainerButtons = new List<InventoryButton>(); private static InventoryButton CurrentButton = null; private static Component LastWorldComponent = null; private static Component CurrentWorldComponent = null; private static GameObject WorldInteractionPreviewDragObject = null; private static void CollectInventoryButtons(InventoryGrid playerGrid, InventoryGrid containerGrid) { int num; if (PlayerButtons.Count == 0) { num = ((ContainerButtons.Count == 0) ? 1 : 0); if (num != 0) { Common.DebugMessage("INFO: Attempting to index PlayerButtons"); CollectInventoryButtons(playerGrid, PlayerButtons); Common.DebugMessage($"INFO: Indexed {PlayerButtons.Count} player buttons"); } } else { num = 0; } if (num != 0 || ForceContainerButtonUpdate) { Common.DebugMessage("INFO: Attempting to index ContainerButtons"); CollectInventoryButtons(containerGrid, ContainerButtons); Common.DebugMessage($"INFO: Indexed {ContainerButtons.Count} container buttons"); ForceContainerButtonUpdate = false; } } private static void CollectInventoryButtons(InventoryGrid grid, List<InventoryButton> buttons) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0061: 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_0072: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) buttons.Clear(); Inventory val = ((grid != null) ? grid.GetInventory() : null); if (val == null) { return; } int width = val.GetWidth(); int height = val.GetHeight(); if (width <= 0 || height <= 0) { return; } ListExtra.Resize<InventoryButton>(buttons, width * height, (InventoryButton)null); UIInputHandler[] componentsInChildren = ((Component)grid).GetComponentsInChildren<UIInputHandler>(); foreach (UIInputHandler val2 in componentsInChildren) { Vector2i buttonPos = InventoryGridPatch.GetButtonPos(grid, val2); if (buttonPos.x != -1 && buttonPos.y != -1) { int index = buttonPos.x + buttonPos.y * width; buttons[index] = new InventoryButton { inputHandler = val2, grid = grid, gridPos = buttonPos, considerForDrag = true, representsExistingItem = (val.GetItemAt(buttonPos.x, buttonPos.y) != null) }; } } } internal static InventoryButton GetHoveredButton(InventoryGrid playerGrid, InventoryGrid containerGrid) { if ((Object)(object)playerGrid != (Object)null && ((Component)playerGrid).gameObject.activeInHierarchy && Common.IsCursorOver(((Component)playerGrid).gameObject)) { return PlayerButtons.Where((InventoryButton x) => Common.IsCursorOver(((Component)x.inputHandler).gameObject)).FirstOrDefault(); } if ((Object)(object)containerGrid != (Object)null && ((Component)containerGrid).gameObject.activeInHierarchy && Common.IsCursorOver(((Component)containerGrid).gameObject)) { return ContainerButtons.Where((InventoryButton x) => Common.IsCursorOver(((Component)x.inputHandler).gameObject)).FirstOrDefault(); } return null; } private static void UpdateContext(InventoryGrid playerGrid, InventoryGrid containerGrid) { if (MouseContext != null) { AbstractInventoryGuiCursorContext.State state = MouseContext.Think(CurrentDragState); if ((uint)(state - 2) <= 1u && FrameInputs.Current.None) { EndDrag(clearContext: true); } } } private static void EndDrag(bool clearContext) { PlayerButtons.ForEach(delegate(InventoryButton x) { x.considerForDrag = false; }); ContainerButtons.ForEach(delegate(InventoryButton x) { x.considerForDrag = false; }); if (clearContext) { MouseContext?.End(); MouseContext = null; } } public static void UpdateSingleDrop(InventoryGrid m_playerGrid, InventoryGrid m_containerGrid) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (MouseContext != null || CurrentDragState.isValid || FrameInputs.Current.Any) { return; } if (!ZInput.GetKey(SingleDropKey.Value, true)) { SingleDropCoolDown = false; } else if (!SingleDropCoolDown) { SingleDropCoolDown = true; InventoryButton hoveredButton = GetHoveredButton(m_playerGrid, m_containerGrid); if (hoveredButton != null) { ItemData curItem = hoveredButton.curItem; PlayerDropFromInv(hoveredButton.grid.GetInventory(), curItem, (!Common.CheckModifier(StackDropModifier.Value)) ? 1 : curItem.m_stack); } } } private static bool PlayerDropFromInv(Inventory inv, ItemData item, int count) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (MouseContext == null && ((Humanoid)Player.m_localPlayer).DropItem(inv, item, count)) { Traverse.Create((object)InventoryGui.instance).Field("m_moveItemEffects").GetValue<EffectList>() .Create(((Component)InventoryGui.instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1); return true; } return false; } private static void UpdateMouseWheel(InventoryGui inventoryGui, InventoryGrid playerGrid, InventoryGrid containerGrid) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) if (MouseContext != null || CurrentDragState.isValid || FrameInputs.Current.Any) { return; } Player localPlayer = Player.m_localPlayer; float mouseScrollWheel = ZInput.GetMouseScrollWheel(); if ((Object)(object)localPlayer == (Object)null || mouseScrollWheel == 0f) { return; } if (((Component)inventoryGui.m_splitPanel).gameObject.activeInHierarchy) { Transform obj = inventoryGui.m_splitPanel.Find("win_bkg"); if (Common.IsCursorOver((RectTransform)(object)((obj is RectTransform) ? obj : null))) { Slider splitSlider = inventoryGui.m_splitSlider; splitSlider.value = Mathf.Clamp(splitSlider.value + ((mouseScrollWheel > 0f) ? 1f : (-1f)), splitSlider.minValue, splitSlider.maxValue); Traverse.Create((object)inventoryGui).Method("OnSplitSliderChanged", new Type[1] { typeof(float) }, (object[])null).GetValue(new object[1] { Mathf.Clamp(splitSlider.value, splitSlider.minValue, splitSlider.maxValue) }); } } else { if (CurrentButton == null) { return; } Inventory inventory = CurrentButton.grid.GetInventory(); Vector2i gridPos = CurrentButton.gridPos; ItemData itemAt = inventory.GetItemAt(gridPos.x, gridPos.y); if (itemAt == null || itemAt.m_stack < 1) { return; } bool flag = (Object)(object)CurrentButton.grid == (Object)(object)containerGrid; WheelActionEnum value = (flag ? ContainerWheelAction : PlayerWheelAction).Value; if (value != 0) { bool pull = value == WheelActionEnum.PullUpPushDown == mouseScrollWheel > 0f; if (flag) { MoveOne(localPlayer, pull, itemAt, containerGrid, playerGrid); } else if (inventoryGui.IsContainerOpen()) { MoveOne(localPlayer, pull, itemAt, playerGrid, containerGrid); } else { MoveOne(localPlayer, pull, itemAt, playerGrid, null); } } } } private static void MoveOne(Player player, bool pull, ItemData item, InventoryGrid owningGrid, InventoryGrid otherGrid) { //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)otherGrid == (Object)(object)owningGrid) { otherGrid = null; } Inventory inventory = owningGrid.GetInventory(); Inventory val = ((otherGrid != null) ? otherGrid.GetInventory() : null); if (pull) { if (item.m_shared.m_maxStackSize == 1) { if (val == null) { Common.DebugMessage("PULL: Doesn't make sense"); return; } if (!inventory.HaveEmptySlot()) { Common.DebugMessage("PULL: No empty slots"); return; } } else if (item.m_stack == item.m_shared.m_maxStackSize) { if (val == null) { Common.DebugMessage("PULL: Doesn't make sense"); return; } ItemData val2 = Common.FindLargestPartialStack(item, owningGrid); if (val2 == null) { if (!inventory.HaveEmptySlot()) { Common.DebugMessage("PULL: No space"); return; } } else { item = val2; } } if (val != null) { ItemData val3 = (ItemData)((item.m_shared.m_maxStackSize > 1) ? ((object)Common.EquivalentStackables(item, otherGrid).FirstOrDefault()) : ((object)Common.FindFirstSimilarItemInInventory(item, val))); if (val3 == null && item.m_stack == item.m_shared.m_maxStackSize && item.m_shared.m_maxStackSize > 1) { ItemData val4 = Common.FindSmallestPartialStack(item, otherGrid); if (val4 != null && inventory.AddItem(item.m_dropPrefab, 1)) { Common.DebugMessage("PULL: One item"); val.RemoveOneItem(val4); return; } } else if (val3 == null || val3.m_stack < 1) { Common.DebugMessage("PULL: No similar item"); } else { if (val3 == item) { Common.DebugMessage("PULL: Found self"); return; } if (val3.m_shared.m_maxStackSize == 1) { Common.DebugMessage("PULL: Single"); inventory.MoveItemToThis(val, val3); return; } if (val.RemoveOneItem(val3)) { Common.DebugMessage("PULL: One item"); ItemData obj = item; obj.m_stack++; InventoryPatch.Changed(inventory); return; } } } ItemData val5 = Common.EquivalentStackables(item, owningGrid).FirstOrDefault(); if (val5 == null || val5.m_stack < 1) { Common.DebugMessage("PULL: No similar item"); } else if (val5 == item) { Common.DebugMessage("PULL: Found self"); } else if (inventory.RemoveOneItem(val5)) { Common.DebugMessage("PULL: One item"); ItemData obj2 = item; obj2.m_stack++; InventoryPatch.Changed(val); } return; } if (val != null) { if (item.m_stack == 1) { Common.DebugMessage("PUSH: Single or last"); ((Humanoid)player).RemoveEquipAction(item); ((Humanoid)player).UnequipItem(item, true); val.MoveItemToThis(inventory, item); UITooltip.HideTooltip(); return; } if (item.m_stack == item.m_shared.m_maxStackSize) { item = Common.FindSmallestPartialStack(item, owningGrid) ?? item; } if (val.AddItem(item.m_dropPrefab, 1)) { Common.DebugMessage("PUSH: One item"); inventory.RemoveOneItem(item); } return; } ItemData val6 = Common.FindLargestPartialStack(item, owningGrid); if (val6 != null) { Common.DebugMessage("PUSH: One item to sibling"); val6.m_stack++; InventoryPatch.Changed(val); inventory.RemoveOneItem(item); if (item.m_stack < 1) { UITooltip.HideTooltip(); } } else if (item.m_stack == 1) { Common.DebugMessage("PUSH: Doesn't make sense"); } else { Vector2i val7 = FindEmptySlot(inventory, TopFirst(inventory, item)); if (val7.x < 0 || val7.y < 0) { Common.DebugMessage("PUSH: No empty slot"); return; } Common.DebugMessage("PUSH: One item to empty slot"); AddItem(inventory, item, 1, val7.x, val7.y); } } private static void UpdateWorldInteractionDragPreview(InventoryGui inventoryGui, Button dropButton) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) LastWorldComponent = CurrentWorldComponent; CurrentWorldComponent = null; VanillaDragState vanillaDragState = new VanillaDragState(); if ((Object)(object)vanillaDragState.dragObject != (Object)null && (Object)(object)vanillaDragState.dragObject != (Object)(object)WorldInteractionPreviewDragObject) { return; } Transform transform = ((Component)dropButton).transform; Transform transform2 = ((Component)transform.parent).transform; for (int i = 0; i < transform2.childCount; i++) { Transform child = transform2.GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if ((Object)(object)val != (Object)(object)transform && ((Component)val).gameObject.activeInHierarchy && Common.IsCursorOver(val)) { ClearWorldInteractionDragPreview(); return; } } CurrentWorldComponent = RaycastComponentForWorldInteraction(out var hit); if ((Object)(object)CurrentWorldComponent != (Object)(object)LastWorldComponent) { VanillaDragState.ClearDrag(); } string hoverPrefabName = GetHoverPrefabName(CurrentWorldComponent, hit); if (hoverPrefabName == null) { ClearWorldInteractionDragPreview(); return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hoverPrefabName); ItemData val2 = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData); if (val2 != null) { SetWorldInteractionDragPreview(inventoryGui, val2); } else { ClearWorldInteractionDragPreview(); } } private static Component RaycastComponentForWorldInteraction(out RaycastHit hit) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Ray val = ((Component)GameCamera.instance).GetComponent<Camera>().ScreenPointToRay(Input.mousePosition); Player localPlayer = Player.m_localPlayer; int value = Traverse.Create((object)localPlayer).Field("m_interactMask").GetValue<int>(); if (!Physics.Raycast(val, ref hit, 50f, value & -513)) { return null; } if (Vector3.Distance(((RaycastHit)(ref hit)).point, ((Character)localPlayer).m_eye.position) > localPlayer.m_maxInteractDistance) { return null; } return ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Component>(); } private static string GetHoverPrefabName(Component component, RaycastHit hit) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)component == (Object)null) { return null; } if (InteractWithArmorStands.Value) { ArmorStand componentInParent = component.GetComponentInParent<ArmorStand>(); if ((Object)(object)componentInParent != (Object)null) { ItemType item = ItemTypeForArmorStandPoint(hit); for (int i = 0; i < componentInParent.m_slots.Count; i++) { ArmorStandSlot val = componentInParent.m_slots[i]; if (val.m_supportedTypes.Count == 0 || val.m_supportedTypes.Contains(item)) { if (!componentInParent.HaveAttachment(i)) { break; } return Traverse.Create((object)componentInParent).Field("m_nview").GetValue<ZNetView>() .GetZDO() .GetString(i + "_item", ""); } } return null; } } if (InteractWithItemStands.Value) { ItemStand componentInParent2 = component.GetComponentInParent<ItemStand>(); if ((Object)(object)componentInParent2 != (Object)null) { return Traverse.Create((object)componentInParent2).Field("m_visualName").GetValue<string>(); } } if (InteractWithWorldItems.Value) { ItemDrop componentInParent3 = component.GetComponentInParent<ItemDrop>(); if ((Object)(object)componentInParent3 != (Object)null) { return ((Object)componentInParent3.m_itemData.m_dropPrefab).name; } } return null; } private static void SetWorldInteractionDragPreview(InventoryGui inventoryGui, ItemData item) { VanillaDragState vanillaDragState = new VanillaDragState(); if ((Object)(object)vanillaDragState.dragObject != (Object)null && (Object)(object)vanillaDragState.dragObject == (Object)(object)WorldInteractionPreviewDragObject) { if (!Common.ItemsAreSimilarButDistinct(vanillaDragState.dragItem, item, considerQuality: true)) { Traverse obj = Traverse.Create((object)inventoryGui); obj.Field("m_dragInventory").SetValue((object)null); obj.Field("m_dragItem").SetValue((object)item); obj.Field("m_dragAmount").SetValue((object)0); } } else { SetupDragItem(inventoryGui, item, null, 0); WorldInteractionPreviewDragObject = new VanillaDragState().dragObject; } } private static void ClearWorldInteractionDragPreview() { if ((Object)(object)WorldInteractionPreviewDragObject != (Object)null && (Object)(object)new VanillaDragState().dragObject == (Object)(object)WorldInteractionPreviewDragObject) { WorldInteractionPreviewDragObject = null; VanillaDragState.ClearDrag(); } } private static void InteractWithArmorStand(RaycastHit hit, ArmorStand armorStand) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; VanillaDragState vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid) { for (int i = 0; i < armorStand.m_slots.Count; i++) { ItemData dragItem = vanillaDragState.dragItem; ArmorStandSlot val = armorStand.m_slots[i]; if (armorStand.HaveAttachment(i)) { if (ArmorStandPatch.CanAttach(armorStand, val, dragItem)) { ArmorStandPatch.RPC_DropItem(armorStand, i); DoInteractAnimation(Player.m_localPlayer, ((Component)armorStand).gameObject); break; } } else if (val.m_switch.UseItem((Humanoid)(object)localPlayer, vanillaDragState.dragItem)) { VanillaDragState.ClearDrag(); DoInteractAnimation(Player.m_localPlayer, ((Component)armorStand).gameObject); break; } } return; } ItemType item = ItemTypeForArmorStandPoint(hit); for (int j = 0; j < armorStand.m_slots.Count; j++) { ArmorStandSlot val2 = armorStand.m_slots[j]; if (val2.m_supportedTypes.Count == 0 || val2.m_supportedTypes.Contains(item)) { if (armorStand.HaveAttachment(j)) { ArmorStandPatch.RPC_DropItem(armorStand, j); DoInteractAnimation(Player.m_localPlayer, ((Component)armorStand).gameObject); } break; } } } private static ItemType ItemTypeForArmorStandPoint(RaycastHit hit) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) Bounds bounds = ((RaycastHit)(ref hit)).collider.bounds; float num = ((Bounds)(ref bounds)).max.y - ((Bounds)(ref bounds)).min.y; float num2 = (((RaycastHit)(ref hit)).point.y - ((Bounds)(ref bounds)).min.y) / num; if (!(num2 >= 0.9375f)) { if (!(num2 >= 0.875f)) { if (!(num2 >= 0.75f)) { if (!(num2 >= 0.625f)) { if (!(num2 >= 0.5f)) { if (!(num2 >= 0.375f)) { return (ItemType)11; } return (ItemType)5; } return (ItemType)3; } return (ItemType)18; } return (ItemType)7; } return (ItemType)17; } return (ItemType)6; } private static void InteractWithContainer(Container container, InventoryGui inventoryGui) { Container value = Traverse.Create((object)inventoryGui).Field("m_currentContainer").GetValue<Container>(); Traverse.Create((object)inventoryGui).Method("CloseContainer", Array.Empty<object>()).GetValue(); if ((Object)(object)container != (Object)(object)value) { container.Interact((Humanoid)(object)Player.m_localPlayer, false, false); } DoInteractAnimation(Player.m_localPlayer, ((Component)container).gameObject); } private static void InteractWithItemStand(ItemStand itemStand) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (itemStand.HaveAttachment()) { if (itemStand.Interact((Humanoid)(object)localPlayer, false, false)) { DoInteractAnimation(Player.m_localPlayer, ((Component)itemStand).gameObject); } } else { if (!PrivateArea.CheckAccess(((Component)itemStand).transform.position, 0f, true, false)) { return; } VanillaDragState vanillaDragState = new VanillaDragState(); if (!vanillaDragState.isValid) { return; } itemStand.UseItem((Humanoid)(object)localPlayer, vanillaDragState.dragItem); ItemData value = Traverse.Create((object)itemStand).Field("m_queuedItem").GetValue<ItemData>(); if (vanillaDragState.dragItem == value && new VanillaDragState().Decrement()) { vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid) { vanillaDragState.UpdateTooltip(); } else { VanillaDragState.ClearDrag(); } DoInteractAnimation(Player.m_localPlayer, ((Component)itemStand).gameObject); } } } public static bool AddItem(Inventory inventory, ItemData item, int amount, int x, int y) { return Traverse.Create((object)inventory).Method("AddItem", new Type[4] { typeof(ItemData), typeof(int), typeof(int), typeof(int) }, (object[])null).GetValue<bool>(new object[4] { item, amount, x, y }); } public static void DoInteractAnimation(Player player, GameObject gameObject) { Traverse.Create((object)player).Method("DoInteractAnimation", new Type[1] { typeof(GameObject) }, (object[])null).GetValue(new object[1] { gameObject }); } public static Vector2i FindEmptySlot(Inventory inventory, bool topFirst) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) return Traverse.Create((object)inventory).Method("FindEmptySlot", new Type[1] { typeof(bool) }, (object[])null).GetValue<Vector2i>(new object[1] { topFirst }); } public static void SetupDragItem(InventoryGui instance, ItemData item, Inventory inventory, int amount) { Traverse.Create((object)instance).Method("SetupDragItem", new Type[3] { typeof(ItemData), typeof(Inventory), typeof(int) }, (object[])null).GetValue(new object[3] { item, inventory, amount }); } public static bool TopFirst(Inventory inventory, ItemData item) { return Traverse.Create((object)inventory).Method("TopFirst", new Type[1] { typeof(ItemData) }, (object[])null).GetValue<bool>(new object[1] { item }); } public static void UpdateCraftingPanel(InventoryGui instance, bool focusView = false) { Traverse.Create((object)instance).Method("UpdateCraftingPanel", new Type[1] { typeof(bool) }, (object[])null).GetValue(new object[1] { focusView }); } [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePostfix(Button ___m_dropButton) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown ButtonClickedEvent onRightClick = ((Component)___m_dropButton).gameObject.AddComponent<ButtonRightClickComponent>().OnRightClick; object obj = <>c.<>9__36_0; if (obj == null) { UnityAction val = delegate { if (IsEnabled.Value) { if (!AllowRightClickDrop.Value) { VanillaDragState.ClearDrag(); } else { VanillaDragState vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid && PlayerDropFromInv(vanillaDragState.dragInventory, vanillaDragState.dragItem, 1) && vanillaDragState.Decrement()) { vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid) { vanillaDragState.UpdateTooltip(); } else { VanillaDragState.ClearDrag(); } } } } }; <>c.<>9__36_0 = val; obj = (object)val; } ((UnityEvent)onRightClick).AddListener((UnityAction)obj); } [HarmonyPatch("CloseContainer")] [HarmonyPostfix] private static void CloseContainerPostfix() { MouseContext?.End(); EndDrag(clearContext: true); ContainerButtons.Clear(); } [HarmonyPatch("Hide")] [HarmonyPostfix] private static void HidePostfix() { MouseContext?.End(); VanillaDragState.ClearDrag(); EndDrag(clearContext: true); OnDestroyPrefix(); } [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroyPrefix() { IgnoreUpdateItemDragRightMouseReset = false; SkipNextUpdate = true; SingleDropCoolDown = false; MouseContext = null; PlayerButtons.Clear(); ContainerButtons.Clear(); CurrentButton = null; } [HarmonyPatch("OnDropOutside")] [HarmonyPrefix] private static bool OnDropOutsidePrefix(InventoryGui __instance) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) RaycastHit hit; Component val = RaycastComponentForWorldInteraction(out hit); if ((Object)(object)val == (Object)null) { return true; } if (InteractWithArmorStands.Value) { ArmorStand componentInParent = val.GetComponentInParent<ArmorStand>(); if ((Object)(object)componentInParent != (Object)null) { Common.DebugMessage("INTR: Hit ArmorStand"); InteractWithArmorStand(hit, componentInParent); return false; } } if (InteractWithContainers.Value) { Container componentInParent2 = val.GetComponentInParent<Container>(); if ((Object)(object)componentInParent2 != (Object)null) { Common.DebugMessage("INTR: Hit Container"); InteractWithContainer(componentInParent2, __instance); return false; } } if (InteractWithItemStands.Value) { ItemStand componentInParent3 = val.GetComponentInParent<ItemStand>(); if ((Object)(object)componentInParent3 != (Object)null) { Common.DebugMessage("INTR: Hit ItemStand"); InteractWithItemStand(componentInParent3); return false; } } if (InteractWithWorldItems.Value) { ItemDrop componentInParent4 = val.GetComponentInParent<ItemDrop>(); if ((Object)(object)componentInParent4 != (Object)null) { Common.DebugMessage("INTR: Hit ItemDrop"); Traverse.Create((object)Player.m_localPlayer).Method("Interact", new Type[3] { typeof(GameObject), typeof(bool), typeof(bool) }, (object[])null).GetValue(new object[3] { ((Component)componentInParent4).gameObject, false, false }); return false; } } return true; } [HarmonyPatch("OnRightClickItem")] [HarmonyPrefix] private static bool OnRightClickItemPrefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, InventoryGrid ___m_playerGrid, InventoryGrid ___m_containerGrid) { if (!IsEnabled.Value) { return true; } FrameInputs.Update(); if (VanillaDragState.IsValid()) { Common.DebugMessage("INFO: Start SingleSmearContext"); MouseContext = new SingleSmearContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons); return false; } if (item != null && item.m_shared.m_maxStackSize != 1) { if (Common.CheckModifier(ModifierKeyEnum.Move)) { int amount = (SplitRoundsUp.Value ? Mathf.CeilToInt((float)item.m_stack / 2f) : Mathf.Max(1, Mathf.FloorToInt((float)item.m_stack / 2f))); SetupDragItem(__instance, item, grid.GetInventory(), amount); Common.DebugMessage("INFO: Start BlockingMouseContext (RMB, split, immediate)"); MouseContext = new BlockingCursorContext(() => Common.CheckModifier(ModifierKeyEnum.Move)); return false; } if (Common.CheckModifier(ModifierKeyEnum.Split)) { if (item.m_stack == 1) { SetupDragItem(__instance, item, grid.GetInventory(), 1); } else { Traverse.Create((object)__instance).Method("ShowSplitDialog", new Type[2] { typeof(ItemData), typeof(Inventory) }, (object[])null).GetValue(new object[2] { item, grid.GetInventory() }); int num = (SplitRoundsUp.Value ? Mathf.CeilToInt((float)item.m_stack / 2f) : Mathf.FloorToInt((float)item.m_stack / 2f)); __instance.m_splitSlider.value = num; Traverse.Create((object)__instance).Method("OnSplitSliderChanged", new Type[1] { typeof(float) }, (object[])null).GetValue(new object[1] { num }); } Common.DebugMessage("INFO: Start BlockingMouseContext (RMB, split, dialog)"); MouseContext = new BlockingCursorContext(() => Common.CheckModifier(ModifierKeyEnum.Split)); return false; } } Common.DebugMessage("CNTX: Start BlockingMouseContext (RMB)"); MouseContext = new BlockingCursorContext(null); return true; } [HarmonyPatch("OnSelectedItem")] [HarmonyPrefix] private static bool OnSelectedItemPrefix(InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod, InventoryGrid ___m_playerGrid, InventoryGrid ___m_containerGrid, out Tuple<Inventory, Vector2i> __state) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) __state = null; if (!IsEnabled.Value) { return true; } FrameInputs.Update(); if (MouseContext != null) { if (MouseContext.CurrentState == AbstractInventoryGuiCursorContext.State.ActiveValid) { Common.DebugMessage($"CNTX: Selecting something for {MouseContext.GetType()}"); return true; } return false; } if (FrameInputs.Current.successiveClicks > 1) { if (AllowDoubleClickCollect.Value) { Common.DebugMessage("CNTX: Start MultiClickContext"); MouseContext = new MultiClickContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons); return true; } Common.DebugMessage("CNTX: Start BlockingMouseContext (LMB, collect)"); MouseContext = new BlockingCursorContext(null); return true; } VanillaDragState vanillaDragState = new VanillaDragState(); if (vanillaDragState.isValid) { __state = new Tuple<Inventory, Vector2i>(vanillaDragState.dragInventory, vanillaDragState.dragItem.m_gridPos); return true; } bool flag = Common.CheckModifier(ModifierKeyEnum.Move); bool flag2 = Common.CheckModifier(ModifierKeyEnum.Split); if (flag && flag2) { Common.DebugMessage("CNTX: Start FilteredStackMoveContext"); MouseContext = new FilteredStackMoveContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons); return false; } if (flag) { Common.DebugMessage("CNTX: Start StackMoveContext"); MouseContext = new StackMoveContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons); return false; } if (flag2) { Common.DebugMessage("CNTX: Start BlockingMouseContext (LMB, split)"); MouseContext = new BlockingCursorContext(() => Common.CheckModifier(ModifierKeyEnum.Split)); return true; } Common.DebugMessage("CNTX: Start BlockingMouseContext (LMB)"); MouseContext = new BlockingCursorContext(null); return true; } [HarmonyPatch("OnSelectedItem")] [HarmonyPostfix] private static void OnSelectedItemPostfix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod, InventoryGrid ___m_playerGrid, InventoryGrid ___m_containerGrid, ref Tuple<Inventory, Vector2i> __state) { //IL_011e: Unknown result type (might be due to invalid IL or missing references) if (!IsEnabled.Value) { return; } if (MouseContext is BlockingCursorContext) { if (Common.CheckModifier(ModifierKeyEnum.Split)) { if (!SplitRoundsUp.Value) { int num = Mathf.Max(1, Mathf.FloorToInt((float)item.m_stack / 2f)); __instance.m_splitSlider.value = num; Traverse.Create((object)__instance).Method("OnSplitSliderChanged", new Type[1] { typeof(float) }, (object[])null).GetValue(new object[1] { num }); } } else if (Common.CheckModifier(ModifierKeyEnum.None)) { Common.DebugMessage("CNTX: Start StackCollectContext"); MouseContext = new StackCollectContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons); } } else if (__state != null && !VanillaDragState.IsValid()) { ItemData val = GetHoveredButton(___m_playerGrid, ___m_containerGrid)?.curItem; if (val == null || val.m_stack <= 0) { Common.DebugMessage("CNTX: Cannot smear a null or empty item"); return; } Common.DebugMessage("CNTX: Start StackSmearContext"); MouseContext = new StackSmearContext(___m_playerGrid, PlayerButtons, ___m_containerGrid, ContainerButtons, __state.Item1, __state.Item2); } } [HarmonyPatch("SetupDragItem")] [HarmonyPrefix] private static bool SetupDragItemPrefix(ItemData item, Inventory inventory, int amount) { if (IgnoreUpdateItemDragRightMouseReset) { IgnoreUpdateItemDragRightMouseReset = false; return !FrameInputs.Current.Right; } return true; } [HarmonyPatch("Show")] [HarmonyPostfix] private static void ShowPostfix(Container container, int activeGroup = 1) { ForceContainerButtonUpdate = true; } [HarmonyPatch("ShowSplitDialog")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ShowSplitDialogTranspiler(IEnumerable<CodeInstruction> instructionsIn) { if (!InitialSwapMoveAndSplit) { return instructionsIn; } return Common.SwapShiftAndCtrl(instructionsIn); } [HarmonyPatch("Update")] [HarmonyPostfix] private static void UpdatePostfix(int ___m_hiddenFrames, InventoryGrid ___m_playerGrid, InventoryGrid ___m_containerGrid) { if (___m_hiddenFrames == 0 && !SkipNextUpdate) { CollectInventoryButtons(___m_playerGrid, ___m_containerGrid); } SkipNextUpdate = false; } [HarmonyPatch("UpdateItemDrag")] [HarmonyPrefix] private static void UpdateItemDragPrefix(InventoryGui __instance, InventoryGrid ___m_playerGrid, InventoryGrid ___m_containerGrid, Button ___m_dropButton) { if (IsEnabled.Value && (PlayerButtons.Count != 0 || ContainerButtons.Count != 0)) { FrameInputs.Update(); CurrentDragState = new VanillaDragState(); CurrentButton = GetHoveredButton(___m_playerGrid, ___m_containerGrid); UpdateContext(___m_playerGrid, ___m_containerGrid); UpdateSingleDrop(___m_playerGrid, ___m_containerGrid); UpdateMouseWheel(__instance, ___m_playerGrid, ___m_containerGrid); UpdateWorldInteractionDragPreview(__instance, ___m_dropButton); IgnoreUpdateItemDragRightMouseReset = CurrentDragState.isValid; } } } public enum WheelActionEnum { None, PullUpPushDown, PushUpPullDown } public enum ModifierKeyEnum { None, Alt, Command, Ctrl, Move, Shift, Split } public static ConfigEntry<bool> IsEnabled; public static ConfigEntry<bool> LoadOnStart; public static ConfigEntry<bool> DebugMessages; public static ConfigEntry<bool> SelectSwappedItem; public static ConfigEntry<bool> SplitRoundsUp; public static ConfigEntry<bool> SwapMoveAndSplit; public static bool InitialSwapMoveAndSplit; public static ConfigEntry<KeyCode> ToggleHudKey; public static ConfigEntry<bool> KeepRemainderOnCursor; public static ConfigEntry<bool> AllowDoubleClickCollect; public static ConfigEntry<int> SuccessiveClickRadius; public static ConfigEntry<float> SuccessiveClickWindow; public static ConfigEntry<bool> AllowRightClickDrop; public static ConfigEntry<KeyCode> SingleDropKey; public static ConfigEntry<ModifierKeyEnum> StackDropModifier; public static ConfigEntry<WheelActionEnum> ContainerWheelAction; public static ConfigEntry<WheelActionEnum> PlayerWheelAction; public static ConfigEntry<bool> InteractWithArmorStands; public static ConfigEntry<bool> InteractWithContainers; public static ConfigEntry<bool> InteractWithItemStands; public static ConfigEntry<bool> InteractWithWorldItems; private readonly Harmony Harmony = new Harmony("com.riintouge.inputtweaks"); private void Awake() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, "Whether this plugin has any effect when loaded."); LoadOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "LoadOnStart", true, "Whether this plugin loads on game start."); DebugMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "DebugMessages", false, "Whether to print plugin-specific trace/debug/warning/error messages."); SelectSwappedItem = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "SelectSwappedItem", false, "Whether selecting a second item with an item already selected will automatically select the second item after the swap. This mimics Minecraft's transient cursor item slot."); SplitRoundsUp = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "SplitRoundsUp", true, "Whether stack splits round up when the stack has an odd number of items."); SwapMoveAndSplit = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "SwapMoveAndSplit", true, "Whether [SHIFT] as split and [CTRL] as move swap behavior. Changes will not apply until the game is restarted."); InitialSwapMoveAndSplit = SwapMoveAndSplit.Value; ToggleHudKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1 - General", "ToggleHudKey", (KeyCode)284, "Toggle the HUD when pressed. Vanilla's default is [CTRL] + [F3] and cannot be changed in-game. Minecraft's default of [F1] conflicts with configuration managers."); KeepRemainderOnCursor = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Cursor Context", "KeepRemainderOnCursor", false, "Whether an unbalanced stack smear leaves the remainder on the cursor for further action."); AllowDoubleClickCollect = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Double-click", "AllowDoubleClickCollect", true, "Whether double-clicking on a partial stack will collect similar items from other stacks."); SuccessiveClickRadius = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Double-click", "SuccessiveClickRadius", 3, new ConfigDescription("The range, in pixels, in which a click may count as a successor to the initial click in the series.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); SuccessiveClickWindow = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Double-click", "SuccessiveClickWindow", 0.25f, new ConfigDescription("The interval, in seconds, in which a click may count as the successor to the previous click in the series.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); AllowRightClickDrop = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Drop Shortcuts", "AllowRightClickDrop", true, "Whether right-clicking with a stack outside of the inventory drops a single item from the stack."); SingleDropKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("4 - Drop Shortcuts", "SingleDropKey", (KeyCode)113, "Drop one item from the stack below the cursor when this key is pressed. Conflicts with auto-run by default."); StackDropModifier = ((BaseUnityPlugin)this).Config.Bind<ModifierKeyEnum>("4 - Drop Shortcuts", "StackDropModifier", ModifierKeyEnum.Move, "Drop the entire stack below the cursor when this modifier is pressed when SingleDropKey is pressed."); ContainerWheelAction = ((BaseUnityPlugin)this).Config.Bind<WheelActionEnum>("5 - Mouse Wheel", "ContainerWheelAction", WheelActionEnum.PushUpPullDown, "How items in a container will be moved when the mouse wheel is turned."); PlayerWheelAction = ((BaseUnityPlugin)this).Config.Bind<WheelActionEnum>("5 - Mouse Wheel", "PlayerWheelAction", WheelActionEnum.PullUpPushDown, "How items in the player's inventory will be moved when the mouse wheel is turned."); InteractWithArmorStands = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - World Interactions", "InteractWithArmorStands", true, "Whether armor stands can be interacted with while the inventory GUI is open."); InteractWithContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - World Interactions", "InteractWithContainers", true, "Whether containers can be interacted with while the inventory GUI is open."); InteractWithItemStands = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - World Interactions", "InteractWithItemStands", true, "Whether item stands can be interacted with while the inventory GUI is open."); InteractWithWorldItems = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - World Interactions", "InteractWithWorldItems", true, "Whether items in the world may be picked up while the inventory GUI is open."); if (LoadOnStart.Value) { InitialSwapMoveAndSplit = SwapMoveAndSplit.Value; Harmony.PatchAll(); } } } public class Common { public const int LeftControlInt = 306; public const int RightControlInt = 305; public const int LeftShiftInt = 304; public const int RightShiftInt = 303; public static bool AnyAlt() { if (!ZInput.GetKey((KeyCode)308, true)) { return ZInput.GetKey((KeyCode)307, true); } return true; } public static bool AnyCommand() { if (!ZInput.GetKey((KeyCode)310, true)) { return ZInput.GetKey((KeyCode)309, true); } return true; } public static bool AnyCtrl() { if (!ZInput.GetKey((KeyCode)306, true)) { return ZInput.GetKey((KeyCode)305, true); } return true; } public static bool AnyShift() { if (!ZInput.GetKey((KeyCode)304, true)) { return ZInput.GetKey((KeyCode)303, true); } return true; } public static bool CanStackOnto(ItemData item, ItemData target) { if (ItemsAreSimilarButDistinct(item, target, considerQuality: true) && target.m_shared.m_maxStackSize > 1) { return target.m_stack < target.m_shared.m_maxStackSize; } return false; } public static bool CheckModifier(InputTweaks.ModifierKeyEnum modifier) { switch (modifier) { case InputTweaks.ModifierKeyEnum.Alt: return AnyAlt(); case InputTweaks.ModifierKeyEnum.Command: return AnyCommand(); case InputTweaks.ModifierKeyEnum.Ctrl: return AnyCtrl(); case InputTweaks.ModifierKeyEnum.Move: if (!InputTweaks.InitialSwapMoveAndSplit) { return AnyCtrl(); } return AnyShift(); case InputTweaks.ModifierKeyEnum.Split: if (!InputTweaks.InitialSwapMoveAndSplit) { return AnyShift(); } return AnyCtrl(); case InputTweaks.ModifierKeyEnum.Shift: return AnyShift(); default: if (!AnyAlt() && !AnyCommand() && !AnyCtrl()) { return !AnyShift(); } return false; } } public static void DebugMessage(string message) { if (InputTweaks.DebugMessages.Value) { Debug.Log((object)message); } } public static List<ItemData> EquivalentStackables(ItemData item, InventoryGrid grid) { int width = InputTweaks.InventoryGridPatch.Width(grid); return (from x in grid.GetInventory().GetAllItems() where CanStackOnto(x, item) orderby x.m_stack, x.m_gridPos.x + x.m_gridPos.y * width select x).ToList(); } public static ItemData FindFirstSimilarItemInInventory(ItemData item, Inventory inv) { foreach (ItemData allItem in inv.GetAllItems()) { if (item != allItem && item.m_shared.m_name.Equals(allItem.m_shared.m_name) && item.m_quality == allItem.m_quality) { return allItem; } } if (item.m_shared.m_maxStackSize == 1) { foreach (ItemData allItem2 in inv.GetAllItems()) { if (item != allItem2 && item.m_shared.m_name.Equals(allItem2.m_shared.m_name)) { return allItem2; } } } return null; } public static ItemData FindLargestPartialStack(ItemData item, InventoryGrid grid) { if (item.m_shared.m_maxStackSize == 1) { return null; } int width = InputTweaks.InventoryGridPatch.Width(grid); return ((IEnumerable<ItemData>)(from x in grid.GetInventory().GetAllItems() where ItemsAreSimilarButDistinct(item, x, considerQuality: true) orderby x.m_stack descending, x.m_gridPos.x + x.m_gridPos.y * width select x)).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => x.m_stack < x.m_shared.m_maxStackSize)); } public static ItemData FindSmallestPartialStack(ItemData item, InventoryGrid grid) { if (item.m_shared.m_maxStackSize == 1) { return null; } int width = InputTweaks.InventoryGridPatch.Width(grid); return ((IEnumerable<ItemData>)(from x in grid.GetInventory().GetAllItems() where ItemsAreSimilarButDistinct(item, x, considerQuality: true) orderby x.m_stack, x.m_gridPos.x + x.m_gridPos.y * width select x)).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => x.m_stack < x.m_shared.m_maxStackSize)); } public static bool IsCursorOver(GameObject go) { Transform obj = ((go != null) ? go.transform : null); return IsCursorOver((RectTransform)(object)((obj is RectTransform) ? obj : null)); } public static bool IsCursorOver(RectTransform rectTransform) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rectTransform != (Object)null) { return RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Vector2.op_Implicit(Input.mousePosition)); } return false; } public static bool ItemsAreSimilarButDistinct(ItemData item, ItemData other, bool considerQuality) { if (item != null && other != null && item != other && item.m_shared.m_name == other.m_shared.m_name) { if (considerQuality) { return item.m_quality == other.m_quality; } return true; } return false; } public static IEnumerable<CodeInstruction> SwapShiftAndCtrl(IEnumerable<CodeInstruction> instructionsIn) { foreach (CodeInstruction item in instructionsIn) { if (item.opcode == OpCodes.Ldc_I4 && (int)item.operand == 304) { item.operand = 306; } else if (item.opcode == OpCodes.Ldc_I4 && (int)item.operand == 303) { item.operand = 305; } else if (item.opcode == OpCodes.Ldc_I4 && (int)item.operand == 306) { item.operand = 304; } else if (item.opcode == OpCodes.Ldc_I4 && (int)item.operand == 305) { item.operand = 303; } yield return item; } } public static List<CodeInstruction> SwapMoveAndSplitInSwitch(IEnumerable<CodeInstruction> instructionsIn) { List<CodeInstruction> list = new List<CodeInstruction>(instructionsIn); for (int i = 0; i + 2 < list.Count; i++) { CodeInstruction obj = list[i]; CodeInstruction val = list[i + 2]; if (obj.opcode == OpCodes.Ldarg_S && val.opcode == OpCodes.Bne_Un) { CodeInstruction val2 = list[i + 1]; if (val2.opcode == OpCodes.Ldc_I4_1) { val2.opcode = OpCodes.Ldc_I4_2; } else if (val2.opcode == OpCodes.Ldc_I4_2) { val2.opcode = OpCodes.Ldc_I4_1; } } } return list; } } public class InventoryButton { public enum SelectionState { Normal, Highlighted, Pressed, Selected, Disabled } private static readonly PropertyInfo CurrentSelectionStateProperty; private static readonly MethodInfo DoStateTransitionMethod; public UIInputHandler inputHandler; public InventoryGrid grid; public Vector2i gridPos; public bool representsExistingItem; public bool considerForDrag; public ItemData curItem { get { if (!((Object)(object)grid != (Object)null)) { return null; } return grid.GetInventory().GetItemAt(gridPos.x, gridPos.y); } } static InventoryButton() { CurrentSelectionStateProperty = AccessTools.Property(typeof(Selectable), "currentSelectionState"); DoStateTransitionMethod = AccessTools.Method(typeof(Selectable), "DoStateTransition", new Type[2] { CurrentSelectionStateProperty.PropertyType, typeof(bool) }, (Type[])null); } public void SetSelectionState(SelectionState state, bool instant) { DoStateTransitionMethod.Invoke(((Component)inputHandler).GetComponent<Button>(), new object[2] { (int)state, instant }); } } public struct Lockable<T> { public T value; public T Value { get { return value; } set { if (!Locked) { this.value = value; } } } public bool Locked { get; set; } public Lockable(bool locked, T value) { Locked = locked; this.value = value; } } public class ContextState { public bool Active { get; protected set; } = true; public bool Valid { get; protected set; } = true; public ContextState SetActive(bool value) { if (Active && !value) { Common.DebugMessage("CNTX: Changing state from Active to Inactive"); Active = value; } return this; } public ContextState SetValid(bool value) { if (Valid && !value) { Common.DebugMessage("CNTX: Changing state from Valid to Invalid"); Valid = value; } return this; } } public abstract class AbstractInventoryGuiCursorContext { public enum State { ActiveValid, ActiveInvalid, DoneValid, DoneInvalid } public virtual State CurrentState { get; protected set; } protected virtual bool UserInputSatisfied() { return true; } public abstract State Think(VanillaDragState dragState); protected virtual State SetState(State state) { if (CurrentState != state) { Common.DebugMessage($"CNTX: Changing state from {CurrentState} to {state}"); CurrentState = state; } return state; } public abstract void End(); } public class BlockingCursorContext : AbstractInventoryGuiCursorContext { protected Func<bool> blockRequirement; public BlockingCursorContext(Func<bool> blockRequirement) { this.blockRequirement = blockRequirement; } public override State Think(VanillaDragState dragState) { if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None) { return SetState(State.DoneValid); } if (CurrentState == State.ActiveInvalid || (blockRequirement != null && !blockRequirement())) { return SetState(State.ActiveInvalid); } return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending BlockingCursorContext"); } } public abstract class InventoryButtonTrackingContext : AbstractInventoryGuiCursorContext { protected InventoryGrid playerGrid; protected List<InventoryButton> playerButtons; protected InventoryGrid containerGrid; protected List<InventoryButton> containerButtons; protected InventoryButton firstButton; protected InventoryButton previousButton; protected InventoryButton currentButton; protected List<InventoryButton> highlightedButtons = new List<InventoryButton>(); public InventoryButtonTrackingContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) { if ((Object)(object)playerGrid == (Object)null || playerButtons == null || containerButtons == null) { Common.DebugMessage("CNTX: One or more null arguments"); CurrentState = State.DoneInvalid; return; } this.playerGrid = playerGrid; this.playerButtons = playerButtons; this.containerGrid = containerGrid; this.containerButtons = containerButtons; firstButton = InputTweaks.InventoryGuiPatch.GetHoveredButton(this.playerGrid, this.containerGrid); if (firstButton == null) { Common.DebugMessage("CNTX: Started on a null button"); CurrentState = State.DoneInvalid; } else { VanillaDragState vanillaDragState = new VanillaDragState(); UpdateInventoryButtons(playerGrid, this.playerButtons, vanillaDragState.dragItem); UpdateInventoryButtons(containerGrid, this.containerButtons, vanillaDragState.dragItem); } } protected void UpdateInventoryButtons(InventoryGrid grid, List<InventoryButton> buttons, ItemData dragItem) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = grid.GetInventory(); foreach (InventoryButton button in buttons) { Vector2i gridPos = button.gridPos; ItemData itemAt = inventory.GetItemAt(gridPos.x, gridPos.y); button.considerForDrag = itemAt == null || dragItem == null || itemAt == dragItem || Common.CanStackOnto(dragItem, itemAt); button.representsExistingItem = itemAt != null; } } public override State Think(VanillaDragState dragState) { if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } previousButton = currentButton; currentButton = InputTweaks.InventoryGuiPatch.GetHoveredButton(playerGrid, containerGrid); highlightedButtons.ForEach(delegate(InventoryButton x) { x.SetSelectionState(InventoryButton.SelectionState.Highlighted, instant: true); }); return State.ActiveValid; } public override void End() { highlightedButtons.ForEach(delegate(InventoryButton x) { x.SetSelectionState(InventoryButton.SelectionState.Normal, instant: false); }); highlightedButtons.Clear(); } } public class MultiClickContext : InventoryButtonTrackingContext { protected bool collected; public MultiClickContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) : base(playerGrid, playerButtons, containerGrid, containerButtons) { if (CurrentState == State.ActiveValid && firstButton == null) { SetState(State.ActiveInvalid); } } protected bool CollectFromInto(InventoryGrid grid, ItemData item) { List<ItemData> list = Common.EquivalentStackables(item, grid).ToList(); Common.DebugMessage($"DBLC: Collecting {item} from {list.Count} equivalent stacks"); Inventory inventory = grid.GetInventory(); foreach (ItemData item2 in list) { int num = Mathf.Min(item.m_shared.m_maxStackSize - item.m_stack, item2.m_stack); Common.DebugMessage($"DBLC: Moving {num} item(s)"); if (inventory.RemoveItem(item2, num)) { item.m_stack += num; } } return item.m_stack < item.m_shared.m_maxStackSize; } public override State Think(VanillaDragState dragState) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.successiveClicks == 0) { return SetState((CurrentState == State.ActiveValid) ? State.DoneValid : State.DoneInvalid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied() || currentButton != firstButton) { return SetState(State.ActiveInvalid); } if (collected) { return SetState(State.ActiveValid); } InventoryGrid grid = currentButton.grid; Inventory inventory = grid.GetInventory(); Vector2i gridPos = currentButton.gridPos; ItemData itemAt = inventory.GetItemAt(gridPos.x, gridPos.y); if (itemAt == null) { return SetState(State.DoneInvalid); } if (itemAt.m_stack < itemAt.m_shared.m_maxStackSize) { InventoryGrid val = (((Object)(object)grid == (Object)(object)playerGrid) ? containerGrid : playerGrid); if (CollectFromInto(grid, itemAt)) { CollectFromInto(val, itemAt); } InputTweaks.InventoryPatch.Changed(inventory); InputTweaks.InventoryPatch.Changed(val.GetInventory()); } InputTweaks.InventoryGuiPatch.SetupDragItem(InventoryGui.instance, itemAt, inventory, itemAt.m_stack); collected = true; return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending MultiClickContext"); } protected override bool UserInputSatisfied() { if (FrameInputs.Current.successiveClicks > 0) { return Common.CheckModifier(InputTweaks.ModifierKeyEnum.None); } return false; } } public class StackMoveContext : InventoryButtonTrackingContext { public StackMoveContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) : base(playerGrid, playerButtons, containerGrid, containerButtons) { } public override State Think(VanillaDragState dragState) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00bb: 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) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None) { return SetState(State.DoneValid); } if (dragState.isValid) { return SetState(State.DoneInvalid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied()) { return SetState(State.ActiveInvalid); } if (currentButton == null || currentButton == previousButton) { return SetState(State.ActiveValid); } if (currentButton != firstButton) { firstButton.SetSelectionState(InventoryButton.SelectionState.Normal, instant: false); } InventoryGrid grid = currentButton.grid; Inventory inventory = grid.GetInventory(); Vector2i gridPos = currentButton.gridPos; ItemData itemAt = inventory.GetItemAt(gridPos.x, gridPos.y); grid.m_onSelected(grid, itemAt, gridPos, (Modifier)2); return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending StackMoveContext"); base.End(); VanillaDragState.ClearDrag(); } protected override bool UserInputSatisfied() { if (FrameInputs.Current.LeftOnly && Common.CheckModifier(InputTweaks.ModifierKeyEnum.Move)) { return !Common.CheckModifier(InputTweaks.ModifierKeyEnum.Split); } return false; } } public class FilteredStackMoveContext : InventoryButtonTrackingContext { protected string itemName; public FilteredStackMoveContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) : base(playerGrid, playerButtons, containerGrid, containerButtons) { if (CurrentState != State.DoneValid || CurrentState != State.DoneInvalid) { itemName = firstButton.curItem?.m_shared?.m_name; if (itemName == null) { SetState(State.DoneInvalid); } } } public override State Think(VanillaDragState dragState) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None) { return SetState(State.DoneValid); } if (dragState.isValid) { return SetState(State.DoneInvalid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied()) { return SetState(State.ActiveInvalid); } if (currentButton == null || currentButton == previousButton) { return SetState(State.ActiveValid); } if (currentButton != firstButton) { firstButton.SetSelectionState(InventoryButton.SelectionState.Normal, instant: false); } InventoryGrid grid = currentButton.grid; Inventory inventory = grid.GetInventory(); Vector2i gridPos = currentButton.gridPos; ItemData itemAt = inventory.GetItemAt(gridPos.x, gridPos.y); if (itemAt != null && itemAt.m_shared.m_name.Equals(itemName)) { grid.m_onSelected(grid, itemAt, gridPos, (Modifier)2); } return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending FilteredStackMoveContext"); base.End(); VanillaDragState.ClearDrag(); } protected override bool UserInputSatisfied() { if (FrameInputs.Current.LeftOnly && Common.AnyShift()) { return Common.AnyCtrl(); } return false; } } public class StackSmearContext : InventoryButtonTrackingContext { protected List<InventoryButton> smearedButtons = new List<InventoryButton>(); protected Inventory swappedInv; protected Vector2i swappedPos; public StackSmearContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons, Inventory swappedInv, Vector2i swappedPos) : base(playerGrid, playerButtons, containerGrid, containerButtons) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (CurrentState == State.DoneInvalid || VanillaDragState.IsValid()) { CurrentState = State.DoneInvalid; return; } firstButton.considerForDrag = false; smearedButtons.Add(firstButton); this.swappedInv = swappedInv; this.swappedPos = swappedPos; if ((firstButton.curItem?.m_stack ?? 0) <= 1) { CurrentState = State.DoneValid; } } public override State Think(VanillaDragState dragState) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None) { return SetState(State.DoneValid); } if (dragState.isValid) { return SetState(State.DoneInvalid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied()) { return SetState(State.ActiveInvalid); } if (currentButton == null || currentButton == previousButton || currentButton == firstButton || !currentButton.considerForDrag) { return SetState(State.ActiveValid); } ItemData curItem = currentButton.curItem; if (curItem == null || Common.CanStackOnto(firstButton.curItem, curItem)) { Vector2i gridPos = currentButton.gridPos; Common.DebugMessage($"CNTX: Left, into ({gridPos})"); currentButton.SetSelectionState(InventoryButton.SelectionState.Highlighted, instant: true); currentButton.considerForDrag = false; highlightedButtons.Add(currentButton); smearedButtons.Add(currentButton); } else { Common.DebugMessage($"CNTX: Cannot stack {firstButton.curItem} onto {curItem}"); } return SetState(State.ActiveValid); } public override void End() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) Common.DebugMessage("CNTX: Ending StackSmearContext"); bool flag = true; if (CurrentState == State.DoneValid) { if (smearedButtons.Count == 1) { if (InputTweaks.SelectSwappedItem.Value && swappedInv != null && firstButton.gridPos != swappedPos) { ItemData curItem = firstButton.curItem; ItemData itemAt = swappedInv.GetItemAt(swappedPos.x, swappedPos.y); if (itemAt != null && !Common.CanStackOnto(curItem, itemAt)) { Common.DebugMessage("INFO: Selecting swapped item"); InputTweaks.InventoryGuiPatch.SetupDragItem(InventoryGui.instance, itemAt, swappedInv, itemAt.m_stack); flag = false; } } } else { ItemData val = firstButton?.curItem; if (val != null) { int num = Mathf.Max(1, Mathf.FloorToInt((float)val.m_stack / (float)smearedButtons.Count)); int num2 = val.m_stack - num; foreach (InventoryButton smearedButton in smearedButtons) { if (smearedButton != firstButton) { if (val.m_stack < 2 * num) { break; } Inventory inventory = smearedButton.grid.GetInventory(); Vector2i gridPos = smearedButton.gridPos; if (InputTweaks.InventoryGuiPatch.AddItem(inventory, val, num, gridPos.x, gridPos.y)) { num2 -= num; } } } if (InputTweaks.KeepRemainderOnCursor.Value && num2 > 0) { InputTweaks.InventoryGuiPatch.SetupDragItem(InventoryGui.instance, val, firstButton.grid.GetInventory(), num2); flag = false; } } } } base.End(); if (flag) { VanillaDragState.ClearDrag(); } } protected override bool UserInputSatisfied() { if (FrameInputs.Current.LeftOnly) { return Common.CheckModifier(InputTweaks.ModifierKeyEnum.None); } return false; } } public class StackCollectContext : InventoryButtonTrackingContext { public StackCollectContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) : base(playerGrid, playerButtons, containerGrid, containerButtons) { if (CurrentState == State.DoneInvalid || !VanillaDragState.IsValid()) { CurrentState = State.DoneInvalid; } } public override State Think(VanillaDragState dragState) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None) { return SetState(State.DoneValid); } if (!dragState.isValid) { return SetState(State.DoneInvalid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied()) { return SetState(State.ActiveInvalid); } if (currentButton == null || currentButton == previousButton || currentButton == firstButton) { return SetState(State.ActiveValid); } ItemData curItem = currentButton.curItem; ItemData curItem2 = firstButton.curItem; if (Common.CanStackOnto(curItem, curItem2)) { Common.DebugMessage($"CNTX: Left, from ({currentButton.gridPos})"); Inventory inventory = currentButton.grid.GetInventory(); Inventory inventory2 = firstButton.grid.GetInventory(); int num = Mathf.Min(curItem2.m_shared.m_maxStackSize - curItem2.m_stack, curItem.m_stack); Common.DebugMessage($"CNTX: Moving {num} item(s)"); if (inventory.RemoveItem(curItem, num)) { curItem2.m_stack += num; if (dragState.Increment(num)) { dragState = new VanillaDragState(); dragState.UpdateTooltip(); UITooltip.HideTooltip(); } if (inventory2 != inventory) { InputTweaks.InventoryPatch.Changed(inventory2); } } } else { Common.DebugMessage($"CNTX: Cannot stack {curItem} onto {curItem2}"); } return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending StackCollectContext"); base.End(); } protected override bool UserInputSatisfied() { if (FrameInputs.Current.LeftOnly) { return Common.CheckModifier(InputTweaks.ModifierKeyEnum.None); } return false; } } public class SingleSmearContext : InventoryButtonTrackingContext { public SingleSmearContext(InventoryGrid playerGrid, List<InventoryButton> playerButtons, InventoryGrid containerGrid, List<InventoryButton> containerButtons) : base(playerGrid, playerButtons, containerGrid, containerButtons) { } public override State Think(VanillaDragState dragState) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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) base.Think(dragState); if (CurrentState == State.DoneValid || CurrentState == State.DoneInvalid) { return CurrentState; } if (FrameInputs.Current.None || !dragState.isValid) { return SetState(State.DoneValid); } if (CurrentState == State.ActiveInvalid || !UserInputSatisfied()) { return SetState(State.ActiveInvalid); } if (currentButton == null || currentButton == previousButton || !currentButton.considerForDrag) { return SetState(State.ActiveValid); } Inventory inventory = currentButton.grid.GetInventory(); ItemData dragItem = dragState.dragItem; Vector2i gridPos = currentButton.gridPos; bool flag = false; if (!InputTweaks.InventoryGuiPatch.AddItem(inventory, dragItem, 1, gridPos.x, gridPos.y)) { if (currentButton.curItem != dragItem) { return SetState(State.ActiveValid); } flag = true; } Common.DebugMessage($"CNTX: Right, into ({gridPos})"); currentButton.SetSelectionState(InventoryButton.SelectionState.Highlighted, instant: true); currentButton.considerForDrag = false; highlightedButtons.Add(currentButton); if (!flag && dragState.dragItem.m_stack <= 0) { Inventory inventory2 = playerGrid.GetInventory(); (inventory2.ContainsItem(dragItem) ? inventory2 : containerGrid.GetInventory()).RemoveItem(dragItem); } if (dragState.Decrement()) { new VanillaDragState().UpdateTooltip(); } return SetState(State.ActiveValid); } public override void End() { Common.DebugMessage("CNTX: Ending SingleSmearContext"); base.End(); } protected override bool UserInputSatisfied() { if (FrameInputs.Current.RightOnly) { return Common.CheckModifier(InputTweaks.ModifierKeyEnum.None); } return false; } } public class VanillaDragState { public readonly GameObject dragObject; public readonly Inventory dragInventory; public readonly ItemData dragItem; public readonly int dragAmount; public readonly bool isValid; public VanillaDragState() { InventoryGui instance = InventoryGui.instance; dragObject = Traverse.Create((object)instance).Field("m_dragGo").GetValue<GameObject>(); if ((Object)(object)dragObject == (Object)null) { dragInventory = null; dragItem = null; dragAmount = 0; } else { Traverse val = Traverse.Create((object)instance); dragInventory = val.Field("m_dragInventory").GetValue<Inventory>(); dragItem = val.Field("m_dragItem").GetValue<ItemData>(); dragAmount = val.Field("m_dragAmount").GetValue<int>(); isValid = (Object)(object)dragObject != (Object)null && dragInventory != null && dragItem != null && dragAmount > 0 && dragInventory.ContainsItem(dragItem); } } protected VanillaDragState(GameObject dragObject, Inventory dragInventory, ItemData dragItem, int dragAmount, bool isValid) { this.dragObject = dragObject; this.dragInventory = dragInventory; this.dragItem = dragItem; this.dragAmount = dragAmount; this.isValid = isValid; } public VanillaDragState Clone() { return new VanillaDragState(dragObject, dragInventory, dragItem, dragAmount, isValid); } public bool Increment(int count = 1) { Common.DebugMessage("INFO: VanillaDragState.Increment()"); if (!isValid) { return false; } Traverse.Create((object)InventoryGui.instance).Field("m_dragAmount").SetValue((object)(dragAmount + count)); return true; } public bool Decrement(int count = 1) { Common.DebugMessage("INFO: VanillaDragState.Decrement()"); if (!isValid) { return false; } Traverse.Create((object)InventoryGui.instance).Field("m_dragAmount").SetValue((object)(dragAmount - count)); return true; } public void UpdateTooltip() { Common.DebugMessage("INFO: VanillaDragState.UpdateTooltip()"); if (isValid) { ((Component)dragObject.transform.Find("icon")).GetComponent<Image>().sprite = dragItem.GetIcon(); ((Component)dragObject.transform.Find("name")).GetComponent<TMP_Text>().text = dragItem.m_shared.m_name; TMP_Text component = ((Component)dragObject.transform.Find("amount")).GetComponent<TMP_Text>(); object text; if (dragAmount <= 1) { text = ""; } else { int num = dragAmount; text = num.ToString(); } component.text = (string)text; } } public static void ClearDrag() { InputTweaks.InventoryGuiPatch.SetupDragItem(InventoryGui.instance, null, null, 1); } public static bool IsValid() { return new VanillaDragState().isValid; } } public class FrameInputs { public enum ButtonDelta { None, Pressed, Held, Released } public const int LeftButton = 0; public const int RightButton = 1; public const int AllButtons = 2; public static FrameInputs Prior = null; public static FrameInputs Current = new FrameInputs(skipInit: true); public static double FrameTimeOfLastUpdate = 0.0; private static double LeftDownLast; private static Vector2i SuccessiveClicksFirstPos; private static int SuccessiveClicks; private readonly int mouseButtons; private readonly ButtonDelta[] buttonDeltas = new ButtonDelta[2]; public readonly Vector2i mousePos; public readonly bool isDoubleClick; public readonly int successiveClicks; public bool Left => Test(0); public bool Right => Test(1); public bool LeftOnly => Only(0); public bool RightOnly => Only(1); public bool None => mouseButtons == 0; public bool Any => mouseButtons > 0; public bool Exclusive => (mouseButtons & (mouseButtons - 1)) == 0; public ButtonDelta LeftDelta => buttonDeltas[0]; public ButtonDelta RightDelta => buttonDeltas[1]; protected FrameInputs(bool skipInit) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_0119: Unknown result type (might be due to invalid IL or missing references) if (skipInit) { return; } for (int i = 0; i < 2; i++) { mouseButtons |= (ZInput.GetMouseButton(i) ? (1 << i) : 0); buttonDeltas[i] = (Test(i) ? ((!Prior.Test(i)) ? ButtonDelta.Pressed : ButtonDelta.Held) : (Prior.Test(i) ? ButtonDelta.Released : ButtonDelta.None)); } mousePos = new Vector2i(Input.mousePosition); double timeAsDouble = Time.timeAsDouble; double num = timeAsDouble - LeftDownLast; if (LeftDelta == ButtonDelta.Pressed) { LeftDownLast = timeAsDouble; if (SuccessiveClicks == 0) { SuccessiveClicksFirstPos = mousePos; SuccessiveClicks++; } else { Vector2i val = mousePos - SuccessiveClicksFirstPos; if (((Vector2i)(ref val)).Magnitude() < InputTweaks.SuccessiveClickRadius.Value) { SuccessiveClicks++; Common.DebugMessage($"DBLC: SuccessiveClicks {SuccessiveClicks}"); } else { SuccessiveClicksFirstPos = mousePos; SuccessiveClicks = 1; Common.DebugMessage("DBLC: SuccessiveClicks reset (distance)"); } } } else if (LeftDelta == ButtonDelta.None && num > (double)InputTweaks.SuccessiveClickWindow.Value && SuccessiveClicks > 0) { SuccessiveClicks = 0; Common.DebugMessage("DBLC: SuccessiveClicks reset (time)"); } successiveClicks = SuccessiveClicks; isDoubleClick = successiveClicks == 2; } public bool Test(int mouseButton) { return (mouseButtons & (1 << mouseButton)) > 0; } public bool Only(int mouseButton) { int num = 1 << mouseButton; return (mouseButtons & num) == num; } public ButtonDelta Delta(int mouseButton) { if (!Current.Test(mouseButton)) { if (!Prior.Test(mouseButton)) { return ButtonDelta.None; } return ButtonDelta.Released; } if (!Prior.Test(mouseButton)) { return ButtonDelta.Pressed; } return ButtonDelta.Held; } public static bool Update() { double timeAsDouble = Time.timeAsDouble; if (timeAsDouble == FrameTimeOfLastUpdate) { return false; } Prior = Current; Current = new FrameInputs(skipInit: false); FrameTimeOfLastUpdate = timeAsDouble; return true; } }