From d5035c57cec24f5a0596f1850723845d52caab49 Mon Sep 17 00:00:00 2001 From: anviaan Date: Sat, 20 Jul 2024 19:09:01 -0500 Subject: [PATCH] Sorting --- .../smartinventory/handler/Interaction.java | 39 +++++++ .../mixin/MixinKeyInputHandler.java | 13 ++- .../smartinventory/slots/ContainerSlots.java | 14 +++ .../smartinventory/slots/InventorySlots.java | 39 +++++++ .../smartinventory/slots/PlayerSlots.java | 23 ++++ .../smartinventory/sort/SortInventory.java | 103 +++++++++++------- 6 files changed, 186 insertions(+), 45 deletions(-) create mode 100644 src/main/java/net/anvian/smartinventory/handler/Interaction.java create mode 100644 src/main/java/net/anvian/smartinventory/slots/ContainerSlots.java create mode 100644 src/main/java/net/anvian/smartinventory/slots/InventorySlots.java create mode 100644 src/main/java/net/anvian/smartinventory/slots/PlayerSlots.java diff --git a/src/main/java/net/anvian/smartinventory/handler/Interaction.java b/src/main/java/net/anvian/smartinventory/handler/Interaction.java new file mode 100644 index 0000000..a0f2ea5 --- /dev/null +++ b/src/main/java/net/anvian/smartinventory/handler/Interaction.java @@ -0,0 +1,39 @@ +package net.anvian.smartinventory.handler; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.slot.SlotActionType; + +public class Interaction { + private static final int LEFT_CLICK = 0; + + public static ItemStack getCursorStack() { + return MinecraftClient.getInstance().player.currentScreenHandler.getCursorStack(); + } + + public static boolean hasEmptyCursor() { + return getCursorStack().isEmpty(); + } + + public static void clickStack(int slot) { + ClientPlayerInteractionManager manager = MinecraftClient.getInstance().interactionManager; + ClientPlayerEntity player = MinecraftClient.getInstance().player; + manager.clickSlot(getSyncId(), slot, LEFT_CLICK, SlotActionType.PICKUP, player); + } + + public static void swapStacks(int slot, int target) { + ClientPlayerInteractionManager manager = MinecraftClient.getInstance().interactionManager; + ClientPlayerEntity player = MinecraftClient.getInstance().player; + manager.clickSlot(getSyncId(), slot, LEFT_CLICK, SlotActionType.PICKUP, player); + manager.clickSlot(getSyncId(), target, LEFT_CLICK, SlotActionType.PICKUP, player); + if (!Interaction.hasEmptyCursor()) { + manager.clickSlot(getSyncId(), slot, LEFT_CLICK, SlotActionType.PICKUP, player); + } + } + + private static int getSyncId() { + return MinecraftClient.getInstance().player.currentScreenHandler.syncId; + } +} diff --git a/src/main/java/net/anvian/smartinventory/mixin/MixinKeyInputHandler.java b/src/main/java/net/anvian/smartinventory/mixin/MixinKeyInputHandler.java index 04e0da3..818626d 100644 --- a/src/main/java/net/anvian/smartinventory/mixin/MixinKeyInputHandler.java +++ b/src/main/java/net/anvian/smartinventory/mixin/MixinKeyInputHandler.java @@ -1,12 +1,13 @@ package net.anvian.smartinventory.mixin; -import net.anvian.smartinventory.event.KeyInput; +import net.anvian.smartinventory.handler.ModKeyBinding; import net.anvian.smartinventory.sort.SortInventory; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.screen.ScreenHandler; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,12 +17,14 @@ public class MixinKeyInputHandler { @Inject(method = "keyPressed", at = @At("HEAD")) private void onKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { - if (keyCode == KeyInput.keyBinding.getDefaultKey().getCode()) { - MinecraftClient client = MinecraftClient.getInstance(); - Screen screen = client.currentScreen; + if (keyCode == ModKeyBinding.keyBinding.getDefaultKey().getCode()) { + ScreenHandler screenHandler = MinecraftClient.getInstance().player.currentScreenHandler; + Screen screen = MinecraftClient.getInstance().currentScreen; if (screen instanceof InventoryScreen || screen instanceof CreativeInventoryScreen) { - SortInventory.sortPlayerInventory(client); + SortInventory.sortPlayerInventory(screenHandler); + } else { + SortInventory.sortContainerInventory(screenHandler); } } } diff --git a/src/main/java/net/anvian/smartinventory/slots/ContainerSlots.java b/src/main/java/net/anvian/smartinventory/slots/ContainerSlots.java new file mode 100644 index 0000000..7d3f67c --- /dev/null +++ b/src/main/java/net/anvian/smartinventory/slots/ContainerSlots.java @@ -0,0 +1,14 @@ +package net.anvian.smartinventory.slots; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.ScreenHandler; + +public class ContainerSlots { + public static InventorySlots get() { + ScreenHandler screenHandler = MinecraftClient.getInstance().player.currentScreenHandler; + int from = 0; + int to = screenHandler.slots.size() - PlayerInventory.MAIN_SIZE; + return new InventorySlots(from, to); + } +} diff --git a/src/main/java/net/anvian/smartinventory/slots/InventorySlots.java b/src/main/java/net/anvian/smartinventory/slots/InventorySlots.java new file mode 100644 index 0000000..4170aa4 --- /dev/null +++ b/src/main/java/net/anvian/smartinventory/slots/InventorySlots.java @@ -0,0 +1,39 @@ +package net.anvian.smartinventory.slots; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.screen.PlayerScreenHandler; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public class InventorySlots extends ArrayList { + + public InventorySlots(int from, int to) { + super(IntStream.range(from, to).boxed().toList()); + } + + public InventorySlots(int from, int to, int offhand) { + super(IntStream.concat(IntStream.range(from, to), IntStream.of(offhand)).boxed().toList()); + } + + public InventorySlots(List slots) { + super(slots); + } + + public int getLastSlot() { + return this.get(this.size() - 1); + } + + public InventorySlots excludeOffhand() { + Screen screen = MinecraftClient.getInstance().currentScreen; + if (screen instanceof InventoryScreen || screen instanceof CreativeInventoryScreen) { + this.remove(Integer.valueOf(PlayerScreenHandler.OFFHAND_ID)); + return new InventorySlots(this); + } + return this; + } +} diff --git a/src/main/java/net/anvian/smartinventory/slots/PlayerSlots.java b/src/main/java/net/anvian/smartinventory/slots/PlayerSlots.java new file mode 100644 index 0000000..4146065 --- /dev/null +++ b/src/main/java/net/anvian/smartinventory/slots/PlayerSlots.java @@ -0,0 +1,23 @@ +package net.anvian.smartinventory.slots; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.screen.ScreenHandler; + +public class PlayerSlots { + public static InventorySlots get() { + int from, to; + if (MinecraftClient.getInstance().currentScreen instanceof InventoryScreen) { + from = PlayerScreenHandler.INVENTORY_START; + to = PlayerScreenHandler.INVENTORY_END; + return new InventorySlots(from, to, PlayerScreenHandler.OFFHAND_ID); + } else { + ScreenHandler screenHandler = MinecraftClient.getInstance().player.currentScreenHandler; + from = screenHandler.slots.size() - PlayerInventory.MAIN_SIZE; + to = screenHandler.slots.size() - PlayerInventory.getHotbarSize(); + return new InventorySlots(from, to); + } + } +} diff --git a/src/main/java/net/anvian/smartinventory/sort/SortInventory.java b/src/main/java/net/anvian/smartinventory/sort/SortInventory.java index 31d17d5..20b4fb6 100644 --- a/src/main/java/net/anvian/smartinventory/sort/SortInventory.java +++ b/src/main/java/net/anvian/smartinventory/sort/SortInventory.java @@ -1,64 +1,87 @@ package net.anvian.smartinventory.sort; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; +import net.anvian.smartinventory.handler.Interaction; +import net.anvian.smartinventory.slots.ContainerSlots; +import net.anvian.smartinventory.slots.InventorySlots; +import net.anvian.smartinventory.slots.PlayerSlots; import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.collection.DefaultedList; +import net.minecraft.screen.ScreenHandler; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class SortInventory { - private static final int HOTBAR_SIZE = 9; - - public static void sortPlayerInventory(MinecraftClient client) { - PlayerEntity player = client.player; - if (player == null) return; - - DefaultedList inventory = player.getInventory().main; - Map groupedItems = groupItems(inventory, HOTBAR_SIZE); - DefaultedList sortedInventory = sortAndFilterInventory(groupedItems); + public static void sortPlayerInventory(ScreenHandler screenHandler) { + if (cursorCleared(PlayerSlots.get(), screenHandler)) { + mergeItemStacks(PlayerSlots.get().excludeOffhand(), screenHandler); + sortItemStacks(PlayerSlots.get().excludeOffhand(), screenHandler); + } + } - updateInventory(inventory, sortedInventory, HOTBAR_SIZE); - player.sendMessage(Text.of("Inventario ordenado!"), false); + public static void sortContainerInventory(ScreenHandler screenHandler) { + if (cursorCleared(ContainerSlots.get(), screenHandler)) { + mergeItemStacks(ContainerSlots.get(), screenHandler); + sortItemStacks(ContainerSlots.get(), screenHandler); + } } - private static Map groupItems(DefaultedList inventory, int start) { - Map groupedItems = new HashMap<>(); - MinecraftClient client = MinecraftClient.getInstance(); - if (client.player == null) return groupedItems; + private static boolean cursorCleared(InventorySlots inventorySlots, ScreenHandler screenHandler) { + if (!Interaction.hasEmptyCursor()) { + clearCursor(inventorySlots, screenHandler); + } + return Interaction.hasEmptyCursor(); + } - for (int i = start; i < inventory.size(); i++) { - ItemStack stack = inventory.get(i); - if (!stack.isEmpty()) { - String key = stack.getItem().toString(); - groupedItems.merge(key, stack, SortInventory::mergeStacks); + private static void mergeItemStacks(InventorySlots inventorySlots, ScreenHandler screenHandler) { + for (int slot : inventorySlots) { + ItemStack stack = screenHandler.getSlot(slot).getStack(); + if (!stack.isEmpty() && stack.getCount() < stack.getMaxCount()) { + Interaction.clickStack(slot); + for (int tempSlot = slot + 1; Interaction.getCursorStack().getCount() < Interaction.getCursorStack().getMaxCount() + && tempSlot <= inventorySlots.getLastSlot() && !Interaction.getCursorStack().isEmpty(); tempSlot++) { + if (ItemStack.areItemsEqual(Interaction.getCursorStack(), screenHandler.getSlot(tempSlot).getStack())) { + Interaction.clickStack(tempSlot); + } + } + if (!Interaction.hasEmptyCursor()) { + Interaction.clickStack(slot); + } } } - return groupedItems; } - private static ItemStack mergeStacks(ItemStack existing, ItemStack incoming) { - int transferAmount = Math.min(incoming.getCount(), existing.getMaxCount() - existing.getCount()); - existing.increment(transferAmount); - incoming.decrement(transferAmount); - return existing.getCount() == 0 ? incoming : existing; + private static void sortItemStacks(InventorySlots inventorySlots, ScreenHandler screenHandler) { + List sortedSlots = getSortedSlots(inventorySlots, screenHandler); + + for (int i = 0; i < sortedSlots.size(); i++) { + Interaction.swapStacks(sortedSlots.get(i), inventorySlots.get(i)); + sortedSlots = getSortedSlots(inventorySlots, screenHandler); + } } - private static DefaultedList sortAndFilterInventory(Map groupedItems) { - List sortedList = groupedItems.values().stream() - .sorted(Comparator.comparing(stack -> stack.getItem().getName(stack).getString())) + private static List getSortedSlots(InventorySlots inventorySlots, ScreenHandler screenHandler) { + return inventorySlots.stream() + .filter(slot -> !screenHandler.getSlot(slot).getStack().isEmpty()) + .sorted(Comparator.comparing((Integer slot) -> screenHandler.getSlot(slot).getStack().getName().getString()) + .thenComparing(slot -> screenHandler.getSlot(slot).getStack().getCount(), Comparator.reverseOrder())) .toList(); - - return DefaultedList.copyOf(ItemStack.EMPTY, sortedList.toArray(new ItemStack[0])); } - private static void updateInventory(DefaultedList inventory, DefaultedList sortedInventory, int start) { - for (int i = start; i < inventory.size(); i++) { - inventory.set(i, i - start < sortedInventory.size() ? sortedInventory.get(i - start) : ItemStack.EMPTY); + private static void clearCursor(InventorySlots inventorySlots, ScreenHandler screenHandler) { + for (int slot : inventorySlots) { + if (ItemStack.areItemsEqual(screenHandler.getSlot(slot).getStack(), Interaction.getCursorStack())) { + if (!Interaction.hasEmptyCursor()) { + Interaction.clickStack(slot); + } + } + } + + for (int slot : inventorySlots) { + if (screenHandler.getSlot(slot).getStack().isEmpty()) { + if (!Interaction.hasEmptyCursor()) { + Interaction.clickStack(slot); + } + } } } }