From a4bb001575a802acebdbbeecb323e1949f8cdffe Mon Sep 17 00:00:00 2001 From: Juuxel <6596629+Juuxel@users.noreply.github.com> Date: Tue, 4 Aug 2020 20:25:42 +0300 Subject: Add slot change listeners, document WItemSlot --- .../github/cottonmc/cotton/gui/ValidatedSlot.java | 31 +++++++++ .../cottonmc/cotton/gui/widget/WItemSlot.java | 79 +++++++++++++++++++++- 2 files changed, 109 insertions(+), 1 deletion(-) (limited to 'src/main') 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 filter; + protected final Multimap 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 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. + * + *

Item slot widgets can contain multiple visual slots themselves. + * For example, a slot widget might be 5x3 with 15 visual slots in total. + * + *

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. + * + *

Filters

+ * 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: + * + *
+ * {@code
+ * // Only sand in this slot!
+ * slot.setFilter(stack -> stack.getItem() == Items.SAND);
+ * }
+ * 
+ * + *

Listeners

+ * Slot change listeners are instances of {@link WItemSlot.ChangeListener} that can handle changes + * to item stacks in slots. For example: + * + *
+ * {@code
+ * slot.addChangeListener((slot, inventory, index, stack) -> {
+ *     if (stack.isEmpty() || stack.getCount() < stack.getMaxCount()) {
+ *         System.out.println("I'm not full yet!");
+ *     }
+ * });
+ * }
+ * 
+ */ public class WItemSlot extends WWidget { private static final Predicate DEFAULT_FILTER = stack -> true; private final List peers = new ArrayList<>(); @@ -34,6 +72,7 @@ public class WItemSlot extends WWidget { private boolean takingAllowed = true; private int focusedSlot = -1; private Predicate filter = DEFAULT_FILTER; + private final Set 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); + } +} -- cgit