package de.take_weiland.mods.commons.inv; import static com.google.common.base.Preconditions.checkArgument; /** * <p>A target for shift-clicks, used with {@link de.take_weiland.mods.commons.inv.SpecialShiftClick}.</p> * <p>Instances of this class must <i>not</i> be reused.</p> * @author diesieben07 */ public abstract class ShiftClickTarget { /** * <p>Tries to merge the stack with one of the Slots between {@code from} and {@code to} (inclusive).</p> * <p>If {@code from} is greater than {@code to}, the range will be iterated in reverse ({@code to} to {@code from}).</p> * @param from first slot * @param to last slot * @return a ShiftClickTarget */ public static ShiftClickTarget range(int from, int to) { checkArgument(from >= 0 && to >= 0, "to and from must be >= 0"); if (to == from) { return of(to); } else if (to > from) { return new RevRange(from, to); } else { return new Range(from, to); } } /** * <p>Discard the shift-click, don't move the ItemStack at all.</p> * @return a ShiftClickTarget */ public static ShiftClickTarget none() { return None.INSTANCE; } /** * <p>Use the default behavior.</p> * @return a ShiftClickTarget */ public static ShiftClickTarget standard() { return Standard.INSTANCE; } /** * <p>Tries to merge the stack with the single given slot.</p> * @param slot the slot * @return a ShiftClickTarget */ public static ShiftClickTarget of(int slot) { return new One(slot); } /** * <p>Tries to merge the stack with the given slots in the order provided.</p> * @param slots the slots * @return a ShiftClickTarget */ public static ShiftClickTarget of(int... slots) { int len = slots.length; if (len == 0) { return none(); } else if (len == 1) { return of(slots[0]); } return new ForArray(slots); } ShiftClickTarget() { } abstract boolean hasNext(); abstract int next(); abstract void reset(); boolean isStandard() { return false; } boolean isNone() { return false; } private static final class Range extends ShiftClickTarget { private final int from; private final int to; private int next; Range(int from, int to) { this.from = from; this.to = to; this.next = from; } @Override boolean hasNext() { return next <= to; } @Override int next() { return next++; } @Override void reset() { next = from; } } private static final class RevRange extends ShiftClickTarget { private final int from; private final int to; private int next; RevRange(int from, int to) { this.from = from; this.to = to; this.next = to; } @Override boolean hasNext() { return next >= from; } @Override int next() { return next--; } @Override void reset() { next = to; } } private static final class ForArray extends ShiftClickTarget { private final int[] slots; private int curr; ForArray(int[] slots) { this.slots = slots; } @Override boolean hasNext() { return curr != slots.length; } @Override int next() { return slots[curr++]; } @Override void reset() { curr = 0; } } private static final class One extends ShiftClickTarget { private final int slot; private boolean done; One(int slot) { this.slot = slot; } @Override boolean hasNext() { return !done; } @Override int next() { return slot; } @Override void reset() { done = false; } } private static final class None extends ShiftClickTarget { static final None INSTANCE = new None(); @Override boolean hasNext() { return false; } @Override int next() { throw new AssertionError(); } @Override void reset() { } @Override boolean isNone() { return true; } } private static final class Standard extends ShiftClickTarget { static final Standard INSTANCE = new Standard(); @Override boolean hasNext() { throw new AssertionError(); } @Override int next() { throw new AssertionError(); } @Override void reset() { throw new AssertionError(); } @Override boolean isStandard() { return true; } } }