diff options
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java | 31 | ||||
-rw-r--r-- | src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java | 79 |
2 files changed, 109 insertions, 1 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java index 6e7db9c..a45fee6 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java @@ -1,5 +1,8 @@ package io.github.cottonmc.cotton.gui; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import io.github.cottonmc.cotton.gui.widget.WItemSlot; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.Inventory; import net.minecraft.item.ItemStack; @@ -7,6 +10,7 @@ import net.minecraft.screen.slot.Slot; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.Objects; import java.util.function.Predicate; public class ValidatedSlot extends Slot { @@ -15,6 +19,7 @@ public class ValidatedSlot extends Slot { private boolean insertingAllowed = true; private boolean takingAllowed = true; private Predicate<ItemStack> filter; + protected final Multimap<WItemSlot, WItemSlot.ChangeListener> listeners = HashMultimap.create(); public ValidatedSlot(Inventory inventory, int index, int x, int y) { super(inventory, index, x, y); @@ -48,6 +53,17 @@ public class ValidatedSlot extends Slot { return result; } + @Override + public void markDirty() { + listeners.forEach((slot, listener) -> listener.onStackChanged(slot, inventory, getInventoryIndex(), getStack())); + super.markDirty(); + } + + /** + * Gets the index of this slot in its inventory. + * + * @return the inventory index + */ public int getInventoryIndex() { return slotNumber; } @@ -111,4 +127,19 @@ public class ValidatedSlot extends Slot { public void setFilter(Predicate<ItemStack> filter) { this.filter = filter; } + + /** + * Adds a change listener to this slot. + * Does nothing if the listener is already registered. + * + * @param owner the owner of this slot + * @param listener the listener + * @throws NullPointerException if either parameter is null + * @since 3.0.0 + */ + public void addChangeListener(WItemSlot owner, WItemSlot.ChangeListener listener) { + Objects.requireNonNull(owner, "owner"); + Objects.requireNonNull(listener, "listener"); + listeners.put(owner, listener); + } }
\ No newline at end of file diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java index 2aee0e7..4ef0056 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java @@ -1,7 +1,10 @@ package io.github.cottonmc.cotton.gui.widget; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.function.Predicate; import io.github.cottonmc.cotton.gui.GuiDescription; @@ -18,6 +21,41 @@ import net.minecraft.screen.slot.SlotActionType; import javax.annotation.Nullable; +/** + * A widget that displays an item that can be interacted with. + * + * <p>Item slot widgets can contain multiple visual slots themselves. + * For example, a slot widget might be 5x3 with 15 visual slots in total. + * + * <p>Item slots are handled with so-called peers in the background. + * They are instances of {@link ValidatedSlot} that handle the interactions + * between the player and the widget. + * + * <h2>Filters</h2> + * Item slots can have filters that check whether a player is allowed to insert an item or not. + * The filter can be set with {@link #setFilter(Predicate)}. For example: + * + * <pre> + * {@code + * // Only sand in this slot! + * slot.setFilter(stack -> stack.getItem() == Items.SAND); + * } + * </pre> + * + * <h2>Listeners</h2> + * Slot change listeners are instances of {@link WItemSlot.ChangeListener} that can handle changes + * to item stacks in slots. For example: + * + * <pre> + * {@code + * slot.addChangeListener((slot, inventory, index, stack) -> { + * if (stack.isEmpty() || stack.getCount() < stack.getMaxCount()) { + * System.out.println("I'm not full yet!"); + * } + * }); + * } + * </pre> + */ public class WItemSlot extends WWidget { private static final Predicate<ItemStack> DEFAULT_FILTER = stack -> true; private final List<ValidatedSlot> peers = new ArrayList<>(); @@ -34,6 +72,7 @@ public class WItemSlot extends WWidget { private boolean takingAllowed = true; private int focusedSlot = -1; private Predicate<ItemStack> filter = DEFAULT_FILTER; + private final Set<ChangeListener> listeners = new HashSet<>(); public WItemSlot(Inventory inventory, int startIndex, int slotsWide, int slotsHigh, boolean big) { this.inventory = inventory; @@ -203,6 +242,9 @@ public class WItemSlot extends WWidget { slot.setInsertingAllowed(insertingAllowed); slot.setTakingAllowed(takingAllowed); slot.setFilter(filter); + for (ChangeListener listener : listeners) { + slot.addChangeListener(this, listener); + } peers.add(slot); host.addSlotPeer(slot); index++; @@ -310,4 +352,39 @@ public class WItemSlot extends WWidget { return focusedSlot >= 0 ? this : null; } } -}
\ No newline at end of file + + /** + * Adds a change listener to this slot. + * Does nothing if the listener is already registered. + * + * @param listener the added listener + * @throws NullPointerException if the listener is null + * @since 3.0.0 + */ + public void addChangeListener(ChangeListener listener) { + Objects.requireNonNull(listener, "listener"); + listeners.add(listener); + + for (ValidatedSlot peer : peers) { + peer.addChangeListener(this, listener); + } + } + + /** + * A listener for changes in an item slot. + * + * @since 3.0.0 + */ + @FunctionalInterface + public interface ChangeListener { + /** + * Handles a changed item stack in an item slot. + * + * @param slot the item slot widget + * @param inventory the item inventory of the slot + * @param index the index of the slot in the inventory + * @param stack the changed item stack + */ + void onStackChanged(WItemSlot slot, Inventory inventory, int index, ItemStack stack); + } +} |