Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add input/output filter + weaken WPlayerInvPanel's components' protection #209

Merged
merged 8 commits into from
Sep 9, 2023
16 changes: 8 additions & 8 deletions gradle.properties
Luligabi1 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.jvmargs = -Xmx1G

# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.20
yarn_mappings=1.20+build.1
loader_version=0.14.21
minecraft_version = 1.20.1
yarn_mappings = 1.20.1+build.10
loader_version = 0.14.21

# Mod Properties
mod_version = 8.0.2
maven_group = io.github.cottonmc
archives_base_name = LibGui

# Dependencies
fabric_version=0.83.0+1.20
jankson_version=6.0.0+j1.2.3
modmenu_version=7.0.1
libninepatch_version=1.2.0
fabric_version = 0.86.1+1.20.1
jankson_version = 6.0.0+j1.2.3
modmenu_version = 7.0.1
libninepatch_version = 1.2.0
53 changes: 47 additions & 6 deletions src/main/java/io/github/cottonmc/cotton/gui/ValidatedSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

public class ValidatedSlot extends Slot {
/**
* The default {@linkplain #setFilter(Predicate) item filter} that allows all items.
* The default {@linkplain #setInputFilter(Predicate) item filter} that allows all items.
Luligabi1 marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 5.1.1
*/
Expand All @@ -24,7 +24,8 @@ public class ValidatedSlot extends Slot {
private final int slotNumber;
private boolean insertingAllowed = true;
private boolean takingAllowed = true;
private Predicate<ItemStack> filter = DEFAULT_ITEM_FILTER;
private Predicate<ItemStack> inputFilter = DEFAULT_ITEM_FILTER;
private Predicate<ItemStack> outputFilter = DEFAULT_ITEM_FILTER;
protected final Multimap<WItemSlot, WItemSlot.ChangeListener> listeners = HashMultimap.create();
private boolean visible = true;

Expand All @@ -36,12 +37,12 @@ public ValidatedSlot(Inventory inventory, int index, int x, int y) {

@Override
public boolean canInsert(ItemStack stack) {
return insertingAllowed && inventory.isValid(slotNumber, stack) && filter.test(stack);
return insertingAllowed && inventory.isValid(slotNumber, stack) && inputFilter.test(stack);
}

@Override
public boolean canTakeItems(PlayerEntity player) {
return takingAllowed && inventory.canPlayerUse(player);
return takingAllowed && inventory.canPlayerUse(player) && outputFilter.test(getStack());
}

@Override
Expand Down Expand Up @@ -115,24 +116,64 @@ public void setTakingAllowed(boolean takingAllowed) {
this.takingAllowed = takingAllowed;
}

/**
* Gets the item stack input filter of this slot.
*
* @return the item input filter
*/
public Predicate<ItemStack> getInputFilter() {
return inputFilter;
}

/**
* Sets the item stack input filter of this slot.
*
* @param inputFilter the new item input filter
*/
public void setInputFilter(Predicate<ItemStack> inputFilter) {
this.inputFilter = inputFilter;
}

/**
* Gets the item stack output filter of this slot.
*
* @return the item output filter
*/
public Predicate<ItemStack> getOutputFilter() {
return outputFilter;
}

/**
* Sets the item stack output filter of this slot.
*
* @param outputFilter the new item output filter
*/
public void setOutputFilter(Predicate<ItemStack> outputFilter) {
this.outputFilter = outputFilter;
}

/**
* Gets the item stack filter of this slot.
*
* @return the item filter
* @deprecated Replaced by {@link #getInputFilter()}
* @since 2.0.0
*/
@Deprecated
public Predicate<ItemStack> getFilter() {
return filter;
return inputFilter;
}

/**
* Sets the item stack filter of this slot.
*
* @param filter the new item filter
* @deprecated Replaced by {@link #setInputFilter(Predicate)}
* @since 2.0.0
*/
@Deprecated
public void setFilter(Predicate<ItemStack> filter) {
this.filter = filter;
setInputFilter(filter);
}

/**
Expand Down
75 changes: 63 additions & 12 deletions src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@
* 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:
* Item slots can have filters that check whether a player is allowed to insert or take out an item or not.
* The filters can be set with {@link #setInputFilter(Predicate)} and {@link #setOutputFilter(Predicate)}. For example:
*
* <pre>
* {@code
* // Only sand in this slot!
* slot.setFilter(stack -> stack.getItem() == Items.SAND);
* // Only sand can be placed on this slot
* slot.setInputFilter(stack -> stack.isOf(Items.SAND));
*
* // Everything except glass can be taken out of this slot
* slot.setOutputFilter(stack -> !stack.isOf(Items.GLASS));
* }
* </pre>
*
Expand Down Expand Up @@ -94,7 +97,8 @@ public class WItemSlot extends WWidget {
private boolean takingAllowed = true;
private int focusedSlot = -1;
private int hoveredSlot = -1;
private Predicate<ItemStack> filter = ValidatedSlot.DEFAULT_ITEM_FILTER;
private Predicate<ItemStack> inputFilter = ValidatedSlot.DEFAULT_ITEM_FILTER;
private Predicate<ItemStack> outputFilter = ValidatedSlot.DEFAULT_ITEM_FILTER;
private final Set<ChangeListener> listeners = new HashSet<>();
private final FocusModel<Integer> focusModel = new FocusModel<>() {
@Override
Expand Down Expand Up @@ -338,7 +342,8 @@ public void validate(GuiDescription host) {
ValidatedSlot slot = createSlotPeer(inventory, index, this.getAbsoluteX() + (x * 18) + 1, this.getAbsoluteY() + (y * 18) + 1);
slot.setInsertingAllowed(insertingAllowed);
slot.setTakingAllowed(takingAllowed);
slot.setFilter(filter);
slot.setInputFilter(inputFilter);
slot.setOutputFilter(outputFilter);
for (ChangeListener listener : listeners) {
slot.addChangeListener(this, listener);
}
Expand Down Expand Up @@ -400,29 +405,75 @@ public void setBackgroundPainter(@Nullable BackgroundPainter painter) {
this.backgroundPainter = painter;
}

/**
* Gets the item stack input filter of this slot.
*
* @return the item input filter
*/
public Predicate<ItemStack> getInputFilter() {
return inputFilter;
}

/**
* Sets the item input filter of this item slot.
*
* @param inputFilter the new item input filter
* @return this item slot
*/
public WItemSlot setInputFilter(Predicate<ItemStack> inputFilter) {
this.inputFilter = inputFilter;
for (ValidatedSlot peer : peers) {
peer.setInputFilter(inputFilter);
}
return this;
}

/**
* Gets the item stack output filter of this slot.
*
* @return the item output filter
*/
public Predicate<ItemStack> getOutputFilter() {
return outputFilter;
}

/**
* Sets the item output filter of this item slot.
*
* @param outputFilter the new item output filter
* @return this item slot
*/
public WItemSlot setOutputFilter(Predicate<ItemStack> outputFilter) {
this.outputFilter = outputFilter;
for (ValidatedSlot peer : peers) {
peer.setOutputFilter(outputFilter);
}
return this;
}

/**
* Gets the item filter of this item slot.
*
* @return the item filter
* @deprecated Replaced by {@link #getInputFilter()}
* @since 2.0.0
*/
@Deprecated
public Predicate<ItemStack> getFilter() {
Luligabi1 marked this conversation as resolved.
Show resolved Hide resolved
return filter;
return inputFilter;
}

/**
* Sets the item filter of this item slot.
*
* @param filter the new item filter
* @return this item slot
* @deprecated Replaced by {@link #setInputFilter(Predicate)}
* @since 2.0.0
*/
@Deprecated
public WItemSlot setFilter(Predicate<ItemStack> filter) {
this.filter = filter;
for (ValidatedSlot peer : peers) {
peer.setFilter(filter);
}
return this;
return setInputFilter(filter);
}

@Environment(EnvType.CLIENT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,38 @@
import net.minecraft.text.Text;

import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.SyncedGuiDescription;
import io.github.cottonmc.cotton.gui.client.BackgroundPainter;
import io.github.cottonmc.cotton.gui.impl.client.NarrationMessages;
import org.jetbrains.annotations.Nullable;

/**
* A player inventory widget that has a visually separate hotbar.
*
* @see SyncedGuiDescription#createPlayerInventoryPanel()
*/
public class WPlayerInvPanel extends WPlainPanel {
private final WItemSlot inv;
private final WItemSlot hotbar;
/**
* A 9 by 3 {@link WItemSlot} that represents the player's inventory.
*
* @see PlayerInventory
*/
protected final WItemSlot inventory;
/**
* A 9 by 1 {@link WItemSlot} that represents the player's hotbar.
*
* @see PlayerInventory
*/
protected final WItemSlot hotbar;
/**
* The label seen above {@link WPlayerInvPanel#inventory}.
*
* <p> In vanilla and {@link WPlayerInvPanel#WPlayerInvPanel(PlayerInventory)}, this label is always 'Inventory'
*
* @see #createInventoryLabel(PlayerInventory)
*/
@Nullable
private final WWidget label;
protected final WWidget label;

/**
* Constructs a player inventory panel with a label.
Expand Down Expand Up @@ -55,14 +75,14 @@ public WPlayerInvPanel(PlayerInventory playerInventory, @Nullable WWidget label)
y += label.getHeight();
}

inv = WItemSlot.ofPlayerStorage(playerInventory);
inventory = WItemSlot.ofPlayerStorage(playerInventory);
hotbar = new WItemSlot(playerInventory, 0, 9, 1, false) {
@Override
protected Text getNarrationName() {
return NarrationMessages.Vanilla.HOTBAR;
}
};
this.add(inv, 0, y);
this.add(inventory, 0, y);
this.add(hotbar, 0, y + 58);
}

Expand Down Expand Up @@ -94,7 +114,7 @@ public static WLabel createInventoryLabel(PlayerInventory playerInventory) {
@Override
public WPanel setBackgroundPainter(BackgroundPainter painter) {
super.setBackgroundPainter(null);
inv.setBackgroundPainter(painter);
inventory.setBackgroundPainter(painter);
hotbar.setBackgroundPainter(painter);
return this;
}
Expand Down
16 changes: 5 additions & 11 deletions src/testMod/java/io/github/cottonmc/test/TestDescription.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,22 @@ public TestDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory pl

root.add(buttonB, 5, 3, 4, 1);
TextureIcon testIcon = new TextureIcon(new Texture(new Identifier("libgui-test", "icon.png")));


root.add(new WButton(testIcon, Text.literal("Button C")), 0, 5, 4, 1);
Luligabi1 marked this conversation as resolved.
Show resolved Hide resolved
root.add(new WButton(Text.literal("Button D")), 5, 5, 4, 1);
root.add(new WTextField(Text.literal("Type something...")).setMaxLength(64), 0, 7, 5, 1);

root.add(new WLabel(Text.literal("Large slot:")), 0, 9);
root.add(WItemSlot.outputOf(blockInventory, 0), 4, 9);
root.add(new WLabel(Text.literal("Large Glass-only output:")), 0, 9);
root.add(WItemSlot.outputOf(blockInventory, 0).setOutputFilter(stack -> stack.isOf(Items.GLASS)), 4, 9);

root.add(WItemSlot.of(blockInventory, 7).setIcon(new TextureIcon(new Identifier("libgui-test", "saddle.png"))), 7, 9);
root.add(WItemSlot.of(blockInventory, 7).setIcon(new TextureIcon(new Identifier("libgui-test", "saddle.png"))).setInputFilter(stack -> stack.isOf(Items.SADDLE)), 7, 10);

root.add(createPlayerInventoryPanel(), 0, 11);
System.out.println(root.toString());

this.getRootPanel().validate(this);

getRootPanel().streamChildren()
.forEach(child -> {
if (child instanceof WItemSlot wis) {
// Prevent apples from entering the item slots
wis.setFilter(stack -> !stack.isOf(Items.APPLE));
}
});

ScreenNetworking.of(this, NetworkSide.SERVER).receive(TEST_MESSAGE, buf -> {
System.out.println("Received on the server!");
});
Expand Down
Loading