Files
NotEnoughItems/src/main/java/codechicken/nei/FastTransferManager.java
T

325 lines
12 KiB
Java
Raw Normal View History

2014-04-29 10:54:20 +10:00
package codechicken.nei;
import static codechicken.nei.NEIServerUtils.areStacksIdentical;
import static codechicken.nei.NEIServerUtils.areStacksSameType;
import static codechicken.nei.NEIServerUtils.copyStack;
2014-04-29 10:54:20 +10:00
import codechicken.nei.guihook.GuiContainerManager;
2019-12-30 20:19:16 -08:00
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
2014-04-29 10:54:20 +10:00
public class FastTransferManager {
2014-04-29 10:54:20 +10:00
/**
* Based on the general assumption that we want to fill top to bottom, left to right
*/
public static class SlotPositionComparator implements Comparator<Integer> {
2019-12-30 20:19:16 -08:00
final Container container;
2014-04-29 10:54:20 +10:00
public SlotPositionComparator(Container c) {
container = c;
}
@Override
public int compare(Integer arg0, Integer arg1) {
Slot slot1 = container.getSlot(arg0);
Slot slot2 = container.getSlot(arg1);
if (slot2.yDisplayPosition != slot1.yDisplayPosition)
return slot1.yDisplayPosition - slot2.yDisplayPosition;
return slot1.xDisplayPosition - slot2.xDisplayPosition;
}
}
2019-12-30 20:19:16 -08:00
public LinkedList<LinkedList<Integer>> slotZones = new LinkedList<>();
public HashMap<Integer, Integer> slotZoneMap = new HashMap<>();
2014-04-29 10:54:20 +10:00
private void generateSlotMap(Container container, ItemStack stack) {
stack = stack.copy();
stack.stackSize = 1;
for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++) {
if (slotZoneMap.containsKey(slotNo) || !container.getSlot(slotNo).isItemValid(stack)) continue;
2014-04-29 10:54:20 +10:00
2019-12-30 20:19:16 -08:00
HashSet<Integer> connectedSlots = new HashSet<>();
2014-04-29 10:54:20 +10:00
findConnectedSlots(container, slotNo, connectedSlots);
2019-12-30 20:19:16 -08:00
LinkedList<Integer> zoneSlots = new LinkedList<>(connectedSlots);
zoneSlots.sort(new SlotPositionComparator(container));
2014-04-29 10:54:20 +10:00
slotZones.add(zoneSlots);
for (int i : zoneSlots) {
slotZoneMap.put(i, slotZones.size() - 1);
}
}
}
private void findConnectedSlots(Container container, int slotNo, HashSet<Integer> connectedSlots) {
connectedSlots.add(slotNo);
Slot slot = container.getSlot(slotNo);
final int threshold = 18;
for (int i = 0; i < container.inventorySlots.size(); i++) {
if (connectedSlots.contains(i)) continue;
2014-04-29 10:54:20 +10:00
Slot slot1 = container.getSlot(i);
if (Math.abs(slot.xDisplayPosition - slot1.xDisplayPosition) <= threshold
&& Math.abs(slot.yDisplayPosition - slot1.yDisplayPosition) <= threshold) {
2014-04-29 10:54:20 +10:00
findConnectedSlots(container, i, connectedSlots);
}
}
}
public static int findSlotWithItem(Container container, ItemStack teststack) {
for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++) {
ItemStack stack = container.getSlot(slotNo).getStack();
if (areStacksSameType(stack, teststack)) return slotNo;
2014-04-29 10:54:20 +10:00
}
return -1;
}
public static void clearSlots(Container container) {
for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++)
((Slot) container.inventorySlots.get(slotNo)).putStack(null);
}
public void performMassTransfer(GuiContainer window, int fromSlot, int toSlot, ItemStack heldStack) {
generateSlotMap(window.inventorySlots, heldStack);
Integer fromZone = slotZoneMap.get(fromSlot);
Integer toZone = slotZoneMap.get(toSlot);
if (fromZone == null || toZone == null || fromZone.equals(toZone)) return;
2014-04-29 10:54:20 +10:00
if (NEIClientUtils.getHeldItem() != null && !areStacksSameType(heldStack, NEIClientUtils.getHeldItem())) return;
2014-04-29 10:54:20 +10:00
if (!fillZoneWithHeldItem(window, toZone)) return;
2014-04-29 10:54:20 +10:00
for (int transferFrom : slotZones.get(fromZone)) {
ItemStack transferStack =
window.inventorySlots.getSlot(transferFrom).getStack();
2014-04-29 10:54:20 +10:00
if (!areStacksSameType(heldStack, transferStack)) continue;
2014-04-29 10:54:20 +10:00
clickSlot(window, transferFrom);
if (!fillZoneWithHeldItem(window, toZone)) {
clickSlot(window, transferFrom);
return;
}
}
}
/**
* @return The slot that one item from the source slot will end up in apon shift clicking, -1 if none.
*/
public int findShiftClickDestinationSlot(Container container, int fromSlot) {
LinkedList<ItemStack> save = saveContainer(container);
Slot slot = container.getSlot(fromSlot);
ItemStack stack = slot.getStack();
if (stack == null) return -1;
2014-04-29 10:54:20 +10:00
stack.stackSize = 1;
slot.putStack(stack.copy());
LinkedList<ItemStack> compareBefore = saveContainer(container);
container.slotClick(fromSlot, 0, 1, NEIClientUtils.mc().thePlayer);
LinkedList<ItemStack> compareAfter = saveContainer(container);
try {
// if(compareAfter.get(fromSlot) != null)//transfer failed
// return -1;
2014-04-29 10:54:20 +10:00
for (int i = 0; i < compareBefore.size(); i++) {
if (i == fromSlot) continue;
2014-04-29 10:54:20 +10:00
ItemStack before = compareBefore.get(i);
ItemStack after = compareAfter.get(i);
if (!areStacksIdentical(before, after) && after != null)
if (before == null
? areStacksSameType(stack, after)
: // transfered into this empty slot
areStacksSameType(stack, after)
&& after.stackSize - before.stackSize > 0) // it added to this stack
return i;
2014-04-29 10:54:20 +10:00
}
return -1;
} finally {
restoreContainer(container, save);
}
}
public LinkedList<ItemStack> saveContainer(Container container) {
2019-12-30 20:19:16 -08:00
LinkedList<ItemStack> stacks = new LinkedList<>();
2014-04-29 10:54:20 +10:00
for (int i = 0; i < container.inventorySlots.size(); i++)
stacks.add(copyStack(container.getSlot(i).getStack()));
return stacks;
}
public void restoreContainer(Container container, LinkedList<ItemStack> items) {
for (int i = 0; i < container.inventorySlots.size(); i++) {
container.getSlot(i).putStack(items.get(i));
}
container.slotClick(-999, 0, 0, NEIClientUtils.mc().thePlayer);
}
public void transferItem(GuiContainer window, int fromSlot) {
int toSlot = findShiftClickDestinationSlot(window.inventorySlots, fromSlot);
if (toSlot == -1) return;
2014-04-29 10:54:20 +10:00
Slot from = window.inventorySlots.getSlot(fromSlot);
if (from.isItemValid(from.getStack())) moveOneItem(window, fromSlot, toSlot);
else // slots that you can't put stuff in
moveOutputSet(window, fromSlot, toSlot);
2014-04-29 10:54:20 +10:00
}
public void moveOutputSet(GuiContainer window, int fromSlot, int toSlot) {
if (NEIClientUtils.getHeldItem() != null) return;
2014-04-29 10:54:20 +10:00
clickSlot(window, fromSlot); // pickup fromSlot
if (NEIClientUtils.getHeldItem()
== null) // maybe this container does auto transfers. No need to pick up the final item
return;
clickSlot(window, toSlot); // place one in toSlot
2014-04-29 10:54:20 +10:00
}
public void moveOneItem(GuiContainer window, int fromSlot, int toSlot) {
clickSlot(window, fromSlot); // pickup fromSlot
clickSlot(window, toSlot, 1); // place one in toSlot
clickSlot(window, fromSlot); // place down in fromSlot
2014-04-29 10:54:20 +10:00
}
public void retrieveItem(GuiContainer window, int toSlot) {
Slot slot = window.inventorySlots.getSlot(toSlot);
ItemStack slotStack = slot.getStack();
if (slotStack == null
|| slotStack.stackSize == slot.getSlotStackLimit()
|| slotStack.stackSize == slotStack.getMaxStackSize()) return;
2014-04-29 10:54:20 +10:00
generateSlotMap(window.inventorySlots, slotStack);
Integer destZone = slotZoneMap.get(toSlot);
if (destZone == null) // slots that don't accept
return;
2014-04-29 10:54:20 +10:00
int firstZoneSlot = findShiftClickDestinationSlot(window.inventorySlots, toSlot);
int firstZone = -1;
if (firstZoneSlot != -1) {
Integer integer = slotZoneMap.get(firstZoneSlot);
if (integer != null) {
firstZone = integer;
if (retrieveItemFromZone(window, firstZone, toSlot)) return;
2014-04-29 10:54:20 +10:00
}
}
for (int zone = 0; zone < slotZones.size(); zone++) {
if (zone == destZone || zone == firstZone) continue;
2014-04-29 10:54:20 +10:00
if (retrieveItemFromZone(window, zone, toSlot)) return;
2014-04-29 10:54:20 +10:00
}
retrieveItemFromZone(window, destZone, toSlot);
}
private boolean retrieveItemFromZone(GuiContainer window, int zone, int toSlot) {
ItemStack stack = window.inventorySlots.getSlot(toSlot).getStack();
for (int i : slotZones.get(zone)) {
if (i == toSlot) continue;
2014-04-29 10:54:20 +10:00
Slot slot = window.inventorySlots.getSlot(i);
ItemStack stack1 = slot.getStack();
if (areStacksSameType(stack, stack1)
&& stack1.stackSize != slot.getSlotStackLimit()
&& // get from full stacks on second pass
2014-04-29 10:54:20 +10:00
stack1.stackSize != stack1.getMaxStackSize()) {
moveOneItem(window, i, toSlot);
return true;
}
}
for (int i : slotZones.get(zone)) {
if (i == toSlot) continue;
2014-04-29 10:54:20 +10:00
Slot slot = window.inventorySlots.getSlot(i);
ItemStack stack1 = slot.getStack();
if (areStacksSameType(stack, stack1)) {
moveOneItem(window, i, toSlot);
return true;
}
}
return false;
}
public static void clickSlot(GuiContainer window, int slotIndex) {
clickSlot(window, slotIndex, 0);
}
public static void clickSlot(GuiContainer window, int slotIndex, int button) {
clickSlot(window, slotIndex, button, 0);
}
public static void clickSlot(GuiContainer window, int slotIndex, int button, int modifier) {
GuiContainerManager.getManager(window).handleSlotClick(slotIndex, button, modifier);
}
private boolean fillZoneWithHeldItem(GuiContainer window, int zoneIndex) {
for (int transferTo : slotZones.get(zoneIndex)) {
ItemStack held = NEIClientUtils.getHeldItem();
if (held == null) break;
2014-04-29 10:54:20 +10:00
ItemStack inToSlot = window.inventorySlots.getSlot(transferTo).getStack();
if (!areStacksSameType(inToSlot, held)) continue;
2014-04-29 10:54:20 +10:00
clickSlot(window, transferTo);
}
for (int transferTo : slotZones.get(zoneIndex)) // repeat on empty slots
2014-04-29 10:54:20 +10:00
{
ItemStack held = NEIClientUtils.getHeldItem();
if (held == null) break;
2014-04-29 10:54:20 +10:00
ItemStack inToSlot = window.inventorySlots.getSlot(transferTo).getStack();
if (inToSlot != null) continue;
2014-04-29 10:54:20 +10:00
clickSlot(window, transferTo);
}
return NEIClientUtils.getHeldItem() == null;
}
public void throwAll(GuiContainer window, int pickedUpFromSlot) {
ItemStack held = NEIClientUtils.getHeldItem();
if (held == null) return;
2014-04-29 10:54:20 +10:00
clickSlot(window, -999);
generateSlotMap(window.inventorySlots, held);
Integer zone = slotZoneMap.get(pickedUpFromSlot);
if (zone == null) // something went wrong and we can't work out where the item was picked up from
return;
for (int slotIndex : slotZones.get(zone)) {
2014-04-29 10:54:20 +10:00
Slot slot = window.inventorySlots.getSlot(slotIndex);
if (areStacksSameType(held, slot.getStack())) {
clickSlot(window, slotIndex);
clickSlot(window, -999);
}
}
}
}